summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp3
-rw-r--r--apct-tests/perftests/autofill/Android.bp1
-rw-r--r--apct-tests/perftests/autofill/AndroidManifest.xml5
-rw-r--r--apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java2
-rw-r--r--apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java10
-rw-r--r--apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java10
-rw-r--r--apct-tests/perftests/contentcapture/src/android/view/contentcapture/AbstractContentCapturePerfTestCase.java2
-rw-r--r--apct-tests/perftests/contentcapture/src/android/view/contentcapture/LoginTest.java3
-rw-r--r--apct-tests/perftests/core/Android.bp3
-rw-r--r--apct-tests/perftests/core/AndroidTest.xml27
-rw-r--r--apct-tests/perftests/multiuser/Android.bp1
-rw-r--r--apct-tests/perftests/multiuser/AndroidManifest.xml3
-rw-r--r--apct-tests/perftests/multiuser/AndroidTest.xml34
-rw-r--r--apct-tests/perftests/windowmanager/Android.bp1
-rw-r--r--apex/jobscheduler/framework/java/android/app/AlarmManager.java8
-rw-r--r--apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java230
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java2
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java13
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobStore.java19
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java10
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java23
-rw-r--r--apex/statsd/aidl/Android.bp1
-rw-r--r--apex/statsd/aidl/android/os/IStatsCompanionService.aidl11
-rw-r--r--apex/statsd/aidl/android/os/IStatsd.aidl7
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java66
-rw-r--r--api/current.txt28
-rw-r--r--api/module-lib-current.txt13
-rwxr-xr-xapi/system-current.txt1
-rw-r--r--api/test-current.txt2
-rw-r--r--cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl1
-rw-r--r--cmds/idmap2/libidmap2/ResourceMapping.cpp7
-rw-r--r--cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h4
-rw-r--r--cmds/idmap2/tests/R.h36
-rw-r--r--cmds/idmap2/tests/ResourceMappingTests.cpp18
-rw-r--r--cmds/idmap2/tests/TestConstants.h8
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-no-name-static.apkbin3477 -> 3485 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-no-name.apkbin3389 -> 3393 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-shared.apkbin3757 -> 3757 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-static-1.apkbin3469 -> 3477 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay-static-2.apkbin3469 -> 3477 bytes
-rw-r--r--cmds/idmap2/tests/data/overlay/overlay.apkbin3489 -> 3489 bytes
-rw-r--r--cmds/idmap2/tests/data/signature-overlay/signature-overlay.apkbin1315 -> 1299 bytes
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml1
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apkbin1827 -> 1907 bytes
-rw-r--r--cmds/idmap2/tests/data/system-overlay/system-overlay.apkbin1319 -> 1387 bytes
-rw-r--r--cmds/idmap2/tests/data/target/res/values/overlayable.xml4
-rw-r--r--cmds/idmap2/tests/data/target/res/values/values.xml1
-rw-r--r--cmds/idmap2/tests/data/target/target-no-overlayable.apkbin2311 -> 2391 bytes
-rw-r--r--cmds/idmap2/tests/data/target/target.apkbin5097 -> 5201 bytes
-rw-r--r--cmds/screencap/screencap.cpp31
-rw-r--r--cmds/statsd/Android.bp9
-rw-r--r--cmds/statsd/src/StatsLogProcessor.cpp76
-rw-r--r--cmds/statsd/src/StatsLogProcessor.h30
-rw-r--r--cmds/statsd/src/StatsService.cpp32
-rw-r--r--cmds/statsd/src/StatsService.h5
-rw-r--r--cmds/statsd/src/atoms.proto2
-rw-r--r--cmds/statsd/src/config/ConfigManager.cpp2
-rw-r--r--cmds/statsd/src/config/ConfigManager.h2
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp4
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.h2
-rw-r--r--cmds/statsd/src/packages/PackageInfoListener.h2
-rw-r--r--cmds/statsd/src/packages/UidMap.h1
-rw-r--r--cmds/statsd/tests/LogEntryMatcher_test.cpp3
-rw-r--r--cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp264
-rw-r--r--cmds/telecom/src/com/android/commands/telecom/Telecom.java10
-rw-r--r--cmds/uiautomator/api/current.txt389
-rw-r--r--cmds/uiautomator/api/removed.txt1
-rw-r--r--cmds/uiautomator/library/Android.bp30
-rw-r--r--cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java6
-rw-r--r--cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java10
-rw-r--r--core/java/android/animation/AnimatorSet.java20
-rw-r--r--core/java/android/app/Activity.java2
-rw-r--r--core/java/android/app/ActivityManagerInternal.java2
-rw-r--r--core/java/android/app/Dialog.java15
-rw-r--r--core/java/android/app/WallpaperManager.java5
-rw-r--r--core/java/android/app/WindowConfiguration.java7
-rw-r--r--core/java/android/app/WindowContext.java2
-rw-r--r--core/java/android/app/backup/BackupAgent.java2
-rw-r--r--core/java/android/app/usage/UsageStats.java5
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java2
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java16
-rw-r--r--core/java/android/companion/BluetoothDeviceFilter.java10
-rw-r--r--core/java/android/content/ContentProvider.java5
-rw-r--r--core/java/android/content/ContentResolver.java2
-rw-r--r--core/java/android/content/Context.java20
-rw-r--r--core/java/android/content/SyncStatusInfo.java2
-rw-r--r--core/java/android/content/pm/PackageParser.java6
-rw-r--r--core/java/android/content/pm/dex/DexMetadataHelper.java4
-rw-r--r--core/java/android/content/res/Configuration.java2
-rw-r--r--core/java/android/database/sqlite/SQLiteDatabase.java2
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java4
-rw-r--r--core/java/android/hardware/hdmi/HdmiControlManager.java34
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java2
-rw-r--r--core/java/android/net/ConnectivityManager.java10
-rw-r--r--core/java/android/net/NetworkAgent.java3
-rw-r--r--core/java/android/net/NetworkState.java4
-rw-r--r--core/java/android/net/NetworkStatsHistory.java36
-rw-r--r--core/java/android/net/NetworkUtils.java31
-rw-r--r--core/java/android/net/SntpClient.java30
-rw-r--r--core/java/android/net/VpnService.java2
-rw-r--r--core/java/android/os/DropBoxManager.java2
-rw-r--r--core/java/android/os/FileUtils.java2
-rw-r--r--core/java/android/os/GraphicsEnvironment.java50
-rw-r--r--core/java/android/os/Looper.java196
-rw-r--r--core/java/android/os/OWNERS2
-rw-r--r--core/java/android/os/Parcelable.java3
-rw-r--r--core/java/android/os/TEST_MAPPING10
-rw-r--r--core/java/android/os/ZygoteProcess.java42
-rw-r--r--[-rwxr-xr-x]core/java/android/provider/Settings.java62
-rw-r--r--core/java/android/security/net/config/NetworkSecurityConfig.java2
-rw-r--r--core/java/android/service/notification/NotificationStats.java5
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java29
-rw-r--r--core/java/android/text/format/DateIntervalFormat.java2
-rw-r--r--core/java/android/util/proto/ProtoInputStream.java6
-rw-r--r--core/java/android/util/proto/ProtoOutputStream.java8
-rw-r--r--core/java/android/view/Display.java13
-rw-r--r--core/java/android/view/FocusFinder.java19
-rw-r--r--core/java/android/view/GestureDetector.java10
-rw-r--r--core/java/android/view/LayoutInflater.java4
-rw-r--r--core/java/android/view/Surface.java6
-rw-r--r--core/java/android/view/SurfaceControl.java351
-rw-r--r--core/java/android/view/View.java8
-rw-r--r--core/java/android/view/ViewConfiguration.java6
-rw-r--r--core/java/android/view/ViewRootImpl.java36
-rw-r--r--core/java/android/view/Window.java5
-rw-r--r--core/java/android/view/WindowManager.java13
-rw-r--r--core/java/android/view/WindowManagerImpl.java18
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java4
-rw-r--r--core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl13
-rw-r--r--core/java/android/view/inputmethod/InlineSuggestionsRequest.java20
-rw-r--r--core/java/android/view/inputmethod/InlineSuggestionsResponse.java38
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java3
-rw-r--r--core/java/android/widget/AbsListView.java3
-rw-r--r--core/java/android/widget/Gallery.java3
-rw-r--r--core/java/android/widget/RemoteViewsAdapter.java4
-rwxr-xr-xcore/java/android/widget/SearchView.java2
-rw-r--r--core/java/android/widget/TEST_MAPPING39
-rw-r--r--core/java/android/widget/inline/InlineContentView.java2
-rw-r--r--core/java/android/widget/inline/TEST_MAPPING15
-rw-r--r--core/java/com/android/internal/app/LocalePicker.java64
-rw-r--r--core/java/com/android/internal/infra/AbstractRemoteService.java2
-rw-r--r--core/java/com/android/internal/os/ChildZygoteInit.java2
-rw-r--r--core/java/com/android/internal/os/OWNERS2
-rw-r--r--core/java/com/android/internal/os/Zygote.java4
-rw-r--r--core/java/com/android/internal/os/ZygoteArguments.java10
-rw-r--r--core/java/com/android/internal/os/ZygoteConnection.java12
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java5
-rw-r--r--core/java/com/android/internal/os/ZygoteServer.java2
-rw-r--r--core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java7
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java5
-rw-r--r--core/java/com/android/internal/telephony/ITelephonyRegistry.aidl6
-rw-r--r--core/java/com/android/server/SystemConfig.java36
-rw-r--r--core/jni/OWNERS2
-rw-r--r--core/jni/android_hardware_input_InputApplicationHandle.cpp23
-rw-r--r--core/jni/android_hardware_input_InputApplicationHandle.h3
-rw-r--r--core/jni/android_hardware_input_InputWindowHandle.cpp4
-rw-r--r--core/jni/android_media_AudioSystem.cpp2
-rw-r--r--core/jni/android_net_NetUtils.cpp6
-rw-r--r--core/jni/android_os_Debug.cpp2
-rw-r--r--core/jni/android_os_Parcel.cpp2
-rw-r--r--core/jni/android_util_Binder.cpp2
-rw-r--r--core/jni/android_view_InputEventSender.cpp5
-rw-r--r--core/jni/android_view_InputQueue.cpp4
-rw-r--r--core/jni/android_view_MotionEvent.cpp17
-rw-r--r--core/jni/android_view_SurfaceControl.cpp179
-rw-r--r--core/proto/android/app/settings_enums.proto5
-rw-r--r--core/proto/android/providers/settings/global.proto10
-rw-r--r--core/proto/android/server/alarm/alarmmanagerservice.proto5
-rw-r--r--core/proto/android/server/appstatetracker.proto14
-rw-r--r--core/proto/android/server/windowmanagerservice.proto3
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/res/res/drawable-car/car_dialog_button_background.xml15
-rw-r--r--core/res/res/values-af/strings.xml3
-rw-r--r--core/res/res/values-am/strings.xml3
-rw-r--r--core/res/res/values-ar/strings.xml3
-rw-r--r--core/res/res/values-as/strings.xml3
-rw-r--r--core/res/res/values-az/strings.xml3
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml3
-rw-r--r--core/res/res/values-be/strings.xml7
-rw-r--r--core/res/res/values-bg/strings.xml3
-rw-r--r--core/res/res/values-bn/strings.xml3
-rw-r--r--core/res/res/values-bs/strings.xml3
-rw-r--r--core/res/res/values-ca/strings.xml4
-rw-r--r--core/res/res/values-cs/strings.xml3
-rw-r--r--core/res/res/values-da/strings.xml3
-rw-r--r--core/res/res/values-de/strings.xml3
-rw-r--r--core/res/res/values-el/strings.xml3
-rw-r--r--core/res/res/values-en-rAU/strings.xml3
-rw-r--r--core/res/res/values-en-rCA/strings.xml3
-rw-r--r--core/res/res/values-en-rGB/strings.xml3
-rw-r--r--core/res/res/values-en-rIN/strings.xml3
-rw-r--r--core/res/res/values-es-rUS/strings.xml3
-rw-r--r--core/res/res/values-es/strings.xml3
-rw-r--r--core/res/res/values-et/strings.xml3
-rw-r--r--core/res/res/values-eu/strings.xml13
-rw-r--r--core/res/res/values-fa/strings.xml7
-rw-r--r--core/res/res/values-fi/strings.xml3
-rw-r--r--core/res/res/values-fr-rCA/strings.xml3
-rw-r--r--core/res/res/values-fr/strings.xml5
-rw-r--r--core/res/res/values-gl/strings.xml3
-rw-r--r--core/res/res/values-gu/strings.xml3
-rw-r--r--core/res/res/values-hi/strings.xml3
-rw-r--r--core/res/res/values-hr/strings.xml3
-rw-r--r--core/res/res/values-hu/strings.xml3
-rw-r--r--core/res/res/values-hy/strings.xml3
-rw-r--r--core/res/res/values-in/strings.xml3
-rw-r--r--core/res/res/values-is/strings.xml3
-rw-r--r--core/res/res/values-it/strings.xml3
-rw-r--r--core/res/res/values-iw/strings.xml2
-rw-r--r--core/res/res/values-ja/strings.xml3
-rw-r--r--core/res/res/values-ka/strings.xml3
-rw-r--r--core/res/res/values-kk/strings.xml3
-rw-r--r--core/res/res/values-km/strings.xml3
-rw-r--r--core/res/res/values-kn/strings.xml3
-rw-r--r--core/res/res/values-ko/strings.xml3
-rw-r--r--core/res/res/values-ky/strings.xml9
-rw-r--r--core/res/res/values-lo/strings.xml3
-rw-r--r--core/res/res/values-lt/strings.xml3
-rw-r--r--core/res/res/values-lv/strings.xml13
-rw-r--r--core/res/res/values-mk/strings.xml3
-rw-r--r--core/res/res/values-ml/strings.xml3
-rw-r--r--core/res/res/values-mn/strings.xml3
-rw-r--r--core/res/res/values-mr/strings.xml3
-rw-r--r--core/res/res/values-ms/strings.xml3
-rw-r--r--core/res/res/values-my/strings.xml3
-rw-r--r--core/res/res/values-nb/strings.xml3
-rw-r--r--core/res/res/values-ne/strings.xml3
-rw-r--r--core/res/res/values-nl/strings.xml35
-rw-r--r--core/res/res/values-or/strings.xml3
-rw-r--r--core/res/res/values-pa/strings.xml3
-rw-r--r--core/res/res/values-pl/strings.xml3
-rw-r--r--core/res/res/values-pt-rBR/strings.xml3
-rw-r--r--core/res/res/values-pt-rPT/strings.xml3
-rw-r--r--core/res/res/values-pt/strings.xml3
-rw-r--r--core/res/res/values-ro/strings.xml3
-rw-r--r--core/res/res/values-ru/strings.xml3
-rw-r--r--core/res/res/values-si/strings.xml3
-rw-r--r--core/res/res/values-sk/strings.xml3
-rw-r--r--core/res/res/values-sl/strings.xml3
-rw-r--r--core/res/res/values-sq/strings.xml3
-rw-r--r--core/res/res/values-sr/strings.xml3
-rw-r--r--core/res/res/values-sv/strings.xml3
-rw-r--r--core/res/res/values-sw/strings.xml3
-rw-r--r--core/res/res/values-ta/strings.xml3
-rw-r--r--core/res/res/values-te/strings.xml3
-rw-r--r--core/res/res/values-th/strings.xml3
-rw-r--r--core/res/res/values-tl/strings.xml3
-rw-r--r--core/res/res/values-tr/strings.xml3
-rw-r--r--core/res/res/values-uk/strings.xml3
-rw-r--r--core/res/res/values-ur/strings.xml3
-rw-r--r--core/res/res/values-uz/strings.xml5
-rw-r--r--core/res/res/values-vi/strings.xml3
-rw-r--r--core/res/res/values-zh-rCN/strings.xml3
-rw-r--r--core/res/res/values-zh-rHK/strings.xml3
-rw-r--r--core/res/res/values-zh-rTW/strings.xml3
-rw-r--r--core/res/res/values-zu/strings.xml3
-rw-r--r--core/res/res/values/config.xml8
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/sysprop/Android.bp21
-rw-r--r--core/sysprop/LocalizationProperties.sysprop24
-rw-r--r--core/sysprop/api/com.android.sysprop.localization-current.txt9
-rw-r--r--core/sysprop/api/com.android.sysprop.localization-latest.txt9
-rw-r--r--core/tests/bugreports/Android.bp6
-rw-r--r--core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java128
-rw-r--r--core/tests/coretests/apks/install/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_bad_dex/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_decl_perm/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_loc_auto/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_loc_internal/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_use_perm_good/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_uses_feature/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/install_verifier_good/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/keyset/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/version/res/values/strings.xml4
-rw-r--r--core/tests/coretests/apks/version_nosys/res/values/strings.xml4
-rw-r--r--core/tests/coretests/src/android/os/VintfObjectTest.java2
-rw-r--r--data/keyboards/Generic.kl1
-rw-r--r--data/keyboards/Vendor_2dc8_Product_6101.kl55
-rw-r--r--graphics/java/android/graphics/HardwareRenderer.java31
-rw-r--r--graphics/proto/Android.bp6
-rw-r--r--graphics/proto/updatable_driver.proto (renamed from graphics/proto/game_driver.proto)12
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java30
-rw-r--r--libs/androidfw/Android.bp2
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h4
-rw-r--r--libs/androidfw/libandroidfw_blocklist.txt (renamed from libs/androidfw/libandroidfw_blacklist.txt)0
-rw-r--r--libs/hwui/AutoBackendTextureRelease.cpp10
-rw-r--r--libs/hwui/AutoBackendTextureRelease.h9
-rw-r--r--libs/hwui/ColorMode.h34
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp2
-rw-r--r--libs/hwui/DeferredLayerUpdater.h2
-rw-r--r--libs/hwui/HardwareBitmapUploader.cpp4
-rw-r--r--libs/hwui/Readback.cpp2
-rw-r--r--libs/hwui/apex/jni_runtime.cpp15
-rw-r--r--libs/hwui/jni/android_graphics_HardwareRenderer.cpp13
-rw-r--r--libs/hwui/pipeline/skia/GLFunctorDrawable.cpp2
-rw-r--r--libs/hwui/pipeline/skia/LayerDrawable.cpp10
-rw-r--r--libs/hwui/pipeline/skia/LayerDrawable.h8
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp2
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp26
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.h4
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp11
-rw-r--r--libs/hwui/renderthread/CanvasContext.h4
-rw-r--r--libs/hwui/renderthread/EglManager.cpp105
-rw-r--r--libs/hwui/renderthread/EglManager.h4
-rw-r--r--libs/hwui/renderthread/IRenderPipeline.h11
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp4
-rw-r--r--libs/hwui/renderthread/RenderProxy.h3
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp6
-rw-r--r--libs/hwui/renderthread/RenderThread.h8
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp16
-rw-r--r--libs/hwui/renderthread/VulkanManager.h12
-rw-r--r--libs/hwui/tests/unit/CacheManagerTests.cpp4
-rw-r--r--libs/hwui/utils/Color.cpp22
-rw-r--r--libs/hwui/utils/Color.h1
-rw-r--r--location/java/android/location/GnssAntennaInfo.java107
-rwxr-xr-xmedia/java/android/media/AudioManager.java23
-rw-r--r--media/java/android/media/AudioRecord.java5
-rw-r--r--media/java/android/media/ExifInterface.java350
-rw-r--r--media/java/android/media/ImageReader.java12
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java11
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicyConfig.java6
-rw-r--r--media/jni/android_media_ImageReader.cpp21
-rw-r--r--media/jni/android_media_MediaPlayer.cpp2
-rw-r--r--media/jni/android_media_MediaSync.cpp2
-rw-r--r--media/jni/audioeffect/Visualizer.cpp33
-rw-r--r--media/jni/audioeffect/Visualizer.h34
-rw-r--r--media/jni/audioeffect/android_media_AudioEffect.cpp21
-rw-r--r--media/jni/audioeffect/android_media_Visualizer.cpp10
-rw-r--r--media/mca/filterfw/java/android/filterfw/core/FilterFunction.java2
-rw-r--r--media/mca/filterfw/jni/jni_native_program.cpp2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java24
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/Preconditions.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java48
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java2
-rw-r--r--non-updatable-api/current.txt28
-rw-r--r--non-updatable-api/module-lib-current.txt13
-rw-r--r--non-updatable-api/system-current.txt1
-rw-r--r--packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java10
-rw-r--r--packages/CarSystemUI/res/values/config.xml25
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java10
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java125
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java12
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java28
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java380
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java10
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java7
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java38
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java3
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarTest.java2
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java162
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java2
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediatorTest.java27
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java4
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java21
-rw-r--r--packages/SettingsLib/res/values-be/strings.xml4
-rw-r--r--packages/SettingsLib/res/values/strings.xml3
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java1
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java1
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java1
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java16
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java22
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java11
-rw-r--r--packages/SimAppDialog/Android.bp1
-rw-r--r--packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.pngbin0 -> 1766 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.pngbin0 -> 1054 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.pngbin0 -> 2215 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.pngbin0 -> 3649 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.pngbin0 -> 5029 bytes
-rw-r--r--packages/SystemUI/res/values-af/strings.xml7
-rw-r--r--packages/SystemUI/res/values-am/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml7
-rw-r--r--packages/SystemUI/res/values-as/strings.xml7
-rw-r--r--packages/SystemUI/res/values-az/strings.xml7
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml7
-rw-r--r--packages/SystemUI/res/values-be/strings.xml9
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml7
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml7
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml7
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml7
-rw-r--r--packages/SystemUI/res/values-da/strings.xml7
-rw-r--r--packages/SystemUI/res/values-de/strings.xml7
-rw-r--r--packages/SystemUI/res/values-el/strings.xml7
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml7
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml7
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml7
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml7
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml7
-rw-r--r--packages/SystemUI/res/values-es/strings.xml7
-rw-r--r--packages/SystemUI/res/values-et/strings.xml7
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml13
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml7
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml7
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml7
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml9
-rw-r--r--packages/SystemUI/res/values-in/strings.xml7
-rw-r--r--packages/SystemUI/res/values-is/strings.xml7
-rw-r--r--packages/SystemUI/res/values-it/strings.xml7
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml7
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml7
-rw-r--r--packages/SystemUI/res/values-km/strings.xml7
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml7
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml7
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml7
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml29
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml7
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml7
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml7
-rw-r--r--packages/SystemUI/res/values-my/strings.xml7
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml7
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml31
-rw-r--r--packages/SystemUI/res/values-or/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml9
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml7
-rw-r--r--packages/SystemUI/res/values-si/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml7
-rw-r--r--packages/SystemUI/res/values-te/strings.xml7
-rw-r--r--packages/SystemUI/res/values-th/strings.xml7
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml7
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml7
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml7
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml7
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml7
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml7
-rw-r--r--packages/SystemUI/res/values/config.xml6
-rw-r--r--packages/SystemUI/res/values/strings.xml5
-rw-r--r--packages/SystemUI/res/xml/one_handed_tutorial.xml67
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java116
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java119
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/BatteryMeterView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/DisplayIdIndexSupplier.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java161
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Recents.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java528
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java516
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java106
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt204
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SimpleNotificationListContainer.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnDismissCallbackImpl.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnDismissCallbackImpl.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewBarn.kt)22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewManager.kt240
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewManagerLogger.kt72
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnDismissCallback.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java69
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java162
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java86
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java80
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/EntryUtil.kt (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/DismissRunnable.java)26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java82
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryHelper.java42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java175
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java6
-rw-r--r--packages/Tethering/Android.bp1
-rw-r--r--packages/Tethering/AndroidManifest.xml2
-rw-r--r--packages/Tethering/proguard.flags2
-rw-r--r--packages/Tethering/src/android/net/ip/IpServer.java26
-rw-r--r--packages/Tethering/src/android/net/util/TetheringMessageBase.java2
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java6
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/Tethering.java80
-rw-r--r--packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java2
-rw-r--r--packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java54
-rw-r--r--packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java28
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java123
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java17
-rw-r--r--services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java2
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetService.java12
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java3
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteFillService.java3
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java8
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java10
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java2
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java46
-rw-r--r--services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java2
-rw-r--r--services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java39
-rw-r--r--services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java10
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java5
-rw-r--r--services/core/Android.bp1
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java1
-rw-r--r--services/core/java/com/android/server/BinderCallsStatsService.java24
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java5
-rw-r--r--services/core/java/com/android/server/BluetoothService.java12
-rw-r--r--services/core/java/com/android/server/GestureLauncherService.java43
-rw-r--r--services/core/java/com/android/server/PinnerService.java16
-rw-r--r--services/core/java/com/android/server/ServiceWatcher.java54
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java18
-rw-r--r--services/core/java/com/android/server/SystemService.java107
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java177
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java19
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java11
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java33
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java16
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java1735
-rw-r--r--services/core/java/com/android/server/am/CoreSettingsObserver.java8
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java17
-rw-r--r--services/core/java/com/android/server/appbinding/AppBindingService.java13
-rw-r--r--services/core/java/com/android/server/attention/AttentionManagerService.java12
-rwxr-xr-xservices/core/java/com/android/server/audio/AudioService.java13
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java16
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java14
-rw-r--r--services/core/java/com/android/server/camera/CameraServiceProxy.java11
-rw-r--r--services/core/java/com/android/server/clipboard/ClipboardService.java6
-rw-r--r--services/core/java/com/android/server/connectivity/PermissionMonitor.java165
-rw-r--r--services/core/java/com/android/server/content/ContentService.java19
-rw-r--r--services/core/java/com/android/server/display/ColorFade.java25
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java4
-rw-r--r--services/core/java/com/android/server/display/color/ColorDisplayService.java49
-rw-r--r--services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java119
-rw-r--r--services/core/java/com/android/server/gpu/GpuService.java78
-rw-r--r--services/core/java/com/android/server/hdmi/ActiveSourceAction.java10
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java30
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java9
-rw-r--r--services/core/java/com/android/server/infra/AbstractMasterSystemService.java9
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java10
-rw-r--r--services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java16
-rw-r--r--services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java3
-rw-r--r--services/core/java/com/android/server/location/LocationProviderProxy.java27
-rw-r--r--services/core/java/com/android/server/location/geofence/GeofenceProxy.java2
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java13
-rw-r--r--services/core/java/com/android/server/media/MediaButtonReceiverHolder.java4
-rw-r--r--services/core/java/com/android/server/media/MediaResourceMonitorService.java3
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java15
-rw-r--r--services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java7
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsCollection.java46
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsFactory.java4
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsRecorder.java2
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java12
-rw-r--r--services/core/java/com/android/server/om/IdmapManager.java34
-rw-r--r--services/core/java/com/android/server/om/OverlayActorEnforcer.java20
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java19
-rw-r--r--services/core/java/com/android/server/om/OverlayReferenceMapper.java16
-rw-r--r--services/core/java/com/android/server/om/OverlayableInfoCallback.java83
-rw-r--r--services/core/java/com/android/server/om/PackageManagerHelper.java66
-rw-r--r--services/core/java/com/android/server/os/TEST_MAPPING10
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java20
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java302
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java564
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java12
-rw-r--r--services/core/java/com/android/server/pm/PackageVerificationState.java8
-rw-r--r--services/core/java/com/android/server/pm/Settings.java12
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java9
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java1
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java13
-rw-r--r--services/core/java/com/android/server/pm/dex/OWNERS2
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java432
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionSettings.java12
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java13
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java33
-rw-r--r--services/core/java/com/android/server/power/ShutdownCheckPoints.java50
-rw-r--r--services/core/java/com/android/server/power/ShutdownThread.java6
-rw-r--r--services/core/java/com/android/server/role/RoleManagerService.java8
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerService.java6
-rw-r--r--services/core/java/com/android/server/search/SearchManagerService.java22
-rw-r--r--services/core/java/com/android/server/slice/SliceManagerService.java11
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java13
-rw-r--r--services/core/java/com/android/server/storage/StorageUserConnection.java48
-rw-r--r--services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java13
-rw-r--r--services/core/java/com/android/server/textservices/TextServicesManagerService.java13
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java23
-rwxr-xr-xservices/core/java/com/android/server/tv/TvInputManagerService.java8
-rw-r--r--services/core/java/com/android/server/twilight/TwilightService.java3
-rw-r--r--services/core/java/com/android/server/vr/VrManagerService.java10
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java93
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java23
-rw-r--r--services/core/java/com/android/server/wm/AppTransition.java41
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java4
-rw-r--r--services/core/java/com/android/server/wm/ConfigurationContainer.java81
-rw-r--r--services/core/java/com/android/server/wm/DisplayArea.java11
-rw-r--r--services/core/java/com/android/server/wm/DisplayAreaPolicy.java17
-rw-r--r--services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java103
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java31
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java29
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java8
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java19
-rw-r--r--services/core/java/com/android/server/wm/Task.java165
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java31
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java77
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java251
-rw-r--r--services/core/jni/com_android_server_fingerprint_FingerprintService.cpp2
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp20
-rw-r--r--services/core/jni/stats/PowerStatsPuller.cpp15
-rw-r--r--services/core/jni/stats/SubsystemSleepStatePuller.cpp56
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java13
-rw-r--r--services/midi/java/com/android/server/midi/MidiService.java7
-rw-r--r--services/print/java/com/android/server/print/PrintManagerService.java9
-rw-r--r--services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java7
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java106
-rw-r--r--services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java100
-rw-r--r--services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java81
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java20
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java123
-rw-r--r--services/tests/servicestests/src/com/android/server/job/JobSetTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt10
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java88
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java53
-rw-r--r--services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt6
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java39
-rw-r--r--services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java132
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java27
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java74
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java55
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java40
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java30
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java25
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java10
-rw-r--r--services/usage/java/com/android/server/usage/AppTimeLimitController.java4
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java17
-rw-r--r--services/usb/java/com/android/server/usb/UsbAlsaManager.java32
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java28
-rw-r--r--services/usb/java/com/android/server/usb/UsbHostManager.java40
-rw-r--r--services/usb/java/com/android/server/usb/UsbPortManager.java2
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java48
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java4
-rw-r--r--telecomm/TEST_MAPPING8
-rwxr-xr-xtelecomm/java/android/telecom/Call.java18
-rw-r--r--telecomm/java/android/telecom/Conference.java10
-rwxr-xr-xtelecomm/java/android/telecom/Connection.java14
-rwxr-xr-xtelecomm/java/android/telecom/ConnectionService.java17
-rwxr-xr-xtelecomm/java/android/telecom/InCallAdapter.java4
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java23
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl2
-rw-r--r--telephony/api/system-current.txt1
-rw-r--r--telephony/common/android/telephony/LocationAccessPolicy.java6
-rw-r--r--telephony/common/com/android/internal/telephony/TelephonyPermissions.java14
-rw-r--r--telephony/common/com/google/android/mms/pdu/PduComposer.java2
-rwxr-xr-xtelephony/common/com/google/android/mms/pdu/PduPersister.java10
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java7
-rw-r--r--telephony/java/android/telephony/CellLocation.java17
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthNr.java2
-rw-r--r--telephony/java/android/telephony/MbmsDownloadSession.java2
-rw-r--r--telephony/java/android/telephony/PreciseDataConnectionState.java159
-rw-r--r--telephony/java/android/telephony/SmsManager.java139
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java7
-rw-r--r--telephony/java/android/telephony/TelephonyFrameworkInitializer.java6
-rw-r--r--telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java6
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java22
-rwxr-xr-xtelephony/java/android/telephony/ims/ImsCallSession.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsReasonInfo.java197
-rw-r--r--telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java12
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java4
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java4
-rw-r--r--telephony/java/android/telephony/mbms/MbmsTempFileProvider.java2
-rw-r--r--telephony/java/com/android/ims/internal/IImsCallSession.aidl4
-rw-r--r--telephony/java/com/android/ims/internal/IImsConfig.aidl8
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/SmsMessage.java4
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SmsMessage.java4
-rw-r--r--tests/BlobStoreTestUtils/src/com/android/utils/blob/FakeBlobData.java (renamed from tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java)8
-rw-r--r--tests/BootImageProfileTest/OWNERS4
-rw-r--r--tests/FlickerTests/Android.bp1
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt153
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.kt446
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.kt190
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.kt156
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/NonRotationTestBase.kt44
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/RotationTestBase.kt79
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt19
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt13
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt83
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt84
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt99
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt129
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ImeAssertions.kt102
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt92
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt103
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt63
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt109
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/pip/EnterPipTest.kt121
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipTestBase.kt60
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToAppTest.kt104
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToHomeTest.kt112
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt118
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt161
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt109
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt266
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt147
-rw-r--r--tests/LocalizationTest/Android.bp41
-rw-r--r--tests/LocalizationTest/AndroidManifest.xml (renamed from core/res/res/drawable-car-night/car_dialog_button_background.xml)29
-rw-r--r--tests/LocalizationTest/AndroidTest.xml34
-rw-r--r--tests/LocalizationTest/java/com/android/internal/app/LocalizationTest.kt118
-rw-r--r--tests/net/common/java/android/net/NetworkProviderTest.kt14
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java2
-rw-r--r--tests/net/java/com/android/server/NetIdManagerTest.kt2
-rw-r--r--tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java300
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java29
-rw-r--r--tests/utils/StubIME/Android.bp (renamed from tests/utils/DummyIME/Android.bp)2
-rw-r--r--tests/utils/StubIME/AndroidManifest.xml (renamed from tests/utils/DummyIME/AndroidManifest.xml)12
-rw-r--r--tests/utils/StubIME/res/xml/method.xml (renamed from tests/utils/DummyIME/res/xml/method.xml)4
-rw-r--r--tests/utils/StubIME/src/com/android/testing/stubime/ImePreferences.java (renamed from tests/utils/DummyIME/src/com/android/testing/dummyime/ImePreferences.java)4
-rw-r--r--tests/utils/StubIME/src/com/android/testing/stubime/StubIme.java (renamed from tests/utils/DummyIME/src/com/android/testing/dummyime/DummyIme.java)6
-rw-r--r--tools/aapt2/ResourceParser.cpp2
-rw-r--r--tools/aapt2/ResourceUtils.cpp2
-rw-r--r--tools/aapt2/Resources.proto1
-rw-r--r--tools/aapt2/cmd/Link.cpp6
-rw-r--r--tools/aapt2/cmd/Optimize.cpp6
-rw-r--r--tools/aapt2/cmd/Optimize.h4
-rw-r--r--tools/aapt2/compile/PngChunkFilter.cpp6
-rw-r--r--tools/aapt2/configuration/ConfigurationParser_test.cpp2
-rw-r--r--tools/aapt2/dump/DumpManifest.cpp22
-rw-r--r--tools/aapt2/format/binary/TableFlattener_test.cpp4
-rw-r--r--tools/aapt2/format/proto/ProtoDeserialize.cpp3
-rw-r--r--tools/aapt2/format/proto/ProtoSerialize.cpp3
-rw-r--r--tools/aapt2/jni/aapt2_jni.cpp2
-rw-r--r--tools/aapt2/link/ManifestFixer.cpp4
-rw-r--r--tools/aapt2/link/TableMerger.cpp20
-rw-r--r--tools/aapt2/link/TableMerger.h4
-rw-r--r--tools/aapt2/link/XmlCompatVersioner.cpp4
-rw-r--r--tools/aapt2/optimize/ResourceFilter.cpp6
-rw-r--r--tools/aapt2/optimize/ResourceFilter.h6
-rw-r--r--tools/aapt2/optimize/ResourceFilter_test.cpp46
-rw-r--r--tools/aapt2/test/Common.cpp4
-rw-r--r--tools/aapt2/trace/TraceBuffer.h2
-rw-r--r--tools/aapt2/util/Maybe_test.cpp34
-rw-r--r--tools/aapt2/xml/XmlActionExecutor.cpp8
-rw-r--r--tools/aapt2/xml/XmlActionExecutor.h4
-rw-r--r--tools/aapt2/xml/XmlActionExecutor_test.cpp4
-rwxr-xr-xtools/aosp/aosp_sha.sh2
-rwxr-xr-xtools/hiddenapi/generate_hiddenapi_lists.py127
-rwxr-xr-xtools/hiddenapi/generate_hiddenapi_lists_test.py39
-rw-r--r--tools/stats_log_api_gen/Android.bp20
-rw-r--r--tools/stats_log_api_gen/Collation.cpp14
-rw-r--r--tools/stats_log_api_gen/Collation.h10
-rw-r--r--tools/stats_log_api_gen/java_writer.cpp28
-rw-r--r--tools/stats_log_api_gen/java_writer.h7
-rw-r--r--tools/stats_log_api_gen/java_writer_q.cpp4
-rw-r--r--tools/stats_log_api_gen/java_writer_q.h7
-rw-r--r--tools/stats_log_api_gen/main.cpp23
-rw-r--r--tools/stats_log_api_gen/native_writer.cpp204
-rw-r--r--tools/stats_log_api_gen/native_writer.h7
-rw-r--r--tools/stats_log_api_gen/test_collation.cpp7
-rw-r--r--tools/stats_log_api_gen/utils.cpp53
-rw-r--r--tools/stats_log_api_gen/utils.h22
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java3
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java11
-rw-r--r--wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java30
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java24
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java2
892 files changed, 15288 insertions, 9626 deletions
diff --git a/Android.bp b/Android.bp
index e19fe640d32b..0780f88df7c6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -433,7 +433,7 @@ java_library {
"apex_aidl_interface-java",
"suspend_control_aidl_interface-java",
"framework-protos",
- "game-driver-protos",
+ "updatable-driver-protos",
"android.hidl.base-V1.0-java",
"android.hardware.cas-V1.0-java",
"android.hardware.cas-V1.1-java",
@@ -467,6 +467,7 @@ java_library {
"com.android.sysprop.apex",
"com.android.sysprop.init",
+ "com.android.sysprop.localization",
"PlatformProperties",
],
sdk_version: "core_platform",
diff --git a/apct-tests/perftests/autofill/Android.bp b/apct-tests/perftests/autofill/Android.bp
index 65c28fb4d0a7..9ac8c87d3de0 100644
--- a/apct-tests/perftests/autofill/Android.bp
+++ b/apct-tests/perftests/autofill/Android.bp
@@ -20,6 +20,7 @@ android_test {
"androidx.test.rules",
"androidx.annotation_annotation",
"apct-perftests-utils",
+ "collector-device-lib-platform",
],
platform_apis: true,
test_suites: ["device-tests"],
diff --git a/apct-tests/perftests/autofill/AndroidManifest.xml b/apct-tests/perftests/autofill/AndroidManifest.xml
index 57595a213d20..51f6a76b2782 100644
--- a/apct-tests/perftests/autofill/AndroidManifest.xml
+++ b/apct-tests/perftests/autofill/AndroidManifest.xml
@@ -16,6 +16,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.perftests.autofill">
+ <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.perftests.utils.PerfTestActivity"
diff --git a/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java b/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java
index 48ce8ab2fce5..8f8fc29ee3c4 100644
--- a/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java
+++ b/apct-tests/perftests/autofill/src/android/view/autofill/AbstractAutofillPerfTestCase.java
@@ -26,7 +26,6 @@ import android.perftests.utils.SettingsStateKeeperRule;
import android.provider.Settings;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import org.junit.After;
@@ -37,7 +36,6 @@ import org.junit.Rule;
/**
* Base class for all autofill tests.
*/
-@LargeTest
public abstract class AbstractAutofillPerfTestCase {
@ClassRule
diff --git a/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java b/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java
index fb5ea80e6ed1..5f52dc782422 100644
--- a/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java
+++ b/apct-tests/perftests/autofill/src/android/view/autofill/LoginTest.java
@@ -24,10 +24,14 @@ import android.perftests.utils.PerfTestActivity;
import android.view.View;
import android.widget.EditText;
+import androidx.test.filters.LargeTest;
+
import com.android.perftests.autofill.R;
+import org.junit.Ignore;
import org.junit.Test;
+@LargeTest
public class LoginTest extends AbstractAutofillPerfTestCase {
private EditText mUsername;
@@ -90,6 +94,8 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
/**
* Now the service returns autofill data, for both username and password.
*/
+ // TODO(b/162216576): fix fail test and re-enable it
+ @Ignore
@Test
public void testFocus_autofillBothFields() throws Throwable {
MyAutofillService.newCannedResponse()
@@ -142,6 +148,8 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
/**
* Now the service returns autofill data, but just for username.
*/
+ // TODO(b/162216576): fix fail test and re-enable it
+ @Ignore
@Test
public void testFocus_autofillUsernameOnly() throws Throwable {
// Must set ignored ids so focus on password does not trigger new requests
@@ -258,6 +266,8 @@ public class LoginTest extends AbstractAutofillPerfTestCase {
});
}
+ // TODO(b/162216576): fix fail test and re-enable it
+ @Ignore
@Test
public void testCallbacks() throws Throwable {
MyAutofillService.newCannedResponse()
diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
index 23f025b0a759..5a04ba303b66 100644
--- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
+++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
@@ -27,7 +27,7 @@ import android.support.test.uiautomator.UiDevice;
import androidx.test.filters.LargeTest;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.utils.blob.DummyBlobData;
+import com.android.utils.blob.FakeBlobData;
import org.junit.After;
import org.junit.Before;
@@ -96,7 +96,7 @@ public class BlobStorePerfTests {
mAtraceUtils.startTrace(ATRACE_CATEGORY_SYSTEM_SERVER);
try {
final List<Long> durations = new ArrayList<>();
- final DummyBlobData blobData = prepareDataBlob(fileSizeInMb);
+ final FakeBlobData blobData = prepareDataBlob(fileSizeInMb);
final TraceMarkParser parser = new TraceMarkParser(
line -> line.name.startsWith(ATRACE_COMPUTE_DIGEST_PREFIX));
while (mState.keepRunning(durations)) {
@@ -120,15 +120,15 @@ public class BlobStorePerfTests {
});
}
- private DummyBlobData prepareDataBlob(int fileSizeInMb) throws Exception {
- final DummyBlobData blobData = new DummyBlobData.Builder(mContext)
+ private FakeBlobData prepareDataBlob(int fileSizeInMb) throws Exception {
+ final FakeBlobData blobData = new FakeBlobData.Builder(mContext)
.setFileSize(fileSizeInMb * 1024 * 1024 /* bytes */)
.build();
blobData.prepare();
return blobData;
}
- private void commitBlob(DummyBlobData blobData) throws Exception {
+ private void commitBlob(FakeBlobData blobData) throws Exception {
final long sessionId = mBlobStoreManager.createSession(blobData.getBlobHandle());
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
blobData.writeToSession(session);
diff --git a/apct-tests/perftests/contentcapture/src/android/view/contentcapture/AbstractContentCapturePerfTestCase.java b/apct-tests/perftests/contentcapture/src/android/view/contentcapture/AbstractContentCapturePerfTestCase.java
index f02c96d74ac9..9b853fed81d3 100644
--- a/apct-tests/perftests/contentcapture/src/android/view/contentcapture/AbstractContentCapturePerfTestCase.java
+++ b/apct-tests/perftests/contentcapture/src/android/view/contentcapture/AbstractContentCapturePerfTestCase.java
@@ -33,7 +33,6 @@ import android.provider.Settings;
import android.util.Log;
import androidx.annotation.NonNull;
-import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import com.android.compatibility.common.util.ActivitiesWatcher;
@@ -51,7 +50,6 @@ import org.junit.runners.model.Statement;
/**
* Base class for all content capture tests.
*/
-@LargeTest
public abstract class AbstractContentCapturePerfTestCase {
private static final String TAG = AbstractContentCapturePerfTestCase.class.getSimpleName();
diff --git a/apct-tests/perftests/contentcapture/src/android/view/contentcapture/LoginTest.java b/apct-tests/perftests/contentcapture/src/android/view/contentcapture/LoginTest.java
index 750d3b407a12..725750976d98 100644
--- a/apct-tests/perftests/contentcapture/src/android/view/contentcapture/LoginTest.java
+++ b/apct-tests/perftests/contentcapture/src/android/view/contentcapture/LoginTest.java
@@ -21,11 +21,14 @@ import static com.android.compatibility.common.util.ActivitiesWatcher.ActivityLi
import android.perftests.utils.BenchmarkState;
import android.view.View;
+import androidx.test.filters.LargeTest;
+
import com.android.compatibility.common.util.ActivitiesWatcher.ActivityWatcher;
import com.android.perftests.contentcapture.R;
import org.junit.Test;
+@LargeTest
public class LoginTest extends AbstractContentCapturePerfTestCase {
@Test
diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp
index 03ab5b6f2c8c..92dbc263cb34 100644
--- a/apct-tests/perftests/core/Android.bp
+++ b/apct-tests/perftests/core/Android.bp
@@ -17,11 +17,14 @@ android_test {
"apct-perftests-overlay-apps",
"apct-perftests-resources-manager-apps",
"apct-perftests-utils",
+ "collector-device-lib",
"guava",
],
libs: ["android.test.base"],
+ data: [":perfetto_artifacts"],
+
platform_apis: true,
jni_libs: ["libperftestscore_jni"],
diff --git a/apct-tests/perftests/core/AndroidTest.xml b/apct-tests/perftests/core/AndroidTest.xml
index 1b289130124f..4f8ee2927d51 100644
--- a/apct-tests/perftests/core/AndroidTest.xml
+++ b/apct-tests/perftests/core/AndroidTest.xml
@@ -16,13 +16,40 @@
<configuration description="Runs CorePerfTests metric instrumentation.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-metric-instrumentation" />
+
+ <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>
+
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CorePerfTests.apk" />
</target_preparer>
+ <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 files in external storage-->
+ <option name="isolated-storage" value="false" />
+
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.perftests.core" />
<option name="hidden-api-checks" value="false"/>
+
+ <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener" />
+ <!-- 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/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp
index 04432f25e337..fc45d4adcc15 100644
--- a/apct-tests/perftests/multiuser/Android.bp
+++ b/apct-tests/perftests/multiuser/Android.bp
@@ -22,5 +22,6 @@ android_test {
],
platform_apis: true,
test_suites: ["device-tests"],
+ data: [":perfetto_artifacts"],
certificate: "platform",
}
diff --git a/apct-tests/perftests/multiuser/AndroidManifest.xml b/apct-tests/perftests/multiuser/AndroidManifest.xml
index e4196dd6cf12..cb05651a3eec 100644
--- a/apct-tests/perftests/multiuser/AndroidManifest.xml
+++ b/apct-tests/perftests/multiuser/AndroidManifest.xml
@@ -17,7 +17,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.perftests.multiuser">
- <uses-sdk android:targetSdkVersion="28" />
<uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
<uses-permission android:name="android.permission.MANAGE_USERS" />
@@ -25,8 +24,6 @@
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
- <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" />
diff --git a/apct-tests/perftests/multiuser/AndroidTest.xml b/apct-tests/perftests/multiuser/AndroidTest.xml
index 9117561fe1e5..c7929af6077f 100644
--- a/apct-tests/perftests/multiuser/AndroidTest.xml
+++ b/apct-tests/perftests/multiuser/AndroidTest.xml
@@ -16,14 +16,48 @@
<configuration description="Runs MultiUserPerfTests metric instrumentation.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-metric-instrumentation" />
+
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="MultiUserPerfTests.apk" />
<option name="test-file-name" value="MultiUserPerfDummyApp.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.multiuser" />
<option name="hidden-api-checks" value="false"/>
+
+ <!-- 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/apct-tests/perftests/windowmanager/Android.bp b/apct-tests/perftests/windowmanager/Android.bp
index 9e95a104af81..9fa99853ace3 100644
--- a/apct-tests/perftests/windowmanager/Android.bp
+++ b/apct-tests/perftests/windowmanager/Android.bp
@@ -19,6 +19,7 @@ android_test {
"androidx.test.rules",
"androidx.annotation_annotation",
"apct-perftests-utils",
+ "collector-device-lib",
"platform-test-annotations",
],
test_suites: ["device-tests"],
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
index 12ec9eb4eb73..7851087bac19 100644
--- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java
+++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
@@ -803,8 +803,8 @@ public class AlarmManager {
* <b>only</b> be used for situations where it is actually required that the alarm go off while
* in idle -- a reasonable example would be for a calendar notification that should make a
* sound so the user is aware of it. When the alarm is dispatched, the app will also be
- * added to the system's temporary whitelist for approximately 10 seconds to allow that
- * application to acquire further wake locks in which to complete its work.</p>
+ * added to the system's temporary power exemption list for approximately 10 seconds to allow
+ * that application to acquire further wake locks in which to complete its work.</p>
*
* <p>These alarms can significantly impact the power use
* of the device when idle (and thus cause significant battery blame to the app scheduling
@@ -855,8 +855,8 @@ public class AlarmManager {
* be used for situations where it is actually required that the alarm go off while in
* idle -- a reasonable example would be for a calendar notification that should make a
* sound so the user is aware of it. When the alarm is dispatched, the app will also be
- * added to the system's temporary whitelist for approximately 10 seconds to allow that
- * application to acquire further wake locks in which to complete its work.</p>
+ * added to the system's temporary power exemption list for approximately 10 seconds to allow
+ * that application to acquire further wake locks in which to complete its work.</p>
*
* <p>These alarms can significantly impact the power use
* of the device when idle (and thus cause significant battery blame to the app scheduling
diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
index 6d2363549604..876d73a570af 100644
--- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
+++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
@@ -67,8 +67,8 @@ import java.util.Objects;
* Class to keep track of the information related to "force app standby", which includes:
* - OP_RUN_ANY_IN_BACKGROUND for each package
* - UID foreground/active state
- * - User+system power save whitelist
- * - Temporary power save whitelist
+ * - User+system power save exemption list
+ * - Temporary power save exemption list
* - Global "force all apps standby" mode enforced by battery saver.
*
* Test: atest com.android.server.AppStateTrackerTest
@@ -110,25 +110,25 @@ public class AppStateTrackerImpl implements AppStateTracker {
final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
/**
- * System except-idle + user whitelist in the device idle controller.
+ * System except-idle + user exemption list in the device idle controller.
*/
@GuardedBy("mLock")
- private int[] mPowerWhitelistedAllAppIds = new int[0];
+ private int[] mPowerExemptAllAppIds = new int[0];
/**
- * User whitelisted apps in the device idle controller.
+ * User exempted apps in the device idle controller.
*/
@GuardedBy("mLock")
- private int[] mPowerWhitelistedUserAppIds = new int[0];
+ private int[] mPowerExemptUserAppIds = new int[0];
@GuardedBy("mLock")
- private int[] mTempWhitelistedAppIds = mPowerWhitelistedAllAppIds;
+ private int[] mTempExemptAppIds = mPowerExemptAllAppIds;
/**
* Per-user packages that are in the EXEMPT bucket.
*/
@GuardedBy("mLock")
- private final SparseSetArray<String> mExemptedPackages = new SparseSetArray<>();
+ private final SparseSetArray<String> mExemptBucketPackages = new SparseSetArray<>();
@GuardedBy("mLock")
final ArraySet<Listener> mListeners = new ArraySet<>();
@@ -177,10 +177,10 @@ public class AppStateTrackerImpl implements AppStateTracker {
int UID_FG_STATE_CHANGED = 0;
int UID_ACTIVE_STATE_CHANGED = 1;
int RUN_ANY_CHANGED = 2;
- int ALL_UNWHITELISTED = 3;
- int ALL_WHITELIST_CHANGED = 4;
- int TEMP_WHITELIST_CHANGED = 5;
- int EXEMPT_CHANGED = 6;
+ int ALL_UNEXEMPTED = 3;
+ int ALL_EXEMPTION_LIST_CHANGED = 4;
+ int TEMP_EXEMPTION_LIST_CHANGED = 5;
+ int EXEMPT_BUCKET_CHANGED = 6;
int FORCE_ALL_CHANGED = 7;
int FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
@@ -192,10 +192,10 @@ public class AppStateTrackerImpl implements AppStateTracker {
"UID_FG_STATE_CHANGED",
"UID_ACTIVE_STATE_CHANGED",
"RUN_ANY_CHANGED",
- "ALL_UNWHITELISTED",
- "ALL_WHITELIST_CHANGED",
- "TEMP_WHITELIST_CHANGED",
- "EXEMPT_CHANGED",
+ "ALL_UNEXEMPTED",
+ "ALL_EXEMPTION_LIST_CHANGED",
+ "TEMP_EXEMPTION_LIST_CHANGED",
+ "EXEMPT_BUCKET_CHANGED",
"FORCE_ALL_CHANGED",
"FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED",
@@ -308,38 +308,39 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
/**
- * This is called when an app-id(s) is removed from the power save whitelist.
+ * This is called when an app-id(s) is removed from the power save allow-list.
*/
- private void onPowerSaveUnwhitelisted(AppStateTrackerImpl sender) {
+ private void onPowerSaveUnexempted(AppStateTrackerImpl sender) {
updateAllJobs();
unblockAllUnrestrictedAlarms();
}
/**
- * This is called when the power save whitelist changes, excluding the
- * {@link #onPowerSaveUnwhitelisted} case.
+ * This is called when the power save exemption list changes, excluding the
+ * {@link #onPowerSaveUnexempted} case.
*/
- private void onPowerSaveWhitelistedChanged(AppStateTrackerImpl sender) {
+ private void onPowerSaveExemptionListChanged(AppStateTrackerImpl sender) {
updateAllJobs();
}
/**
- * This is called when the temp whitelist changes.
+ * This is called when the temp exemption list changes.
*/
- private void onTempPowerSaveWhitelistChanged(AppStateTrackerImpl sender) {
+ private void onTempPowerSaveExemptionListChanged(AppStateTrackerImpl sender) {
// TODO This case happens rather frequently; consider optimizing and update jobs
// only for affected app-ids.
updateAllJobs();
- // Note when an app is just put in the temp whitelist, we do *not* drain pending alarms.
+ // Note when an app is just put in the temp exemption list, we do *not* drain pending
+ // alarms.
}
/**
* This is called when the EXEMPT bucket is updated.
*/
- private void onExemptChanged(AppStateTrackerImpl sender) {
+ private void onExemptBucketChanged(AppStateTrackerImpl sender) {
// This doesn't happen very often, so just re-evaluate all jobs / alarms.
updateAllJobs();
unblockAllUnrestrictedAlarms();
@@ -709,8 +710,8 @@ public class AppStateTrackerImpl implements AppStateTracker {
&& !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
final String pkgName = intent.getData().getSchemeSpecificPart();
- if (mExemptedPackages.remove(userId, pkgName)) {
- mHandler.notifyExemptChanged();
+ if (mExemptBucketPackages.remove(userId, pkgName)) {
+ mHandler.notifyExemptBucketChanged();
}
}
}
@@ -727,12 +728,12 @@ public class AppStateTrackerImpl implements AppStateTracker {
synchronized (mLock) {
final boolean changed;
if (bucket == UsageStatsManager.STANDBY_BUCKET_EXEMPTED) {
- changed = mExemptedPackages.add(userId, packageName);
+ changed = mExemptBucketPackages.add(userId, packageName);
} else {
- changed = mExemptedPackages.remove(userId, packageName);
+ changed = mExemptBucketPackages.remove(userId, packageName);
}
if (changed) {
- mHandler.notifyExemptChanged();
+ mHandler.notifyExemptBucketChanged();
}
}
}
@@ -748,13 +749,13 @@ public class AppStateTrackerImpl implements AppStateTracker {
private static final int MSG_UID_ACTIVE_STATE_CHANGED = 0;
private static final int MSG_UID_FG_STATE_CHANGED = 1;
private static final int MSG_RUN_ANY_CHANGED = 3;
- private static final int MSG_ALL_UNWHITELISTED = 4;
- private static final int MSG_ALL_WHITELIST_CHANGED = 5;
- private static final int MSG_TEMP_WHITELIST_CHANGED = 6;
+ private static final int MSG_ALL_UNEXEMPTED = 4;
+ private static final int MSG_ALL_EXEMPTION_LIST_CHANGED = 5;
+ private static final int MSG_TEMP_EXEMPTION_LIST_CHANGED = 6;
private static final int MSG_FORCE_ALL_CHANGED = 7;
private static final int MSG_USER_REMOVED = 8;
private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
- private static final int MSG_EXEMPT_CHANGED = 10;
+ private static final int MSG_EXEMPT_BUCKET_CHANGED = 10;
private static final int MSG_ON_UID_STATE_CHANGED = 11;
private static final int MSG_ON_UID_ACTIVE = 12;
@@ -777,19 +778,19 @@ public class AppStateTrackerImpl implements AppStateTracker {
obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget();
}
- public void notifyAllUnwhitelisted() {
- removeMessages(MSG_ALL_UNWHITELISTED);
- obtainMessage(MSG_ALL_UNWHITELISTED).sendToTarget();
+ public void notifyAllUnexempted() {
+ removeMessages(MSG_ALL_UNEXEMPTED);
+ obtainMessage(MSG_ALL_UNEXEMPTED).sendToTarget();
}
- public void notifyAllWhitelistChanged() {
- removeMessages(MSG_ALL_WHITELIST_CHANGED);
- obtainMessage(MSG_ALL_WHITELIST_CHANGED).sendToTarget();
+ public void notifyAllExemptionListChanged() {
+ removeMessages(MSG_ALL_EXEMPTION_LIST_CHANGED);
+ obtainMessage(MSG_ALL_EXEMPTION_LIST_CHANGED).sendToTarget();
}
- public void notifyTempWhitelistChanged() {
- removeMessages(MSG_TEMP_WHITELIST_CHANGED);
- obtainMessage(MSG_TEMP_WHITELIST_CHANGED).sendToTarget();
+ public void notifyTempExemptionListChanged() {
+ removeMessages(MSG_TEMP_EXEMPTION_LIST_CHANGED);
+ obtainMessage(MSG_TEMP_EXEMPTION_LIST_CHANGED).sendToTarget();
}
public void notifyForceAllAppsStandbyChanged() {
@@ -802,9 +803,9 @@ public class AppStateTrackerImpl implements AppStateTracker {
obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
}
- public void notifyExemptChanged() {
- removeMessages(MSG_EXEMPT_CHANGED);
- obtainMessage(MSG_EXEMPT_CHANGED).sendToTarget();
+ public void notifyExemptBucketChanged() {
+ removeMessages(MSG_EXEMPT_BUCKET_CHANGED);
+ obtainMessage(MSG_EXEMPT_BUCKET_CHANGED).sendToTarget();
}
public void doUserRemoved(int userId) {
@@ -866,32 +867,32 @@ public class AppStateTrackerImpl implements AppStateTracker {
mStatLogger.logDurationStat(Stats.RUN_ANY_CHANGED, start);
return;
- case MSG_ALL_UNWHITELISTED:
+ case MSG_ALL_UNEXEMPTED:
for (Listener l : cloneListeners()) {
- l.onPowerSaveUnwhitelisted(sender);
+ l.onPowerSaveUnexempted(sender);
}
- mStatLogger.logDurationStat(Stats.ALL_UNWHITELISTED, start);
+ mStatLogger.logDurationStat(Stats.ALL_UNEXEMPTED, start);
return;
- case MSG_ALL_WHITELIST_CHANGED:
+ case MSG_ALL_EXEMPTION_LIST_CHANGED:
for (Listener l : cloneListeners()) {
- l.onPowerSaveWhitelistedChanged(sender);
+ l.onPowerSaveExemptionListChanged(sender);
}
- mStatLogger.logDurationStat(Stats.ALL_WHITELIST_CHANGED, start);
+ mStatLogger.logDurationStat(Stats.ALL_EXEMPTION_LIST_CHANGED, start);
return;
- case MSG_TEMP_WHITELIST_CHANGED:
+ case MSG_TEMP_EXEMPTION_LIST_CHANGED:
for (Listener l : cloneListeners()) {
- l.onTempPowerSaveWhitelistChanged(sender);
+ l.onTempPowerSaveExemptionListChanged(sender);
}
- mStatLogger.logDurationStat(Stats.TEMP_WHITELIST_CHANGED, start);
+ mStatLogger.logDurationStat(Stats.TEMP_EXEMPTION_LIST_CHANGED, start);
return;
- case MSG_EXEMPT_CHANGED:
+ case MSG_EXEMPT_BUCKET_CHANGED:
for (Listener l : cloneListeners()) {
- l.onExemptChanged(sender);
+ l.onExemptBucketChanged(sender);
}
- mStatLogger.logDurationStat(Stats.EXEMPT_CHANGED, start);
+ mStatLogger.logDurationStat(Stats.EXEMPT_BUCKET_CHANGED, start);
return;
case MSG_FORCE_ALL_CHANGED:
@@ -1004,7 +1005,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
cleanUpArrayForUser(mActiveUids, removedUserId);
cleanUpArrayForUser(mForegroundUids, removedUserId);
- mExemptedPackages.remove(removedUserId);
+ mExemptBucketPackages.remove(removedUserId);
}
}
@@ -1020,39 +1021,39 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
/**
- * Called by device idle controller to update the power save whitelists.
+ * Called by device idle controller to update the power save exemption lists.
*/
- public void setPowerSaveWhitelistAppIds(
- int[] powerSaveWhitelistExceptIdleAppIdArray,
- int[] powerSaveWhitelistUserAppIdArray,
- int[] tempWhitelistAppIdArray) {
+ public void setPowerSaveExemptionListAppIds(
+ int[] powerSaveExemptionListExceptIdleAppIdArray,
+ int[] powerSaveExemptionListUserAppIdArray,
+ int[] tempExemptionListAppIdArray) {
synchronized (mLock) {
- final int[] previousWhitelist = mPowerWhitelistedAllAppIds;
- final int[] previousTempWhitelist = mTempWhitelistedAppIds;
+ final int[] previousExemptionList = mPowerExemptAllAppIds;
+ final int[] previousTempExemptionList = mTempExemptAppIds;
- mPowerWhitelistedAllAppIds = powerSaveWhitelistExceptIdleAppIdArray;
- mTempWhitelistedAppIds = tempWhitelistAppIdArray;
- mPowerWhitelistedUserAppIds = powerSaveWhitelistUserAppIdArray;
+ mPowerExemptAllAppIds = powerSaveExemptionListExceptIdleAppIdArray;
+ mTempExemptAppIds = tempExemptionListAppIdArray;
+ mPowerExemptUserAppIds = powerSaveExemptionListUserAppIdArray;
- if (isAnyAppIdUnwhitelisted(previousWhitelist, mPowerWhitelistedAllAppIds)) {
- mHandler.notifyAllUnwhitelisted();
- } else if (!Arrays.equals(previousWhitelist, mPowerWhitelistedAllAppIds)) {
- mHandler.notifyAllWhitelistChanged();
+ if (isAnyAppIdUnexempt(previousExemptionList, mPowerExemptAllAppIds)) {
+ mHandler.notifyAllUnexempted();
+ } else if (!Arrays.equals(previousExemptionList, mPowerExemptAllAppIds)) {
+ mHandler.notifyAllExemptionListChanged();
}
- if (!Arrays.equals(previousTempWhitelist, mTempWhitelistedAppIds)) {
- mHandler.notifyTempWhitelistChanged();
+ if (!Arrays.equals(previousTempExemptionList, mTempExemptAppIds)) {
+ mHandler.notifyTempExemptionListChanged();
}
}
}
/**
- * @retunr true if a sorted app-id array {@code prevArray} has at least one element
+ * @return true if a sorted app-id array {@code prevArray} has at least one element
* that's not in a sorted app-id array {@code newArray}.
*/
@VisibleForTesting
- static boolean isAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray) {
+ static boolean isAnyAppIdUnexempt(int[] prevArray, int[] newArray) {
int i1 = 0;
int i2 = 0;
boolean prevFinished;
@@ -1100,7 +1101,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
*/
public boolean areAlarmsRestricted(int uid, @NonNull String packageName,
boolean isExemptOnBatterySaver) {
- return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false,
+ return isRestricted(uid, packageName, /*useTempExemptionListToo=*/ false,
isExemptOnBatterySaver);
}
@@ -1109,7 +1110,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
*/
public boolean areJobsRestricted(int uid, @NonNull String packageName,
boolean hasForegroundExemption) {
- return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true,
+ return isRestricted(uid, packageName, /*useTempExemptionListToo=*/ true,
hasForegroundExemption);
}
@@ -1127,17 +1128,16 @@ public class AppStateTrackerImpl implements AppStateTracker {
* @return whether force-app-standby is effective for a UID package-name.
*/
private boolean isRestricted(int uid, @NonNull String packageName,
- boolean useTempWhitelistToo, boolean exemptOnBatterySaver) {
+ boolean useTempExemptionListToo, boolean exemptOnBatterySaver) {
if (isUidActive(uid)) {
return false;
}
synchronized (mLock) {
- // Whitelisted?
final int appId = UserHandle.getAppId(uid);
- if (ArrayUtils.contains(mPowerWhitelistedAllAppIds, appId)) {
+ if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) {
return false;
}
- if (useTempWhitelistToo && ArrayUtils.contains(mTempWhitelistedAppIds, appId)) {
+ if (useTempExemptionListToo && ArrayUtils.contains(mTempExemptAppIds, appId)) {
return false;
}
if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
@@ -1148,7 +1148,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
final int userId = UserHandle.getUserId(uid);
if (mAppStandbyInternal.isAppIdleEnabled() && !mAppStandbyInternal.isInParole()
- && mExemptedPackages.contains(userId, packageName)) {
+ && mExemptBucketPackages.contains(userId, packageName)) {
return false;
}
return mForceAllAppsStandby;
@@ -1225,34 +1225,34 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
/**
- * @return whether a UID is in the user / system defined power-save whitelist or not.
+ * @return whether a UID is in the user / system defined power-save exemption list or not.
*
* Note clients normally shouldn't need to access it. It's only for dumpsys.
*/
- public boolean isUidPowerSaveWhitelisted(int uid) {
+ public boolean isUidPowerSaveExempt(int uid) {
synchronized (mLock) {
- return ArrayUtils.contains(mPowerWhitelistedAllAppIds, UserHandle.getAppId(uid));
+ return ArrayUtils.contains(mPowerExemptAllAppIds, UserHandle.getAppId(uid));
}
}
/**
* @param uid the uid to check for
- * @return whether a UID is in the user defined power-save whitelist or not.
+ * @return whether a UID is in the user defined power-save exemption list or not.
*/
- public boolean isUidPowerSaveUserWhitelisted(int uid) {
+ public boolean isUidPowerSaveUserExempt(int uid) {
synchronized (mLock) {
- return ArrayUtils.contains(mPowerWhitelistedUserAppIds, UserHandle.getAppId(uid));
+ return ArrayUtils.contains(mPowerExemptUserAppIds, UserHandle.getAppId(uid));
}
}
/**
- * @return whether a UID is in the temp power-save whitelist or not.
+ * @return whether a UID is in the temp power-save exemption list or not.
*
* Note clients normally shouldn't need to access it. It's only for dumpsys.
*/
- public boolean isUidTempPowerSaveWhitelisted(int uid) {
+ public boolean isUidTempPowerSaveExempt(int uid) {
synchronized (mLock) {
- return ArrayUtils.contains(mTempWhitelistedAppIds, UserHandle.getAppId(uid));
+ return ArrayUtils.contains(mTempExemptAppIds, UserHandle.getAppId(uid));
}
}
@@ -1290,25 +1290,25 @@ public class AppStateTrackerImpl implements AppStateTracker {
pw.print("Foreground uids: ");
dumpUids(pw, mForegroundUids);
- pw.print("Except-idle + user whitelist appids: ");
- pw.println(Arrays.toString(mPowerWhitelistedAllAppIds));
+ pw.print("Except-idle + user exemption list appids: ");
+ pw.println(Arrays.toString(mPowerExemptAllAppIds));
- pw.print("User whitelist appids: ");
- pw.println(Arrays.toString(mPowerWhitelistedUserAppIds));
+ pw.print("User exemption list appids: ");
+ pw.println(Arrays.toString(mPowerExemptUserAppIds));
- pw.print("Temp whitelist appids: ");
- pw.println(Arrays.toString(mTempWhitelistedAppIds));
+ pw.print("Temp exemption list appids: ");
+ pw.println(Arrays.toString(mTempExemptAppIds));
- pw.println("Exempted packages:");
+ pw.println("Exempted bucket packages:");
pw.increaseIndent();
- for (int i = 0; i < mExemptedPackages.size(); i++) {
+ for (int i = 0; i < mExemptBucketPackages.size(); i++) {
pw.print("User ");
- pw.print(mExemptedPackages.keyAt(i));
+ pw.print(mExemptBucketPackages.keyAt(i));
pw.println();
pw.increaseIndent();
- for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
- pw.print(mExemptedPackages.valueAt(i, j));
+ for (int j = 0; j < mExemptBucketPackages.sizeAt(i); j++) {
+ pw.print(mExemptBucketPackages.valueAt(i, j));
pw.println();
}
pw.decreaseIndent();
@@ -1372,24 +1372,24 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
}
- for (int appId : mPowerWhitelistedAllAppIds) {
- proto.write(AppStateTrackerProto.POWER_SAVE_WHITELIST_APP_IDS, appId);
+ for (int appId : mPowerExemptAllAppIds) {
+ proto.write(AppStateTrackerProto.POWER_SAVE_EXEMPT_APP_IDS, appId);
}
- for (int appId : mPowerWhitelistedUserAppIds) {
- proto.write(AppStateTrackerProto.POWER_SAVE_USER_WHITELIST_APP_IDS, appId);
+ for (int appId : mPowerExemptUserAppIds) {
+ proto.write(AppStateTrackerProto.POWER_SAVE_USER_EXEMPT_APP_IDS, appId);
}
- for (int appId : mTempWhitelistedAppIds) {
- proto.write(AppStateTrackerProto.TEMP_POWER_SAVE_WHITELIST_APP_IDS, appId);
+ for (int appId : mTempExemptAppIds) {
+ proto.write(AppStateTrackerProto.TEMP_POWER_SAVE_EXEMPT_APP_IDS, appId);
}
- for (int i = 0; i < mExemptedPackages.size(); i++) {
- for (int j = 0; j < mExemptedPackages.sizeAt(i); j++) {
- final long token2 = proto.start(AppStateTrackerProto.EXEMPTED_PACKAGES);
+ for (int i = 0; i < mExemptBucketPackages.size(); i++) {
+ for (int j = 0; j < mExemptBucketPackages.sizeAt(i); j++) {
+ final long token2 = proto.start(AppStateTrackerProto.EXEMPTED_BUCKET_PACKAGES);
- proto.write(ExemptedPackage.USER_ID, mExemptedPackages.keyAt(i));
- proto.write(ExemptedPackage.PACKAGE_NAME, mExemptedPackages.valueAt(i, j));
+ proto.write(ExemptedPackage.USER_ID, mExemptBucketPackages.keyAt(i));
+ proto.write(ExemptedPackage.PACKAGE_NAME, mExemptBucketPackages.valueAt(i, j));
proto.end(token2);
}
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index b1bafeea3c98..6c3398f91db1 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -3715,7 +3715,7 @@ public class DeviceIdleController extends SystemService
}
private void passWhiteListsToForceAppStandbyTrackerLocked() {
- mAppStateTracker.setPowerSaveWhitelistAppIds(
+ mAppStateTracker.setPowerSaveExemptionListAppIds(
mPowerSaveWhitelistExceptIdleAppIdArray,
mPowerSaveWhitelistUserAppIdArray,
mTempWhitelistAppIdArray);
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 6529503808b3..4194fd0068c2 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -2089,7 +2089,7 @@ public class AlarmManagerService extends SystemService {
} else if (workSource == null && (callingUid < Process.FIRST_APPLICATION_UID
|| UserHandle.isSameApp(callingUid, mSystemUiUid)
|| ((mAppStateTracker != null)
- && mAppStateTracker.isUidPowerSaveUserWhitelisted(callingUid)))) {
+ && mAppStateTracker.isUidPowerSaveUserExempt(callingUid)))) {
flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
flags &= ~AlarmManager.FLAG_ALLOW_WHILE_IDLE;
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 06c469a5cc82..3234b274eaa7 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -89,6 +89,7 @@ import com.android.server.AppStateTracker;
import com.android.server.AppStateTrackerImpl;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
+import com.android.server.SystemService.TargetUser;
import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
import com.android.server.job.controllers.BackgroundJobsController;
@@ -975,24 +976,24 @@ public class JobSchedulerService extends com.android.server.SystemService
}
@Override
- public void onStartUser(int userHandle) {
+ public void onUserStarting(@NonNull TargetUser user) {
synchronized (mLock) {
- mStartedUsers = ArrayUtils.appendInt(mStartedUsers, userHandle);
+ mStartedUsers = ArrayUtils.appendInt(mStartedUsers, user.getUserIdentifier());
}
// Let's kick any outstanding jobs for this user.
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
@Override
- public void onUnlockUser(int userHandle) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
// Let's kick any outstanding jobs for this user.
mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
@Override
- public void onStopUser(int userHandle) {
+ public void onUserStopping(@NonNull TargetUser user) {
synchronized (mLock) {
- mStartedUsers = ArrayUtils.removeInt(mStartedUsers, userHandle);
+ mStartedUsers = ArrayUtils.removeInt(mStartedUsers, user.getUserIdentifier());
}
}
@@ -1193,7 +1194,7 @@ public class JobSchedulerService extends com.android.server.SystemService
private void cancelJobsForNonExistentUsers() {
UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
synchronized (mLock) {
- mJobs.removeJobsOfNonUsers(umi.getUserIds());
+ mJobs.removeJobsOfUnlistedUsers(umi.getUserIds());
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index 7bd51b77a119..eaf8f4d96331 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -254,11 +254,11 @@ public final class JobStore {
}
/**
- * Remove the jobs of users not specified in the whitelist.
- * @param whitelist Array of User IDs whose jobs are not to be removed.
+ * Remove the jobs of users not specified in the keepUserIds.
+ * @param keepUserIds Array of User IDs whose jobs should be kept and not removed.
*/
- public void removeJobsOfNonUsers(int[] whitelist) {
- mJobSet.removeJobsOfNonUsers(whitelist);
+ public void removeJobsOfUnlistedUsers(int[] keepUserIds) {
+ mJobSet.removeJobsOfUnlistedUsers(keepUserIds);
}
@VisibleForTesting
@@ -1151,15 +1151,14 @@ public final class JobStore {
}
/**
- * Removes the jobs of all users not specified by the whitelist of user ids.
- * This will remove jobs scheduled *by* non-existent users as well as jobs scheduled *for*
- * non-existent users
+ * Removes the jobs of all users not specified by the keepUserIds of user ids.
+ * This will remove jobs scheduled *by* and *for* any unlisted users.
*/
- public void removeJobsOfNonUsers(final int[] whitelist) {
+ public void removeJobsOfUnlistedUsers(final int[] keepUserIds) {
final Predicate<JobStatus> noSourceUser =
- job -> !ArrayUtils.contains(whitelist, job.getSourceUserId());
+ job -> !ArrayUtils.contains(keepUserIds, job.getSourceUserId());
final Predicate<JobStatus> noCallingUser =
- job -> !ArrayUtils.contains(whitelist, job.getUserId());
+ job -> !ArrayUtils.contains(keepUserIds, job.getUserId());
removeAll(noSourceUser.or(noCallingUser));
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index b6324358ec33..44c8fcff8c63 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -91,9 +91,9 @@ public final class BackgroundJobsController extends StateController {
pw.print(" from ");
UserHandle.formatUid(pw, uid);
pw.print(mAppStateTracker.isUidActive(uid) ? " active" : " idle");
- if (mAppStateTracker.isUidPowerSaveWhitelisted(uid) ||
- mAppStateTracker.isUidTempPowerSaveWhitelisted(uid)) {
- pw.print(", whitelisted");
+ if (mAppStateTracker.isUidPowerSaveExempt(uid)
+ || mAppStateTracker.isUidTempPowerSaveExempt(uid)) {
+ pw.print(", exempted");
}
pw.print(": ");
pw.print(sourcePkg);
@@ -132,8 +132,8 @@ public final class BackgroundJobsController extends StateController {
proto.write(TrackedJob.IS_IN_FOREGROUND, mAppStateTracker.isUidActive(sourceUid));
proto.write(TrackedJob.IS_WHITELISTED,
- mAppStateTracker.isUidPowerSaveWhitelisted(sourceUid) ||
- mAppStateTracker.isUidTempPowerSaveWhitelisted(sourceUid));
+ mAppStateTracker.isUidPowerSaveExempt(sourceUid)
+ || mAppStateTracker.isUidTempPowerSaveExempt(sourceUid));
proto.write(TrackedJob.CAN_RUN_ANY_IN_BACKGROUND,
mAppStateTracker.isRunAnyInBackgroundAppOpsAllowed(sourceUid, sourcePkg));
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 2f993dad51c7..6bc95bf8bc75 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -222,12 +222,19 @@ public class AppStandbyController implements AppStandbyInternal {
@GuardedBy("mPackageAccessListeners")
private final ArrayList<AppIdleStateChangeListener> mPackageAccessListeners = new ArrayList<>();
+ /**
+ * Lock specifically for bookkeeping around the carrier-privileged app set.
+ * Do not acquire any other locks while holding this one. Methods that
+ * require this lock to be held are named with a "CPL" suffix.
+ */
+ private final Object mCarrierPrivilegedLock = new Lock();
+
/** Whether we've queried the list of carrier privileged apps. */
- @GuardedBy("mAppIdleLock")
+ @GuardedBy("mCarrierPrivilegedLock")
private boolean mHaveCarrierPrivilegedApps;
/** List of carrier-privileged apps that should be excluded from standby */
- @GuardedBy("mAppIdleLock")
+ @GuardedBy("mCarrierPrivilegedLock")
private List<String> mCarrierPrivilegedApps;
@GuardedBy("mActiveAdminApps")
@@ -1594,9 +1601,9 @@ public class AppStandbyController implements AppStandbyInternal {
}
private boolean isCarrierApp(String packageName) {
- synchronized (mAppIdleLock) {
+ synchronized (mCarrierPrivilegedLock) {
if (!mHaveCarrierPrivilegedApps) {
- fetchCarrierPrivilegedAppsLocked();
+ fetchCarrierPrivilegedAppsCPL();
}
if (mCarrierPrivilegedApps != null) {
return mCarrierPrivilegedApps.contains(packageName);
@@ -1610,14 +1617,14 @@ public class AppStandbyController implements AppStandbyInternal {
if (DEBUG) {
Slog.i(TAG, "Clearing carrier privileged apps list");
}
- synchronized (mAppIdleLock) {
+ synchronized (mCarrierPrivilegedLock) {
mHaveCarrierPrivilegedApps = false;
mCarrierPrivilegedApps = null; // Need to be refetched.
}
}
- @GuardedBy("mAppIdleLock")
- private void fetchCarrierPrivilegedAppsLocked() {
+ @GuardedBy("mCarrierPrivilegedLock")
+ private void fetchCarrierPrivilegedAppsCPL() {
TelephonyManager telephonyManager =
mContext.getSystemService(TelephonyManager.class);
mCarrierPrivilegedApps =
@@ -1858,7 +1865,7 @@ public class AppStandbyController implements AppStandbyInternal {
@Override
public void dumpState(String[] args, PrintWriter pw) {
- synchronized (mAppIdleLock) {
+ synchronized (mCarrierPrivilegedLock) {
pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
+ "): " + mCarrierPrivilegedApps);
}
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
index 04339e67d799..f66cf7c9e23c 100644
--- a/apex/statsd/aidl/Android.bp
+++ b/apex/statsd/aidl/Android.bp
@@ -30,6 +30,7 @@ aidl_interface {
"android/os/StatsDimensionsValueParcel.aidl",
"android/util/StatsEventParcel.aidl",
],
+ host_supported: true,
backend: {
java: {
enabled: false, // framework-statsd and service-statsd use framework-statsd-aidl-sources
diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
index 5cdb3249501b..d56a4bd0a8e5 100644
--- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
+++ b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
@@ -27,17 +27,6 @@ interface IStatsCompanionService {
oneway void statsdReady();
/**
- * Register an alarm for anomaly detection to fire at the given timestamp (ms since epoch).
- * If anomaly alarm had already been registered, it will be replaced with the new timestamp.
- * Uses AlarmManager.set API, so if the timestamp is in the past, alarm fires immediately, and
- * alarm is inexact.
- */
- oneway void setAnomalyAlarm(long timestampMs);
-
- /** Cancel any anomaly detection alarm. */
- oneway void cancelAnomalyAlarm();
-
- /**
* Register a repeating alarm for pulling to fire at the given timestamp and every
* intervalMs thereafter (in ms since epoch).
* If polling alarm had already been registered, it will be replaced by new one.
diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl
index 0d3f4208a2ab..066412a9f157 100644
--- a/apex/statsd/aidl/android/os/IStatsd.aidl
+++ b/apex/statsd/aidl/android/os/IStatsd.aidl
@@ -42,13 +42,6 @@ interface IStatsd {
void statsCompanionReady();
/**
- * Tells statsd that an anomaly may have occurred, so statsd can check whether this is so and
- * act accordingly.
- * Two-way binder call so that caller's method (and corresponding wakelocks) will linger.
- */
- void informAnomalyAlarmFired();
-
- /**
* Tells statsd that it is time to poll some stats. Statsd will be responsible for determing
* what stats to poll and initiating the polling.
* Two-way binder call so that caller's method (and corresponding wakelocks) will linger.
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index cbc8ed636ff2..b5e72247a4a3 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -100,7 +100,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private static IStatsd sStatsd;
private static final Object sStatsdLock = new Object();
- private final OnAlarmListener mAnomalyAlarmListener;
private final OnAlarmListener mPullingAlarmListener;
private final OnAlarmListener mPeriodicAlarmListener;
@@ -124,7 +123,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
handlerThread.start();
mHandler = new CompanionHandler(handlerThread.getLooper());
- mAnomalyAlarmListener = new AnomalyAlarmListener(context);
mPullingAlarmListener = new PullingAlarmListener(context);
mPeriodicAlarmListener = new PeriodicAlarmListener(context);
}
@@ -336,41 +334,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
- public static final class AnomalyAlarmListener implements OnAlarmListener {
- private final Context mContext;
-
- AnomalyAlarmListener(Context context) {
- mContext = context;
- }
-
- @Override
- public void onAlarm() {
- if (DEBUG) {
- Log.i(TAG, "StatsCompanionService believes an anomaly has occurred at time "
- + System.currentTimeMillis() + "ms.");
- }
- IStatsd statsd = getStatsdNonblocking();
- if (statsd == null) {
- Log.w(TAG, "Could not access statsd to inform it of anomaly alarm firing");
- return;
- }
-
- // Wakelock needs to be retained while calling statsd.
- Thread thread = new WakelockThread(mContext,
- AnomalyAlarmListener.class.getCanonicalName(), new Runnable() {
- @Override
- public void run() {
- try {
- statsd.informAnomalyAlarmFired();
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to inform statsd of anomaly alarm firing", e);
- }
- }
- });
- thread.start();
- }
- }
-
public final static class PullingAlarmListener implements OnAlarmListener {
private final Context mContext;
@@ -469,34 +432,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
@Override // Binder call
- public void setAnomalyAlarm(long timestampMs) {
- StatsCompanion.enforceStatsdCallingUid();
- if (DEBUG) Log.d(TAG, "Setting anomaly alarm for " + timestampMs);
- final long callingToken = Binder.clearCallingIdentity();
- try {
- // using ELAPSED_REALTIME, not ELAPSED_REALTIME_WAKEUP, so if device is asleep, will
- // only fire when it awakens.
- // AlarmManager will automatically cancel any previous mAnomalyAlarmListener alarm.
- mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, timestampMs, TAG + ".anomaly",
- mAnomalyAlarmListener, mHandler);
- } finally {
- Binder.restoreCallingIdentity(callingToken);
- }
- }
-
- @Override // Binder call
- public void cancelAnomalyAlarm() {
- StatsCompanion.enforceStatsdCallingUid();
- if (DEBUG) Log.d(TAG, "Cancelling anomaly alarm");
- final long callingToken = Binder.clearCallingIdentity();
- try {
- mAlarmManager.cancel(mAnomalyAlarmListener);
- } finally {
- Binder.restoreCallingIdentity(callingToken);
- }
- }
-
- @Override // Binder call
public void setAlarmForSubscriberTriggering(long timestampMs) {
StatsCompanion.enforceStatsdCallingUid();
if (DEBUG) {
@@ -666,7 +601,6 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
// instead of in binder death because statsd can come back and set different alarms, or not
// want to set an alarm when it had been set. This guarantees that when we get a new statsd,
// we cancel any alarms before it is able to set them.
- cancelAnomalyAlarm();
cancelPullingAlarm();
cancelAlarmForSubscriberTriggering();
diff --git a/api/current.txt b/api/current.txt
index 75ea7d7adc4c..09de005c008c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24207,6 +24207,7 @@ package android.media {
method @NonNull public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
method @NonNull public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations();
method public int getAllowedCapturePolicy();
+ method public int getAudioHwSyncForSession(int);
method public android.media.AudioDeviceInfo[] getDevices(int);
method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException;
method public int getMode();
@@ -45455,6 +45456,7 @@ package android.system {
package android.telecom {
public final class Call {
+ method public void addConferenceParticipants(@NonNull java.util.List<android.net.Uri>);
method public void answer(int);
method public void conference(android.telecom.Call);
method public void deflect(android.net.Uri);
@@ -45563,6 +45565,7 @@ package android.telecom {
method public static boolean hasProperty(int, int);
method public boolean hasProperty(int);
method public static String propertiesToString(int);
+ field public static final int CAPABILITY_ADD_PARTICIPANT = 33554432; // 0x2000000
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
@@ -45592,6 +45595,7 @@ package android.telecom {
field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+ field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 8192; // 0x2000
field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800
field public static final int PROPERTY_RTT = 1024; // 0x400
@@ -45669,6 +45673,7 @@ package android.telecom {
public abstract class Conference extends android.telecom.Conferenceable {
ctor public Conference(android.telecom.PhoneAccountHandle);
method public final boolean addConnection(android.telecom.Connection);
+ method @NonNull public static android.telecom.Conference createFailedConference(@NonNull android.telecom.DisconnectCause, @NonNull android.telecom.PhoneAccountHandle);
method public final void destroy();
method public final android.telecom.CallAudioState getCallAudioState();
method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
@@ -45684,6 +45689,9 @@ package android.telecom {
method public final android.telecom.StatusHints getStatusHints();
method public android.telecom.Connection.VideoProvider getVideoProvider();
method public int getVideoState();
+ method public final boolean isRingbackRequested();
+ method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>);
+ method public void onAnswer(int);
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onConnectionAdded(android.telecom.Connection);
method public void onDisconnect();
@@ -45692,6 +45700,7 @@ package android.telecom {
method public void onMerge(android.telecom.Connection);
method public void onMerge();
method public void onPlayDtmfTone(char);
+ method public void onReject();
method public void onSeparate(android.telecom.Connection);
method public void onStopDtmfTone();
method public void onSwap();
@@ -45712,6 +45721,8 @@ package android.telecom {
method public final void setDisconnected(android.telecom.DisconnectCause);
method public final void setExtras(@Nullable android.os.Bundle);
method public final void setOnHold();
+ method public final void setRingbackRequested(boolean);
+ method public final void setRinging();
method public final void setStatusHints(android.telecom.StatusHints);
method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider);
method public final void setVideoState(android.telecom.Connection, int);
@@ -45748,6 +45759,7 @@ package android.telecom {
method public final boolean isRingbackRequested();
method public final void notifyConferenceMergeFailed();
method public void onAbort();
+ method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>);
method public void onAnswer(int);
method public void onAnswer();
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
@@ -45827,6 +45839,7 @@ package android.telecom {
field public static final int AUDIO_CODEC_GSM_HR = 10; // 0xa
field public static final int AUDIO_CODEC_NONE = 0; // 0x0
field public static final int AUDIO_CODEC_QCELP13K = 3; // 0x3
+ field public static final int CAPABILITY_ADD_PARTICIPANT = 67108864; // 0x4000000
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000
@@ -45870,6 +45883,7 @@ package android.telecom {
field public static final int PROPERTY_ASSISTED_DIALING = 512; // 0x200
field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
field public static final int PROPERTY_HIGH_DEF_AUDIO = 4; // 0x4
+ field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 4096; // 0x1000
field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10
field public static final int PROPERTY_IS_RTT = 256; // 0x100
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1024; // 0x400
@@ -45965,9 +45979,13 @@ package android.telecom {
method public void onConference(android.telecom.Connection, android.telecom.Connection);
method public void onConnectionServiceFocusGained();
method public void onConnectionServiceFocusLost();
+ method @Nullable public android.telecom.Conference onCreateIncomingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
+ method public void onCreateIncomingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method @Nullable public android.telecom.Conference onCreateOutgoingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
+ method public void onCreateOutgoingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
@@ -46278,6 +46296,7 @@ package android.telecom {
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall(int);
method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
+ method public void addNewIncomingConference(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void cancelMissedCallsNotification();
method public android.content.Intent createManageBlockedNumbersIntent();
method @Deprecated @RequiresPermission(android.Manifest.permission.ANSWER_PHONE_CALLS) public boolean endCall();
@@ -46305,6 +46324,7 @@ package android.telecom {
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void showInCallScreen(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void silenceRinger();
+ method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void startConference(@NonNull java.util.List<android.net.Uri>, @NonNull android.os.Bundle);
method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle);
field public static final String ACTION_CHANGE_DEFAULT_DIALER = "android.telecom.action.CHANGE_DEFAULT_DIALER";
field public static final String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
@@ -46844,6 +46864,8 @@ package android.telephony {
field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
field public static final String KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL = "support_3gpp_call_forwarding_while_roaming_bool";
+ field public static final String KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL = "support_add_conference_participants_bool";
+ field public static final String KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL = "support_adhoc_conference_calls_bool";
field public static final String KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL = "support_clir_network_default_bool";
field public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
field public static final String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool";
@@ -47843,6 +47865,7 @@ package android.telephony {
method @Nullable public android.net.LinkProperties getLinkProperties();
method public int getNetworkType();
method public int getState();
+ method public int getTransportType();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseDataConnectionState> CREATOR;
}
@@ -47916,12 +47939,13 @@ package android.telephony {
public final class SmsManager {
method public String createAppSpecificSmsToken(android.app.PendingIntent);
method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
+ method @NonNull public android.telephony.SmsManager createForSubscriptionId(int);
method public java.util.ArrayList<java.lang.String> divideMessage(String);
method public void downloadMultimediaMessage(android.content.Context, String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method @NonNull public android.os.Bundle getCarrierConfigValues();
- method public static android.telephony.SmsManager getDefault();
+ method @Deprecated public static android.telephony.SmsManager getDefault();
method public static int getDefaultSmsSubscriptionId();
- method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
+ method @Deprecated public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback);
method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress();
method public int getSubscriptionId();
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index c91c39a4293d..3f3b8eaffdab 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -31,6 +31,14 @@ package android.graphics {
}
+package android.media {
+
+ public class AudioManager {
+ field public static final int FLAG_FROM_KEY = 4096; // 0x1000
+ }
+
+}
+
package android.net {
public final class TetheringConstants {
@@ -77,6 +85,11 @@ package android.os {
method public final void markVintfStability();
}
+ public interface Parcelable {
+ field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
+ field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
+ }
+
public class StatsFrameworkInitializer {
method public static void registerServiceWrappers();
method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager);
diff --git a/api/system-current.txt b/api/system-current.txt
index 11db781dd42f..fb0d924673b8 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -10838,6 +10838,7 @@ package android.telephony {
method @Deprecated public int getDataConnectionApnTypeBitMask();
method @Deprecated public int getDataConnectionFailCause();
method @Deprecated public int getDataConnectionState();
+ method public int getId();
}
public final class PreciseDisconnectCause {
diff --git a/api/test-current.txt b/api/test-current.txt
index 866b9383d40b..963ef7c540c7 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -553,11 +553,13 @@ package android.app {
method public int getActivityType();
method public android.graphics.Rect getAppBounds();
method public android.graphics.Rect getBounds();
+ method @NonNull public android.graphics.Rect getMaxBounds();
method public int getRotation();
method public int getWindowingMode();
method public void setActivityType(int);
method public void setAppBounds(android.graphics.Rect);
method public void setBounds(android.graphics.Rect);
+ method public void setMaxBounds(@Nullable android.graphics.Rect);
method public void setRotation(int);
method public void setTo(android.app.WindowConfiguration);
method public void setWindowingMode(int);
diff --git a/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl
index 02b27a8800b6..403d8c55de16 100644
--- a/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl
+++ b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl
@@ -29,4 +29,5 @@ interface OverlayablePolicy {
const int ODM_PARTITION = 0x00000020;
const int OEM_PARTITION = 0x00000040;
const int ACTOR_SIGNATURE = 0x00000080;
+ const int CONFIG_SIGNATURE = 0x0000100;
}
diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp
index 34589a1c39dc..fd8b4eb86b4a 100644
--- a/cmds/idmap2/libidmap2/ResourceMapping.cpp
+++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp
@@ -61,10 +61,13 @@ Result<Unit> CheckOverlayable(const LoadedPackage& target_package,
const ResourceId& target_resource) {
static constexpr const PolicyBitmask sDefaultPolicies =
PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION | PolicyFlags::SYSTEM_PARTITION |
- PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE;
+ PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE |
+ PolicyFlags::CONFIG_SIGNATURE;
// If the resource does not have an overlayable definition, allow the resource to be overlaid if
- // the overlay is preinstalled or signed with the same signature as the target.
+ // the overlay is preinstalled, signed with the same signature as the target or signed with the
+ // same signature as reference package defined in SystemConfig under 'overlay-config-signature'
+ // tag.
if (!target_package.DefinesOverlayable()) {
return (sDefaultPolicies & fulfilled_policies) != 0
? Result<Unit>({})
diff --git a/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h
index f7987b01fe9e..cdce45191094 100644
--- a/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h
+++ b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h
@@ -38,16 +38,18 @@ constexpr const char* kPolicyOdm = "odm";
constexpr const char* kPolicyOem = "oem";
constexpr const char* kPolicyProduct = "product";
constexpr const char* kPolicyPublic = "public";
+constexpr const char* kPolicyConfigSignature = "config_signature";
constexpr const char* kPolicySignature = "signature";
constexpr const char* kPolicySystem = "system";
constexpr const char* kPolicyVendor = "vendor";
-inline static const std::array<std::pair<StringPiece, PolicyFlags>, 8> kPolicyStringToFlag = {
+inline static const std::array<std::pair<StringPiece, PolicyFlags>, 9> kPolicyStringToFlag = {
std::pair{kPolicyActor, PolicyFlags::ACTOR_SIGNATURE},
{kPolicyOdm, PolicyFlags::ODM_PARTITION},
{kPolicyOem, PolicyFlags::OEM_PARTITION},
{kPolicyProduct, PolicyFlags::PRODUCT_PARTITION},
{kPolicyPublic, PolicyFlags::PUBLIC},
+ {kPolicyConfigSignature, PolicyFlags::CONFIG_SIGNATURE},
{kPolicySignature, PolicyFlags::SIGNATURE},
{kPolicySystem, PolicyFlags::SYSTEM_PARTITION},
{kPolicyVendor, PolicyFlags::VENDOR_PARTITION},
diff --git a/cmds/idmap2/tests/R.h b/cmds/idmap2/tests/R.h
index 4f2ee1c4880a..854b57fb22aa 100644
--- a/cmds/idmap2/tests/R.h
+++ b/cmds/idmap2/tests/R.h
@@ -43,16 +43,17 @@ namespace R::target {
constexpr ResourceId not_overlayable = 0x7f020003;
constexpr ResourceId other = 0x7f020004;
constexpr ResourceId policy_actor = 0x7f020005;
- constexpr ResourceId policy_odm = 0x7f020006;
- constexpr ResourceId policy_oem = 0x7f020007;
- constexpr ResourceId policy_product = 0x7f020008;
- constexpr ResourceId policy_public = 0x7f020009;
- constexpr ResourceId policy_signature = 0x7f02000a;
- constexpr ResourceId policy_system = 0x7f02000b;
- constexpr ResourceId policy_system_vendor = 0x7f02000c;
- constexpr ResourceId str1 = 0x7f02000d;
- constexpr ResourceId str3 = 0x7f02000f;
- constexpr ResourceId str4 = 0x7f020010;
+ constexpr ResourceId policy_config_signature = 0x7f020006;
+ constexpr ResourceId policy_odm = 0x7f020007;
+ constexpr ResourceId policy_oem = 0x7f020008;
+ constexpr ResourceId policy_product = 0x7f020009;
+ constexpr ResourceId policy_public = 0x7f02000a;
+ constexpr ResourceId policy_signature = 0x7f02000b;
+ constexpr ResourceId policy_system = 0x7f02000c;
+ constexpr ResourceId policy_system_vendor = 0x7f02000d;
+ constexpr ResourceId str1 = 0x7f02000e;
+ constexpr ResourceId str3 = 0x7f020010;
+ constexpr ResourceId str4 = 0x7f020011;
namespace literal { // NOLINT(runtime/indentation_namespace)
inline const std::string str1 = hexify(R::target::string::str1);
@@ -94,13 +95,14 @@ namespace R::system_overlay_invalid::string {
constexpr ResourceId not_overlayable = 0x7f010000;
constexpr ResourceId other = 0x7f010001;
constexpr ResourceId policy_actor = 0x7f010002;
- constexpr ResourceId policy_odm = 0x7f010003;
- constexpr ResourceId policy_oem = 0x7f010004;
- constexpr ResourceId policy_product = 0x7f010005;
- constexpr ResourceId policy_public = 0x7f010006;
- constexpr ResourceId policy_signature = 0x7f010007;
- constexpr ResourceId policy_system = 0x7f010008;
- constexpr ResourceId policy_system_vendor = 0x7f010009;
+ constexpr ResourceId policy_config_signature = 0x7f010003;
+ constexpr ResourceId policy_odm = 0x7f010004;
+ constexpr ResourceId policy_oem = 0x7f010005;
+ constexpr ResourceId policy_product = 0x7f010006;
+ constexpr ResourceId policy_public = 0x7f010007;
+ constexpr ResourceId policy_signature = 0x7f010008;
+ constexpr ResourceId policy_system = 0x7f010009;
+ constexpr ResourceId policy_system_vendor = 0x7f01000a;
} // namespace R::system_overlay_invalid::string
// clang-format on
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index de039f440e33..3ec6ac24b238 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -237,7 +237,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
- ASSERT_EQ(res.GetTargetToOverlayMap().size(), 10U);
+ ASSERT_EQ(res.GetTargetToOverlayMap().size(), 11U);
ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::not_overlayable,
false /* rewrite */));
@@ -256,6 +256,10 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_public,
false /* rewrite */));
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
+ Res_value::TYPE_REFERENCE,
+ R::system_overlay_invalid::string::policy_config_signature,
+ false /* rewrite */));
ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_signature,
false /* rewrite */));
@@ -298,8 +302,9 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) {
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
}
-// Overlays that are pre-installed or are signed with the same signature as the target can overlay
-// packages that have not defined overlayable resources.
+// Overlays that are pre-installed or are signed with the same signature as the target or are signed
+// with the same signature as the reference package can overlay packages that have not defined
+// overlayable resources.
TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void {
auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
@@ -309,7 +314,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources;
- ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 10U);
+ ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 11U);
ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::not_overlayable,
false /* rewrite */));
@@ -330,6 +335,10 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_public,
false /* rewrite */));
+ ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
+ Res_value::TYPE_REFERENCE,
+ R::system_overlay_invalid::string::policy_config_signature,
+ false /* rewrite */));
ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
R::system_overlay_invalid::string::policy_signature,
false /* rewrite */));
@@ -342,6 +351,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
};
CheckEntries(PolicyFlags::SIGNATURE);
+ CheckEntries(PolicyFlags::CONFIG_SIGNATURE);
CheckEntries(PolicyFlags::PRODUCT_PARTITION);
CheckEntries(PolicyFlags::SYSTEM_PARTITION);
CheckEntries(PolicyFlags::VENDOR_PARTITION);
diff --git a/cmds/idmap2/tests/TestConstants.h b/cmds/idmap2/tests/TestConstants.h
index 74ea18f88648..9641f6b55670 100644
--- a/cmds/idmap2/tests/TestConstants.h
+++ b/cmds/idmap2/tests/TestConstants.h
@@ -19,11 +19,11 @@
namespace android::idmap2::TestConstants {
-constexpr const auto TARGET_CRC = 0x41c60c8c;
-constexpr const auto TARGET_CRC_STRING = "41c60c8c";
+constexpr const auto TARGET_CRC = 0x7c2d4719;
+constexpr const auto TARGET_CRC_STRING = "7c2d4719";
-constexpr const auto OVERLAY_CRC = 0xc054fb26;
-constexpr const auto OVERLAY_CRC_STRING = "c054fb26";
+constexpr const auto OVERLAY_CRC = 0x5afff726;
+constexpr const auto OVERLAY_CRC_STRING = "5afff726";
} // namespace android::idmap2::TestConstants
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
index 7c25985e5a61..dab25b1f8131 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
index c75f3e1dbddf..c8b95c2601ad 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-shared.apk b/cmds/idmap2/tests/data/overlay/overlay-shared.apk
index 93dcc82f9358..0a8b7372172e 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-shared.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-shared.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
index 5b8a6e4a90ed..fd41182f8493 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
index 698a1fd6e702..b24765fc666a 100644
--- a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay.apk b/cmds/idmap2/tests/data/overlay/overlay.apk
index 1db303ff05b5..870575efa10c 100644
--- a/cmds/idmap2/tests/data/overlay/overlay.apk
+++ b/cmds/idmap2/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
index 51e19de082ed..e0fd20499671 100644
--- a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
+++ b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
index 7119d8283061..ebaf49c34762 100644
--- a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
@@ -26,6 +26,7 @@
<string name="policy_odm">policy_odm</string>
<string name="policy_oem">policy_oem</string>
<string name="policy_actor">policy_actor</string>
+ <string name="policy_config_signature">policy_config_signature</string>
<!-- Requests to overlay a resource that is not declared as overlayable. -->
<string name="not_overlayable">not_overlayable</string>
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
index bd990983693c..a63daf86caf5 100644
--- a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/system-overlay/system-overlay.apk b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
index a0fba4378b57..90d2803a1eca 100644
--- a/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
+++ b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/target/res/values/overlayable.xml b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
index ad4cd4882632..57e6c439c23c 100644
--- a/cmds/idmap2/tests/data/target/res/values/overlayable.xml
+++ b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
@@ -45,6 +45,10 @@
<item type="string" name="policy_actor" />
</policy>
+ <policy type="config_signature">
+ <item type="string" name="policy_config_signature"/>
+ </policy>
+
<!-- Resources publicly overlayable -->
<policy type="public">
<item type="string" name="policy_public" />
diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml
index 5230e25e626b..00909a9e481c 100644
--- a/cmds/idmap2/tests/data/target/res/values/values.xml
+++ b/cmds/idmap2/tests/data/target/res/values/values.xml
@@ -37,6 +37,7 @@
<string name="policy_system">policy_system</string>
<string name="policy_system_vendor">policy_system_vendor</string>
<string name="policy_actor">policy_actor</string>
+ <string name="policy_config_signature">policy_config_signature</string>
<string name="other">other</string>
</resources>
diff --git a/cmds/idmap2/tests/data/target/target-no-overlayable.apk b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
index 58504a74a83a..cc3491de894d 100644
--- a/cmds/idmap2/tests/data/target/target-no-overlayable.apk
+++ b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk
index c80e5eb65ff2..4a58c5e28f49 100644
--- a/cmds/idmap2/tests/data/target/target.apk
+++ b/cmds/idmap2/tests/data/target/target.apk
Binary files differ
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index c1d8399d91a5..a46a54cc2063 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -182,16 +182,17 @@ int main(int argc, char** argv)
ProcessState::self()->setThreadPoolMaxThreadCount(0);
ProcessState::self()->startThreadPool();
- ui::Dataspace outDataspace;
- sp<GraphicBuffer> outBuffer;
-
- status_t result = ScreenshotClient::capture(*displayId, &outDataspace, &outBuffer);
+ ScreenCaptureResults captureResults;
+ status_t result = ScreenshotClient::captureDisplay(*displayId, captureResults);
if (result != NO_ERROR) {
close(fd);
return 1;
}
- result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);
+ ui::Dataspace dataspace = captureResults.capturedDataspace;
+ sp<GraphicBuffer> buffer = captureResults.buffer;
+
+ result = buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);
if (base == nullptr || result != NO_ERROR) {
String8 reason;
@@ -207,13 +208,13 @@ int main(int argc, char** argv)
if (png) {
AndroidBitmapInfo info;
- info.format = flinger2bitmapFormat(outBuffer->getPixelFormat());
+ info.format = flinger2bitmapFormat(buffer->getPixelFormat());
info.flags = ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
- info.width = outBuffer->getWidth();
- info.height = outBuffer->getHeight();
- info.stride = outBuffer->getStride() * bytesPerPixel(outBuffer->getPixelFormat());
+ info.width = buffer->getWidth();
+ info.height = buffer->getHeight();
+ info.stride = buffer->getStride() * bytesPerPixel(buffer->getPixelFormat());
- int result = AndroidBitmap_compress(&info, static_cast<int32_t>(outDataspace), base,
+ int result = AndroidBitmap_compress(&info, static_cast<int32_t>(dataspace), base,
ANDROID_BITMAP_COMPRESS_FORMAT_PNG, 100, &fd,
[](void* fdPtr, const void* data, size_t size) -> bool {
int bytesWritten = write(*static_cast<int*>(fdPtr),
@@ -229,11 +230,11 @@ int main(int argc, char** argv)
notifyMediaScanner(fn);
}
} else {
- uint32_t w = outBuffer->getWidth();
- uint32_t h = outBuffer->getHeight();
- uint32_t s = outBuffer->getStride();
- uint32_t f = outBuffer->getPixelFormat();
- uint32_t c = dataSpaceToInt(outDataspace);
+ uint32_t w = buffer->getWidth();
+ uint32_t h = buffer->getHeight();
+ uint32_t s = buffer->getStride();
+ uint32_t f = buffer->getPixelFormat();
+ uint32_t c = dataSpaceToInt(dataspace);
write(fd, &w, 4);
write(fd, &h, 4);
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 124f815f51f0..1579715727ac 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -171,7 +171,8 @@ cc_library_static {
export_generated_headers: ["statslog_statsdtest.h"],
shared_libs: [
"libstatssocket",
- ]
+ "libstatspull",
+ ],
}
cc_library_static {
@@ -185,7 +186,11 @@ cc_library_static {
],
shared_libs: [
"libstatssocket",
- ]
+ "libstatspull",
+ ],
+ export_shared_lib_headers: [
+ "libstatspull",
+ ],
}
// =========
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 05e9ec3a1769..6327490b0b71 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -120,10 +120,9 @@ static void flushProtoToBuffer(ProtoOutputStream& proto, vector<uint8_t>* outDat
}
}
-void StatsLogProcessor::onAnomalyAlarmFired(
+void StatsLogProcessor::processFiredAnomalyAlarmsLocked(
const int64_t& timestampNs,
unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet) {
- std::lock_guard<std::mutex> lock(mMetricsMutex);
for (const auto& itr : mMetricsManagers) {
itr.second->onAnomalyAlarmFired(timestampNs, alarmSet);
}
@@ -429,6 +428,20 @@ void StatsLogProcessor::OnLogEvent(LogEvent* event, int64_t elapsedRealtimeNs) {
return;
}
+ bool fireAlarm = false;
+ {
+ std::lock_guard<std::mutex> anomalyLock(mAnomalyAlarmMutex);
+ if (mNextAnomalyAlarmTime != 0 &&
+ MillisToNano(mNextAnomalyAlarmTime) <= elapsedRealtimeNs) {
+ mNextAnomalyAlarmTime = 0;
+ VLOG("informing anomaly alarm at time %lld", (long long)elapsedRealtimeNs);
+ fireAlarm = true;
+ }
+ }
+ if (fireAlarm) {
+ informAnomalyAlarmFiredLocked(NanoToMillis(elapsedRealtimeNs));
+ }
+
int64_t curTimeSec = getElapsedRealtimeSec();
if (curTimeSec - mLastPullerCacheClearTimeSec > StatsdStats::kPullerCacheClearIntervalSec) {
mPullerManager->ClearPullerCacheIfNecessary(curTimeSec * NS_PER_SEC);
@@ -513,19 +526,34 @@ void StatsLogProcessor::OnConfigUpdated(const int64_t timestampNs, const ConfigK
OnConfigUpdatedLocked(timestampNs, key, config);
}
-void StatsLogProcessor::OnConfigUpdatedLocked(
- const int64_t timestampNs, const ConfigKey& key, const StatsdConfig& config) {
+void StatsLogProcessor::OnConfigUpdatedLocked(const int64_t timestampNs, const ConfigKey& key,
+ const StatsdConfig& config, bool modularUpdate) {
VLOG("Updated configuration for key %s", key.ToString().c_str());
- sp<MetricsManager> newMetricsManager =
- new MetricsManager(key, config, mTimeBaseNs, timestampNs, mUidMap, mPullerManager,
- mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
- if (newMetricsManager->isConfigValid()) {
- newMetricsManager->init();
- mUidMap->OnConfigUpdated(key);
- newMetricsManager->refreshTtl(timestampNs);
- mMetricsManagers[key] = newMetricsManager;
- VLOG("StatsdConfig valid");
+ // Create new config if this is not a modular update or if this is a new config.
+ const auto& it = mMetricsManagers.find(key);
+ bool configValid = false;
+ if (!modularUpdate || it == mMetricsManagers.end()) {
+ sp<MetricsManager> newMetricsManager =
+ new MetricsManager(key, config, mTimeBaseNs, timestampNs, mUidMap, mPullerManager,
+ mAnomalyAlarmMonitor, mPeriodicAlarmMonitor);
+ configValid = newMetricsManager->isConfigValid();
+ if (configValid) {
+ newMetricsManager->init();
+ mUidMap->OnConfigUpdated(key);
+ newMetricsManager->refreshTtl(timestampNs);
+ mMetricsManagers[key] = newMetricsManager;
+ VLOG("StatsdConfig valid");
+ }
} else {
+ // Preserve the existing MetricsManager, update necessary components and metadata in place.
+ configValid = it->second->updateConfig(timestampNs, config);
+ if (configValid) {
+ // TODO(b/162323476): refresh TTL, ensure init() is handled properly.
+ mUidMap->OnConfigUpdated(key);
+
+ }
+ }
+ if (!configValid) {
// If there is any error in the config, don't use it.
// Remove any existing config with the same key.
ALOGE("StatsdConfig NOT valid");
@@ -1090,6 +1118,28 @@ void StatsLogProcessor::noteOnDiskData(const ConfigKey& key) {
mOnDiskDataConfigs.insert(key);
}
+void StatsLogProcessor::setAnomalyAlarm(const int64_t elapsedTimeMillis) {
+ std::lock_guard<std::mutex> lock(mAnomalyAlarmMutex);
+ mNextAnomalyAlarmTime = elapsedTimeMillis;
+}
+
+void StatsLogProcessor::cancelAnomalyAlarm() {
+ std::lock_guard<std::mutex> lock(mAnomalyAlarmMutex);
+ mNextAnomalyAlarmTime = 0;
+}
+
+void StatsLogProcessor::informAnomalyAlarmFiredLocked(const int64_t elapsedTimeMillis) {
+ VLOG("StatsService::informAlarmForSubscriberTriggeringFired was called");
+ std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
+ mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(elapsedTimeMillis / 1000));
+ if (alarmSet.size() > 0) {
+ VLOG("Found periodic alarm fired.");
+ processFiredAnomalyAlarmsLocked(MillisToNano(elapsedTimeMillis), alarmSet);
+ } else {
+ ALOGW("Cannot find an periodic alarm that fired. Perhaps it was recently cancelled.");
+ }
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index c0f54a0995ac..383dbd9db2c1 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -66,11 +66,6 @@ public:
const DumpLatency dumpLatency,
ProtoOutputStream* proto);
- /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
- void onAnomalyAlarmFired(
- const int64_t& timestampNs,
- unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
-
/* Tells MetricsManager that the alarms in alarmSet have fired. Modifies periodic alarmSet. */
void onPeriodicAlarmFired(
const int64_t& timestampNs,
@@ -146,6 +141,10 @@ public:
// Add a specific config key to the possible configs to dump ASAP.
void noteOnDiskData(const ConfigKey& key);
+ void setAnomalyAlarm(const int64_t timeMillis);
+
+ void cancelAnomalyAlarm();
+
private:
// For testing only.
inline sp<AlarmMonitor> getAnomalyAlarmMonitor() const {
@@ -158,6 +157,11 @@ private:
mutable mutex mMetricsMutex;
+ // Guards mNextAnomalyAlarmTime. A separate mutex is needed because alarms are set/cancelled
+ // in the onLogEvent code path, which is locked by mMetricsMutex.
+ // DO NOT acquire mMetricsMutex while holding mAnomalyAlarmMutex. This can lead to a deadlock.
+ mutable mutex mAnomalyAlarmMutex;
+
std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers;
std::unordered_map<ConfigKey, int64_t> mLastBroadcastTimes;
@@ -183,8 +187,8 @@ private:
void resetIfConfigTtlExpiredLocked(const int64_t timestampNs);
- void OnConfigUpdatedLocked(
- const int64_t currentTimestampNs, const ConfigKey& key, const StatsdConfig& config);
+ void OnConfigUpdatedLocked(const int64_t currentTimestampNs, const ConfigKey& key,
+ const StatsdConfig& config, bool modularUpdate = false);
void GetActiveConfigsLocked(const int uid, vector<int64_t>& outActiveConfigs);
@@ -248,6 +252,15 @@ private:
// Reset the specified configs.
void resetConfigsLocked(const int64_t timestampNs, const std::vector<ConfigKey>& configs);
+ // An anomaly alarm should have fired.
+ // Check with anomaly alarm manager to find the alarms and process the result.
+ void informAnomalyAlarmFiredLocked(const int64_t elapsedTimeMillis);
+
+ /* Tells MetricsManager that the alarms in alarmSet have fired. Modifies anomaly alarmSet. */
+ void processFiredAnomalyAlarmsLocked(
+ const int64_t& timestampNs,
+ unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet);
+
// Function used to send a broadcast so that receiver for the config key can call getData
// to retrieve the stored data.
std::function<bool(const ConfigKey& key)> mSendBroadcast;
@@ -274,6 +287,9 @@ private:
//Last time we wrote metadata to disk.
int64_t mLastMetadataWriteNs = 0;
+ // The time for the next anomaly alarm for alerts.
+ int64_t mNextAnomalyAlarmTime = 0;
+
bool mPrintAllLogs = false;
FRIEND_TEST(StatsLogProcessorTest, TestOutOfOrderLogs);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index d5e331495164..68c2dd56ef13 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -91,17 +91,13 @@ Status checkUid(uid_t expectedUid) {
StatsService::StatsService(const sp<Looper>& handlerLooper, shared_ptr<LogEventQueue> queue)
: mAnomalyAlarmMonitor(new AlarmMonitor(
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
- [](const shared_ptr<IStatsCompanionService>& sc, int64_t timeMillis) {
- if (sc != nullptr) {
- sc->setAnomalyAlarm(timeMillis);
- StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
- }
+ [this](const shared_ptr<IStatsCompanionService>& /*sc*/, int64_t timeMillis) {
+ mProcessor->setAnomalyAlarm(timeMillis);
+ StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
},
- [](const shared_ptr<IStatsCompanionService>& sc) {
- if (sc != nullptr) {
- sc->cancelAnomalyAlarm();
- StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
- }
+ [this](const shared_ptr<IStatsCompanionService>& /*sc*/) {
+ mProcessor->cancelAnomalyAlarm();
+ StatsdStats::getInstance().noteRegisteredAnomalyAlarmChanged();
})),
mPeriodicAlarmMonitor(new AlarmMonitor(
MIN_DIFF_TO_UPDATE_REGISTERED_ALARM_SECS,
@@ -977,22 +973,6 @@ Status StatsService::informOnePackageRemoved(const string& app, int32_t uid) {
return Status::ok();
}
-Status StatsService::informAnomalyAlarmFired() {
- ENFORCE_UID(AID_SYSTEM);
-
- VLOG("StatsService::informAnomalyAlarmFired was called");
- int64_t currentTimeSec = getElapsedRealtimeSec();
- std::unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>> alarmSet =
- mAnomalyAlarmMonitor->popSoonerThan(static_cast<uint32_t>(currentTimeSec));
- if (alarmSet.size() > 0) {
- VLOG("Found an anomaly alarm that fired.");
- mProcessor->onAnomalyAlarmFired(currentTimeSec * NS_PER_SEC, alarmSet);
- } else {
- VLOG("Cannot find an anomaly alarm that fired. Perhaps it was recently cancelled.");
- }
- return Status::ok();
-}
-
Status StatsService::informAlarmForSubscriberTriggeringFired() {
ENFORCE_UID(AID_SYSTEM);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 324ffbd65e51..479f4e87ec96 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -66,7 +66,6 @@ public:
virtual Status systemRunning();
virtual Status statsCompanionReady();
virtual Status bootCompleted();
- virtual Status informAnomalyAlarmFired();
virtual Status informPollAlarmFired();
virtual Status informAlarmForSubscriberTriggeringFired();
@@ -404,6 +403,10 @@ private:
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricOnBootWithoutMinPartialBucket);
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithoutMinPartialBucket);
FRIEND_TEST(PartialBucketE2eTest, TestGaugeMetricWithMinPartialBucket);
+
+ FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
+ FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
+ FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
};
} // namespace statsd
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index e70eac88c769..c95f4c07f86c 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -66,7 +66,7 @@ import "frameworks/base/core/proto/android/stats/textclassifier/textclassifier_e
import "frameworks/base/core/proto/android/stats/otaupdate/updateengine_enums.proto";
/**
- * The master atom class. This message defines all of the available
+ * The primary atom class. This message defines all of the available
* raw stats log events from the Android system, also known as "atoms."
*
* This field contains a single oneof with all of the available messages.
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index bbae3fef7934..13020e06dc5d 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -128,7 +128,7 @@ void ConfigManager::Startup() {
}
void ConfigManager::StartupForTest() {
- // Dummy function to avoid reading configs from disks for tests.
+ // No-op function to avoid reading configs from disks for tests.
}
void ConfigManager::AddListener(const sp<ConfigListener>& listener) {
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index 40146b1b2bec..bef057f96409 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -46,7 +46,7 @@ public:
void Startup();
/*
- * Dummy initializer for tests.
+ * No-op initializer for tests.
*/
void StartupForTest();
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index 60de1a24cce5..189d8117ae55 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -195,6 +195,10 @@ MetricsManager::~MetricsManager() {
VLOG("~MetricsManager()");
}
+bool MetricsManager::updateConfig(const int64_t currentTimeNs, const StatsdConfig& config) {
+ return mConfigValid;
+}
+
void MetricsManager::initLogSourceWhiteList() {
std::lock_guard<std::mutex> lock(mAllowedLogSourcesMutex);
mAllowedLogSources.clear();
diff --git a/cmds/statsd/src/metrics/MetricsManager.h b/cmds/statsd/src/metrics/MetricsManager.h
index ad30a88c5d19..042de29e173d 100644
--- a/cmds/statsd/src/metrics/MetricsManager.h
+++ b/cmds/statsd/src/metrics/MetricsManager.h
@@ -46,6 +46,8 @@ public:
virtual ~MetricsManager();
+ bool updateConfig(const int64_t currentTimeNs, const StatsdConfig& config);
+
// Return whether the configuration is valid.
bool isConfigValid() const;
diff --git a/cmds/statsd/src/packages/PackageInfoListener.h b/cmds/statsd/src/packages/PackageInfoListener.h
index 6c50a8c41770..1bc84c5433f9 100644
--- a/cmds/statsd/src/packages/PackageInfoListener.h
+++ b/cmds/statsd/src/packages/PackageInfoListener.h
@@ -17,6 +17,8 @@
#ifndef STATSD_PACKAGE_INFO_LISTENER_H
#define STATSD_PACKAGE_INFO_LISTENER_H
+#include <utils/RefBase.h>
+
#include <string>
namespace android {
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 22250aee402e..622321b804ec 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -17,7 +17,6 @@
#pragma once
#include "config/ConfigKey.h"
-#include "config/ConfigListener.h"
#include "packages/PackageInfoListener.h"
#include "stats_util.h"
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 26423d464027..6264c075426a 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -13,9 +13,6 @@
// limitations under the License.
#include <gtest/gtest.h>
-#include <log/log_event_list.h>
-#include <log/log_read.h>
-#include <log/logprint.h>
#include <stdio.h>
#include "annotations.h"
diff --git a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
index 95e301002a1b..70e7365ec238 100644
--- a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
@@ -12,14 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
#include <gtest/gtest.h>
-#include "src/anomaly/DurationAnomalyTracker.h"
+#include <vector>
+
#include "src/StatsLogProcessor.h"
+#include "src/StatsService.h"
+#include "src/anomaly/DurationAnomalyTracker.h"
#include "src/stats_log_util.h"
#include "tests/statsd_test_util.h"
-#include <vector>
+using ::ndk::SharedRefBase;
namespace android {
namespace os {
@@ -29,6 +34,9 @@ namespace statsd {
namespace {
+const int kConfigKey = 789130124;
+const int kCallingUid = 0;
+
StatsdConfig CreateStatsdConfig(int num_buckets,
uint64_t threshold_ns,
DurationMetric::AggregationType aggregationType,
@@ -89,6 +97,13 @@ MetricDimensionKey dimensionKey2(
(int32_t)0x02010101), Value((int32_t)222))}),
DEFAULT_DIMENSION_KEY);
+void sendConfig(shared_ptr<StatsService>& service, const StatsdConfig& config) {
+ string str;
+ config.SerializeToString(&str);
+ std::vector<uint8_t> configAsVec(str.begin(), str.end());
+ service->addConfiguration(kConfigKey, configAsVec, kCallingUid);
+}
+
} // namespace
TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
@@ -98,16 +113,18 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
- int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
+ shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+ sendConfig(service, config);
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+ int64_t bucketStartTimeNs = processor->mTimeBaseNs;
+ int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
+
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -158,12 +175,13 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
(uint32_t)alarmFiredTimestampSec0);
+ EXPECT_EQ(alarmFiredTimestampSec0,
+ processor->getAnomalyAlarmMonitor()->getRegisteredAlarmTimeSec());
// Anomaly alarm fired.
- auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
- static_cast<uint32_t>(alarmFiredTimestampSec0));
- ASSERT_EQ(1u, alarmSet.size());
- processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
+ auto alarmTriggerEvent = CreateBatterySaverOnEvent(alarmFiredTimestampSec0 * NS_PER_SEC);
+ processor->OnLogEvent(alarmTriggerEvent.get(), alarmFiredTimestampSec0 * NS_PER_SEC);
+
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
@@ -179,39 +197,39 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock wl1.
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11,
- attributionUids2, attributionTags2, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC - 11, attributionUids2,
+ attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey1);
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
(uint64_t)alarmFiredTimestampSec1);
// Release wakelock wl1.
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10,
- attributionUids2, attributionTags2, "wl1");
- processor->OnLogEvent(release_event.get());
+ int64_t release_event_time = roundedBucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
+ auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
static_cast<uint32_t>(alarmFiredTimestampSec1));
ASSERT_EQ(0u, alarmSet.size());
// Acquire wakelock wl1 near the end of bucket #0.
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 2,
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - 2,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Release the event at early bucket #1.
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Anomaly detected when stopping the alarm. The refractory period does not change.
EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
@@ -236,17 +254,17 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
// Condition turns true.
screen_off_event =
- CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC,
+ CreateScreenStateChangedEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC,
android::view::DisplayStateEnum::DISPLAY_STATE_OFF);
processor->OnLogEvent(screen_off_event.get());
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Condition turns to false.
- screen_on_event =
- CreateScreenStateChangedEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1,
- android::view::DisplayStateEnum::DISPLAY_STATE_ON);
- processor->OnLogEvent(screen_on_event.get());
+ int64_t condition_false_time = bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1;
+ screen_on_event = CreateScreenStateChangedEvent(
+ condition_false_time, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+ processor->OnLogEvent(screen_on_event.get(), condition_false_time);
// Condition turns to false. Cancelled the alarm.
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Detected one anomaly.
@@ -262,12 +280,11 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC,
- attributionUids2, attributionTags2, "wl1");
+ release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
processor->OnLogEvent(release_event.get());
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
}
@@ -279,16 +296,18 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
const uint64_t alert_id = config.alert(0).id();
const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
- int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
+ shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+ sendConfig(service, config);
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+ int64_t bucketStartTimeNs = processor->mTimeBaseNs;
+ int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
+
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -298,96 +317,97 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
// Acquire wakelock "wc1" in bucket #0.
auto acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1,
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - NS_PER_SEC / 2 - 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock "wc1" in bucket #0.
- auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs - 1,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ int64_t release_event_time = roundedBucketStartTimeNs + bucketSizeNs - 1;
+ auto release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock "wc1" in bucket #1.
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 1,
- attributionUids2, attributionTags2, "wl1");
+ acquire_event =
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC + 1,
+ attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + bucketSizeNs + 100,
- attributionUids2, attributionTags2, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + bucketSizeNs + NS_PER_SEC + 100;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire wakelock "wc2" in bucket #2.
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
- attributionUids3, attributionTags3, "wl2");
+ acquire_event =
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + 1,
+ attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2,
+ EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Release wakelock "wc2" in bucket #2.
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
- attributionUids3, attributionTags3, "wl2");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids3,
+ attributionTags3, "wl2");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
- EXPECT_EQ(refractory_period_sec +
- (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
// Acquire wakelock "wc1" in bucket #2.
acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC,
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs + 3 * NS_PER_SEC,
attributionUids2, attributionTags2, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 3 + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Release wakelock "wc1" in bucket #2.
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC,
- attributionUids2, attributionTags2, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 2 * bucketSizeNs + 3.5 * NS_PER_SEC;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids2,
+ attributionTags2, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- EXPECT_EQ(refractory_period_sec +
- (int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) /
- NS_PER_SEC +
- 1,
+ EXPECT_EQ(refractory_period_sec + (release_event_time) / NS_PER_SEC + 1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4,
- attributionUids3, attributionTags3, "wl2");
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 6 * bucketSizeNs + 4,
+ attributionUids3, attributionTags3, "wl2");
processor->OnLogEvent(acquire_event.get());
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 6 * bucketSizeNs + 5,
+ attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 2,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+ EXPECT_EQ((roundedBucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 2,
anomalyTracker->getAlarmTimestampSec(dimensionKey2));
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 2,
- attributionUids3, attributionTags3, "wl2");
- processor->OnLogEvent(release_event.get());
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 6 * bucketSizeNs + 6,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 6 * bucketSizeNs + NS_PER_SEC + 2;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids3,
+ attributionTags3, "wl2");
+ processor->OnLogEvent(release_event.get(), release_event_time);
+ release_event = CreateReleaseWakelockEvent(release_event_time + 4, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time + 4);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
// The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
- EXPECT_EQ(refractory_period_sec + (int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC +
+ EXPECT_EQ(refractory_period_sec +
+ (int64_t)(roundedBucketStartTimeNs + 6 * bucketSizeNs + NS_PER_SEC) /
+ NS_PER_SEC +
1,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
}
@@ -396,20 +416,22 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
const int num_buckets = 2;
const uint64_t threshold_ns = 3 * NS_PER_SEC;
auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
- int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
- int64_t bucketSizeNs =
- TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
-
const uint64_t alert_id = config.alert(0).id();
+ int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1e6;
const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
- ConfigKey cfgKey;
- auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+ shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+ sendConfig(service, config);
+
+ auto processor = service->mProcessor;
ASSERT_EQ(processor->mMetricsManagers.size(), 1u);
EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
ASSERT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+ int64_t bucketStartTimeNs = processor->mTimeBaseNs;
+ int64_t roundedBucketStartTimeNs = bucketStartTimeNs / NS_PER_SEC * NS_PER_SEC;
+
sp<AnomalyTracker> anomalyTracker =
processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
@@ -418,81 +440,81 @@ TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
processor->OnLogEvent(screen_off_event.get());
// Acquire wakelock "wc1" in bucket #0.
- auto acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs - 100,
+ auto acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs - 100,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+ EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Acquire the wakelock "wc1" again.
acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1,
+ CreateAcquireWakelockEvent(roundedBucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
// The alarm does not change.
- EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+ EXPECT_EQ((roundedBucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// Anomaly alarm fired late.
- const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
- auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
- static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
- ASSERT_EQ(1u, alarmSet.size());
- processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
+ const int64_t firedAlarmTimestampNs = roundedBucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
+ auto alarmTriggerEvent = CreateBatterySaverOnEvent(firedAlarmTimestampNs);
+ processor->OnLogEvent(alarmTriggerEvent.get(), firedAlarmTimestampNs);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- acquire_event = CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs - 100,
+ acquire_event = CreateAcquireWakelockEvent(roundedBucketStartTimeNs + 2 * bucketSizeNs - 100,
attributionUids1, attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- auto release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 1,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ int64_t release_event_time = bucketStartTimeNs + 2 * bucketSizeNs + 1;
+ auto release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
// Within the refractory period. No anomaly.
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
// A new wakelock, but still within refractory period.
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC, attributionUids1,
+ attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- release_event = CreateReleaseWakelockEvent(bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC,
- attributionUids1, attributionTags1, "wl1");
+ release_event =
+ CreateReleaseWakelockEvent(roundedBucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC,
+ attributionUids1, attributionTags1, "wl1");
// Still in the refractory period. No anomaly.
processor->OnLogEvent(release_event.get());
EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 5, attributionUids1,
+ attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+ EXPECT_EQ((roundedBucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- release_event =
- CreateReleaseWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4,
- attributionUids1, attributionTags1, "wl1");
- processor->OnLogEvent(release_event.get());
+ release_event_time = roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 4;
+ release_event = CreateReleaseWakelockEvent(release_event_time, attributionUids1,
+ attributionTags1, "wl1");
+ processor->OnLogEvent(release_event.get(), release_event_time);
EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey1));
- acquire_event =
- CreateAcquireWakelockEvent(bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3,
- attributionUids1, attributionTags1, "wl1");
+ acquire_event = CreateAcquireWakelockEvent(
+ roundedBucketStartTimeNs + 5 * bucketSizeNs - 2 * NS_PER_SEC - 3, attributionUids1,
+ attributionTags1, "wl1");
processor->OnLogEvent(acquire_event.get());
- EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+ EXPECT_EQ((roundedBucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC + 1,
anomalyTracker->getAlarmTimestampSec(dimensionKey1));
}
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index fed9c43faa38..5f13a5ce3aae 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -69,6 +69,7 @@ public final class Telecom extends BaseCommand {
private static final String COMMAND_SET_DEFAULT_DIALER = "set-default-dialer";
private static final String COMMAND_GET_DEFAULT_DIALER = "get-default-dialer";
private static final String COMMAND_STOP_BLOCK_SUPPRESSION = "stop-block-suppression";
+ private static final String COMMAND_CLEANUP_STUCK_CALLS = "cleanup-stuck-calls";
/**
* Change the system dialer package name if a package name was specified,
@@ -119,6 +120,8 @@ public final class Telecom extends BaseCommand {
+ "usage: telecom get-max-phones\n"
+ "usage: telecom stop-block-suppression: Stop suppressing the blocked number"
+ " provider after a call to emergency services.\n"
+ + "usage: telecom cleanup-stuck-calls: Clear any disconnected calls that have"
+ + " gotten wedged in Telecom.\n"
+ "usage: telecom set-emer-phone-account-filter <PACKAGE>\n"
+ "\n"
+ "telecom set-phone-account-enabled: Enables the given phone account, if it has"
@@ -214,6 +217,9 @@ public final class Telecom extends BaseCommand {
case COMMAND_STOP_BLOCK_SUPPRESSION:
runStopBlockSuppression();
break;
+ case COMMAND_CLEANUP_STUCK_CALLS:
+ runCleanupStuckCalls();
+ break;
case COMMAND_SET_DEFAULT_DIALER:
runSetDefaultDialer();
break;
@@ -335,6 +341,10 @@ public final class Telecom extends BaseCommand {
mTelecomService.stopBlockSuppression();
}
+ private void runCleanupStuckCalls() throws RemoteException {
+ mTelecomService.cleanupStuckCalls();
+ }
+
private void runSetDefaultDialer() throws RemoteException {
String packageName = nextArg();
if ("default".equals(packageName)) packageName = null;
diff --git a/cmds/uiautomator/api/current.txt b/cmds/uiautomator/api/current.txt
index 489c2eadfd91..bf87d091934e 100644
--- a/cmds/uiautomator/api/current.txt
+++ b/cmds/uiautomator/api/current.txt
@@ -1,221 +1,222 @@
+// Signature format: 2.0
package com.android.uiautomator.core {
- public final deprecated class Configurator {
- method public long getActionAcknowledgmentTimeout();
- method public static com.android.uiautomator.core.Configurator getInstance();
- method public long getKeyInjectionDelay();
- method public long getScrollAcknowledgmentTimeout();
- method public long getWaitForIdleTimeout();
- method public long getWaitForSelectorTimeout();
- method public com.android.uiautomator.core.Configurator setActionAcknowledgmentTimeout(long);
- method public com.android.uiautomator.core.Configurator setKeyInjectionDelay(long);
- method public com.android.uiautomator.core.Configurator setScrollAcknowledgmentTimeout(long);
- method public com.android.uiautomator.core.Configurator setWaitForIdleTimeout(long);
- method public com.android.uiautomator.core.Configurator setWaitForSelectorTimeout(long);
+ @Deprecated public final class Configurator {
+ method @Deprecated public long getActionAcknowledgmentTimeout();
+ method @Deprecated public static com.android.uiautomator.core.Configurator getInstance();
+ method @Deprecated public long getKeyInjectionDelay();
+ method @Deprecated public long getScrollAcknowledgmentTimeout();
+ method @Deprecated public long getWaitForIdleTimeout();
+ method @Deprecated public long getWaitForSelectorTimeout();
+ method @Deprecated public com.android.uiautomator.core.Configurator setActionAcknowledgmentTimeout(long);
+ method @Deprecated public com.android.uiautomator.core.Configurator setKeyInjectionDelay(long);
+ method @Deprecated public com.android.uiautomator.core.Configurator setScrollAcknowledgmentTimeout(long);
+ method @Deprecated public com.android.uiautomator.core.Configurator setWaitForIdleTimeout(long);
+ method @Deprecated public com.android.uiautomator.core.Configurator setWaitForSelectorTimeout(long);
}
- public deprecated class UiCollection extends com.android.uiautomator.core.UiObject {
- ctor public UiCollection(com.android.uiautomator.core.UiSelector);
- method public com.android.uiautomator.core.UiObject getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public com.android.uiautomator.core.UiObject getChildByInstance(com.android.uiautomator.core.UiSelector, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public com.android.uiautomator.core.UiObject getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public int getChildCount(com.android.uiautomator.core.UiSelector);
+ @Deprecated public class UiCollection extends com.android.uiautomator.core.UiObject {
+ ctor @Deprecated public UiCollection(com.android.uiautomator.core.UiSelector);
+ method @Deprecated public com.android.uiautomator.core.UiObject getChildByDescription(com.android.uiautomator.core.UiSelector, String) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public com.android.uiautomator.core.UiObject getChildByInstance(com.android.uiautomator.core.UiSelector, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public com.android.uiautomator.core.UiObject getChildByText(com.android.uiautomator.core.UiSelector, String) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public int getChildCount(com.android.uiautomator.core.UiSelector);
}
- public deprecated class UiDevice {
- method public void clearLastTraversedText();
- method public boolean click(int, int);
- method public boolean drag(int, int, int, int, int);
- method public void dumpWindowHierarchy(java.lang.String);
- method public void freezeRotation() throws android.os.RemoteException;
- method public deprecated java.lang.String getCurrentActivityName();
- method public java.lang.String getCurrentPackageName();
- method public int getDisplayHeight();
- method public int getDisplayRotation();
- method public android.graphics.Point getDisplaySizeDp();
- method public int getDisplayWidth();
- method public static com.android.uiautomator.core.UiDevice getInstance();
- method public java.lang.String getLastTraversedText();
- method public java.lang.String getProductName();
- method public boolean hasAnyWatcherTriggered();
- method public boolean hasWatcherTriggered(java.lang.String);
- method public boolean isNaturalOrientation();
- method public boolean isScreenOn() throws android.os.RemoteException;
- method public boolean openNotification();
- method public boolean openQuickSettings();
- method public boolean pressBack();
- method public boolean pressDPadCenter();
- method public boolean pressDPadDown();
- method public boolean pressDPadLeft();
- method public boolean pressDPadRight();
- method public boolean pressDPadUp();
- method public boolean pressDelete();
- method public boolean pressEnter();
- method public boolean pressHome();
- method public boolean pressKeyCode(int);
- method public boolean pressKeyCode(int, int);
- method public boolean pressMenu();
- method public boolean pressRecentApps() throws android.os.RemoteException;
- method public boolean pressSearch();
- method public void registerWatcher(java.lang.String, com.android.uiautomator.core.UiWatcher);
- method public void removeWatcher(java.lang.String);
- method public void resetWatcherTriggers();
- method public void runWatchers();
- method public void setCompressedLayoutHeirarchy(boolean);
- method public void setOrientationLeft() throws android.os.RemoteException;
- method public void setOrientationNatural() throws android.os.RemoteException;
- method public void setOrientationRight() throws android.os.RemoteException;
- method public void sleep() throws android.os.RemoteException;
- method public boolean swipe(int, int, int, int, int);
- method public boolean swipe(android.graphics.Point[], int);
- method public boolean takeScreenshot(java.io.File);
- method public boolean takeScreenshot(java.io.File, float, int);
- method public void unfreezeRotation() throws android.os.RemoteException;
- method public void waitForIdle();
- method public void waitForIdle(long);
- method public boolean waitForWindowUpdate(java.lang.String, long);
- method public void wakeUp() throws android.os.RemoteException;
+ @Deprecated public class UiDevice {
+ method @Deprecated public void clearLastTraversedText();
+ method @Deprecated public boolean click(int, int);
+ method @Deprecated public boolean drag(int, int, int, int, int);
+ method @Deprecated public void dumpWindowHierarchy(String);
+ method @Deprecated public void freezeRotation() throws android.os.RemoteException;
+ method @Deprecated public String getCurrentActivityName();
+ method @Deprecated public String getCurrentPackageName();
+ method @Deprecated public int getDisplayHeight();
+ method @Deprecated public int getDisplayRotation();
+ method @Deprecated public android.graphics.Point getDisplaySizeDp();
+ method @Deprecated public int getDisplayWidth();
+ method @Deprecated public static com.android.uiautomator.core.UiDevice getInstance();
+ method @Deprecated public String getLastTraversedText();
+ method @Deprecated public String getProductName();
+ method @Deprecated public boolean hasAnyWatcherTriggered();
+ method @Deprecated public boolean hasWatcherTriggered(String);
+ method @Deprecated public boolean isNaturalOrientation();
+ method @Deprecated public boolean isScreenOn() throws android.os.RemoteException;
+ method @Deprecated public boolean openNotification();
+ method @Deprecated public boolean openQuickSettings();
+ method @Deprecated public boolean pressBack();
+ method @Deprecated public boolean pressDPadCenter();
+ method @Deprecated public boolean pressDPadDown();
+ method @Deprecated public boolean pressDPadLeft();
+ method @Deprecated public boolean pressDPadRight();
+ method @Deprecated public boolean pressDPadUp();
+ method @Deprecated public boolean pressDelete();
+ method @Deprecated public boolean pressEnter();
+ method @Deprecated public boolean pressHome();
+ method @Deprecated public boolean pressKeyCode(int);
+ method @Deprecated public boolean pressKeyCode(int, int);
+ method @Deprecated public boolean pressMenu();
+ method @Deprecated public boolean pressRecentApps() throws android.os.RemoteException;
+ method @Deprecated public boolean pressSearch();
+ method @Deprecated public void registerWatcher(String, com.android.uiautomator.core.UiWatcher);
+ method @Deprecated public void removeWatcher(String);
+ method @Deprecated public void resetWatcherTriggers();
+ method @Deprecated public void runWatchers();
+ method @Deprecated public void setCompressedLayoutHeirarchy(boolean);
+ method @Deprecated public void setOrientationLeft() throws android.os.RemoteException;
+ method @Deprecated public void setOrientationNatural() throws android.os.RemoteException;
+ method @Deprecated public void setOrientationRight() throws android.os.RemoteException;
+ method @Deprecated public void sleep() throws android.os.RemoteException;
+ method @Deprecated public boolean swipe(int, int, int, int, int);
+ method @Deprecated public boolean swipe(android.graphics.Point[], int);
+ method @Deprecated public boolean takeScreenshot(java.io.File);
+ method @Deprecated public boolean takeScreenshot(java.io.File, float, int);
+ method @Deprecated public void unfreezeRotation() throws android.os.RemoteException;
+ method @Deprecated public void waitForIdle();
+ method @Deprecated public void waitForIdle(long);
+ method @Deprecated public boolean waitForWindowUpdate(String, long);
+ method @Deprecated public void wakeUp() throws android.os.RemoteException;
}
- public deprecated class UiObject {
- ctor public UiObject(com.android.uiautomator.core.UiSelector);
- method public void clearTextField() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean click() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean clickAndWaitForNewWindow() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean clickAndWaitForNewWindow(long) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean clickBottomRight() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean clickTopLeft() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean dragTo(com.android.uiautomator.core.UiObject, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean dragTo(int, int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean exists();
- method protected android.view.accessibility.AccessibilityNodeInfo findAccessibilityNodeInfo(long);
- method public android.graphics.Rect getBounds() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public com.android.uiautomator.core.UiObject getChild(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public int getChildCount() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public java.lang.String getClassName() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public java.lang.String getContentDescription() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public com.android.uiautomator.core.UiObject getFromParent(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public java.lang.String getPackageName() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public final com.android.uiautomator.core.UiSelector getSelector();
- method public java.lang.String getText() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public android.graphics.Rect getVisibleBounds() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean isCheckable() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean isChecked() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean isClickable() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean isEnabled() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean isFocusable() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean isFocused() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean isLongClickable() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean isScrollable() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean isSelected() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean longClick() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean longClickBottomRight() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean longClickTopLeft() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean performMultiPointerGesture(android.view.MotionEvent.PointerCoords...);
- method public boolean performTwoPointerGesture(android.graphics.Point, android.graphics.Point, android.graphics.Point, android.graphics.Point, int);
- method public boolean pinchIn(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean pinchOut(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean setText(java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean swipeDown(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean swipeLeft(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean swipeRight(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean swipeUp(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean waitForExists(long);
- method public boolean waitUntilGone(long);
- field protected static final int FINGER_TOUCH_HALF_WIDTH = 20; // 0x14
- field protected static final int SWIPE_MARGIN_LIMIT = 5; // 0x5
- field protected static final deprecated long WAIT_FOR_EVENT_TMEOUT = 3000L; // 0xbb8L
- field protected static final long WAIT_FOR_SELECTOR_POLL = 1000L; // 0x3e8L
- field protected static final deprecated long WAIT_FOR_SELECTOR_TIMEOUT = 10000L; // 0x2710L
- field protected static final long WAIT_FOR_WINDOW_TMEOUT = 5500L; // 0x157cL
+ @Deprecated public class UiObject {
+ ctor @Deprecated public UiObject(com.android.uiautomator.core.UiSelector);
+ method @Deprecated public void clearTextField() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean click() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean clickAndWaitForNewWindow() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean clickAndWaitForNewWindow(long) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean clickBottomRight() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean clickTopLeft() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean dragTo(com.android.uiautomator.core.UiObject, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean dragTo(int, int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean exists();
+ method @Deprecated protected android.view.accessibility.AccessibilityNodeInfo findAccessibilityNodeInfo(long);
+ method @Deprecated public android.graphics.Rect getBounds() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public com.android.uiautomator.core.UiObject getChild(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public int getChildCount() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public String getClassName() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public String getContentDescription() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public com.android.uiautomator.core.UiObject getFromParent(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public String getPackageName() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public final com.android.uiautomator.core.UiSelector getSelector();
+ method @Deprecated public String getText() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public android.graphics.Rect getVisibleBounds() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean isCheckable() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean isChecked() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean isClickable() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean isEnabled() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean isFocusable() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean isFocused() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean isLongClickable() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean isScrollable() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean isSelected() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean longClick() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean longClickBottomRight() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean longClickTopLeft() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean performMultiPointerGesture(android.view.MotionEvent.PointerCoords[]...);
+ method @Deprecated public boolean performTwoPointerGesture(android.graphics.Point, android.graphics.Point, android.graphics.Point, android.graphics.Point, int);
+ method @Deprecated public boolean pinchIn(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean pinchOut(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean setText(String) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean swipeDown(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean swipeLeft(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean swipeRight(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean swipeUp(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean waitForExists(long);
+ method @Deprecated public boolean waitUntilGone(long);
+ field @Deprecated protected static final int FINGER_TOUCH_HALF_WIDTH = 20; // 0x14
+ field @Deprecated protected static final int SWIPE_MARGIN_LIMIT = 5; // 0x5
+ field @Deprecated protected static final long WAIT_FOR_EVENT_TMEOUT = 3000L; // 0xbb8L
+ field @Deprecated protected static final long WAIT_FOR_SELECTOR_POLL = 1000L; // 0x3e8L
+ field @Deprecated protected static final long WAIT_FOR_SELECTOR_TIMEOUT = 10000L; // 0x2710L
+ field @Deprecated protected static final long WAIT_FOR_WINDOW_TMEOUT = 5500L; // 0x157cL
}
- public deprecated class UiObjectNotFoundException extends java.lang.Exception {
- ctor public UiObjectNotFoundException(java.lang.String);
- ctor public UiObjectNotFoundException(java.lang.String, java.lang.Throwable);
- ctor public UiObjectNotFoundException(java.lang.Throwable);
+ @Deprecated public class UiObjectNotFoundException extends java.lang.Exception {
+ ctor @Deprecated public UiObjectNotFoundException(String);
+ ctor @Deprecated public UiObjectNotFoundException(String, Throwable);
+ ctor @Deprecated public UiObjectNotFoundException(Throwable);
}
- public deprecated class UiScrollable extends com.android.uiautomator.core.UiCollection {
- ctor public UiScrollable(com.android.uiautomator.core.UiSelector);
- method protected boolean exists(com.android.uiautomator.core.UiSelector);
- method public boolean flingBackward() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean flingForward() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean flingToBeginning(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean flingToEnd(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public com.android.uiautomator.core.UiObject getChildByDescription(com.android.uiautomator.core.UiSelector, java.lang.String, boolean) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public com.android.uiautomator.core.UiObject getChildByText(com.android.uiautomator.core.UiSelector, java.lang.String, boolean) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public int getMaxSearchSwipes();
- method public double getSwipeDeadZonePercentage();
- method public boolean scrollBackward() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollBackward(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollDescriptionIntoView(java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollForward() throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollForward(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollIntoView(com.android.uiautomator.core.UiObject) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollIntoView(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollTextIntoView(java.lang.String) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollToBeginning(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollToBeginning(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollToEnd(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public boolean scrollToEnd(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
- method public com.android.uiautomator.core.UiScrollable setAsHorizontalList();
- method public com.android.uiautomator.core.UiScrollable setAsVerticalList();
- method public com.android.uiautomator.core.UiScrollable setMaxSearchSwipes(int);
- method public com.android.uiautomator.core.UiScrollable setSwipeDeadZonePercentage(double);
+ @Deprecated public class UiScrollable extends com.android.uiautomator.core.UiCollection {
+ ctor @Deprecated public UiScrollable(com.android.uiautomator.core.UiSelector);
+ method @Deprecated protected boolean exists(com.android.uiautomator.core.UiSelector);
+ method @Deprecated public boolean flingBackward() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean flingForward() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean flingToBeginning(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean flingToEnd(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public com.android.uiautomator.core.UiObject getChildByDescription(com.android.uiautomator.core.UiSelector, String, boolean) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public com.android.uiautomator.core.UiObject getChildByText(com.android.uiautomator.core.UiSelector, String, boolean) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public int getMaxSearchSwipes();
+ method @Deprecated public double getSwipeDeadZonePercentage();
+ method @Deprecated public boolean scrollBackward() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollBackward(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollDescriptionIntoView(String) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollForward() throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollForward(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollIntoView(com.android.uiautomator.core.UiObject) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollIntoView(com.android.uiautomator.core.UiSelector) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollTextIntoView(String) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollToBeginning(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollToBeginning(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollToEnd(int, int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public boolean scrollToEnd(int) throws com.android.uiautomator.core.UiObjectNotFoundException;
+ method @Deprecated public com.android.uiautomator.core.UiScrollable setAsHorizontalList();
+ method @Deprecated public com.android.uiautomator.core.UiScrollable setAsVerticalList();
+ method @Deprecated public com.android.uiautomator.core.UiScrollable setMaxSearchSwipes(int);
+ method @Deprecated public com.android.uiautomator.core.UiScrollable setSwipeDeadZonePercentage(double);
}
- public deprecated class UiSelector {
- ctor public UiSelector();
- method public com.android.uiautomator.core.UiSelector checkable(boolean);
- method public com.android.uiautomator.core.UiSelector checked(boolean);
- method public com.android.uiautomator.core.UiSelector childSelector(com.android.uiautomator.core.UiSelector);
- method public com.android.uiautomator.core.UiSelector className(java.lang.String);
- method public <T> com.android.uiautomator.core.UiSelector className(java.lang.Class<T>);
- method public com.android.uiautomator.core.UiSelector classNameMatches(java.lang.String);
- method public com.android.uiautomator.core.UiSelector clickable(boolean);
- method protected com.android.uiautomator.core.UiSelector cloneSelector();
- method public com.android.uiautomator.core.UiSelector description(java.lang.String);
- method public com.android.uiautomator.core.UiSelector descriptionContains(java.lang.String);
- method public com.android.uiautomator.core.UiSelector descriptionMatches(java.lang.String);
- method public com.android.uiautomator.core.UiSelector descriptionStartsWith(java.lang.String);
- method public com.android.uiautomator.core.UiSelector enabled(boolean);
- method public com.android.uiautomator.core.UiSelector focusable(boolean);
- method public com.android.uiautomator.core.UiSelector focused(boolean);
- method public com.android.uiautomator.core.UiSelector fromParent(com.android.uiautomator.core.UiSelector);
- method public com.android.uiautomator.core.UiSelector index(int);
- method public com.android.uiautomator.core.UiSelector instance(int);
- method public com.android.uiautomator.core.UiSelector longClickable(boolean);
- method public com.android.uiautomator.core.UiSelector packageName(java.lang.String);
- method public com.android.uiautomator.core.UiSelector packageNameMatches(java.lang.String);
- method public com.android.uiautomator.core.UiSelector resourceId(java.lang.String);
- method public com.android.uiautomator.core.UiSelector resourceIdMatches(java.lang.String);
- method public com.android.uiautomator.core.UiSelector scrollable(boolean);
- method public com.android.uiautomator.core.UiSelector selected(boolean);
- method public com.android.uiautomator.core.UiSelector text(java.lang.String);
- method public com.android.uiautomator.core.UiSelector textContains(java.lang.String);
- method public com.android.uiautomator.core.UiSelector textMatches(java.lang.String);
- method public com.android.uiautomator.core.UiSelector textStartsWith(java.lang.String);
+ @Deprecated public class UiSelector {
+ ctor @Deprecated public UiSelector();
+ method @Deprecated public com.android.uiautomator.core.UiSelector checkable(boolean);
+ method @Deprecated public com.android.uiautomator.core.UiSelector checked(boolean);
+ method @Deprecated public com.android.uiautomator.core.UiSelector childSelector(com.android.uiautomator.core.UiSelector);
+ method @Deprecated public com.android.uiautomator.core.UiSelector className(String);
+ method @Deprecated public <T> com.android.uiautomator.core.UiSelector className(Class<T>);
+ method @Deprecated public com.android.uiautomator.core.UiSelector classNameMatches(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector clickable(boolean);
+ method @Deprecated protected com.android.uiautomator.core.UiSelector cloneSelector();
+ method @Deprecated public com.android.uiautomator.core.UiSelector description(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector descriptionContains(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector descriptionMatches(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector descriptionStartsWith(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector enabled(boolean);
+ method @Deprecated public com.android.uiautomator.core.UiSelector focusable(boolean);
+ method @Deprecated public com.android.uiautomator.core.UiSelector focused(boolean);
+ method @Deprecated public com.android.uiautomator.core.UiSelector fromParent(com.android.uiautomator.core.UiSelector);
+ method @Deprecated public com.android.uiautomator.core.UiSelector index(int);
+ method @Deprecated public com.android.uiautomator.core.UiSelector instance(int);
+ method @Deprecated public com.android.uiautomator.core.UiSelector longClickable(boolean);
+ method @Deprecated public com.android.uiautomator.core.UiSelector packageName(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector packageNameMatches(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector resourceId(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector resourceIdMatches(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector scrollable(boolean);
+ method @Deprecated public com.android.uiautomator.core.UiSelector selected(boolean);
+ method @Deprecated public com.android.uiautomator.core.UiSelector text(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector textContains(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector textMatches(String);
+ method @Deprecated public com.android.uiautomator.core.UiSelector textStartsWith(String);
}
- public abstract deprecated interface UiWatcher {
- method public abstract boolean checkForCondition();
+ @Deprecated public interface UiWatcher {
+ method @Deprecated public boolean checkForCondition();
}
}
package com.android.uiautomator.testrunner {
- public abstract deprecated interface IAutomationSupport {
- method public abstract void sendStatus(int, android.os.Bundle);
+ @Deprecated public interface IAutomationSupport {
+ method @Deprecated public void sendStatus(int, android.os.Bundle);
}
- public deprecated class UiAutomatorTestCase extends junit.framework.TestCase {
- ctor public UiAutomatorTestCase();
- method public com.android.uiautomator.testrunner.IAutomationSupport getAutomationSupport();
- method public android.os.Bundle getParams();
- method public com.android.uiautomator.core.UiDevice getUiDevice();
- method public void sleep(long);
+ @Deprecated public class UiAutomatorTestCase extends junit.framework.TestCase {
+ ctor @Deprecated public UiAutomatorTestCase();
+ method @Deprecated public com.android.uiautomator.testrunner.IAutomationSupport getAutomationSupport();
+ method @Deprecated public android.os.Bundle getParams();
+ method @Deprecated public com.android.uiautomator.core.UiDevice getUiDevice();
+ method @Deprecated public void sleep(long);
}
}
diff --git a/cmds/uiautomator/api/removed.txt b/cmds/uiautomator/api/removed.txt
index e69de29bb2d1..d802177e249b 100644
--- a/cmds/uiautomator/api/removed.txt
+++ b/cmds/uiautomator/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/cmds/uiautomator/library/Android.bp b/cmds/uiautomator/library/Android.bp
index c33d31f576a3..04b00cb837b2 100644
--- a/cmds/uiautomator/library/Android.bp
+++ b/cmds/uiautomator/library/Android.bp
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-droiddoc {
- name: "uiautomator-stubs-docs",
+droidstubs {
+ name: "uiautomator-stubs",
srcs: [
"core-src/**/*.java",
"testrunner-src/**/*.java",
@@ -24,10 +24,10 @@ droiddoc {
"android.test.base",
"unsupportedappusage",
],
- custom_template: "droiddoc-templates-sdk",
installable: false,
- args: "-stubpackages com.android.uiautomator.core:" +
- "com.android.uiautomator.testrunner",
+ flags: [
+ "-stubpackages com.android.uiautomator.core:com.android.uiautomator.testrunner",
+ ],
check_api: {
current: {
@@ -41,10 +41,26 @@ droiddoc {
},
}
+droiddoc {
+ name: "uiautomator-stubs-docs",
+ srcs: [
+ ":uiautomator-stubs",
+ ],
+ libs: [
+ "android.test.runner",
+ "junit",
+ "android.test.base",
+ "unsupportedappusage",
+ ],
+ installable: false,
+ custom_template: "droiddoc-templates-sdk",
+ create_stubs: false,
+}
+
java_library_static {
name: "android_uiautomator",
srcs: [
- ":uiautomator-stubs-docs",
+ ":uiautomator-stubs",
],
libs: [
"android.test.runner",
@@ -64,7 +80,7 @@ java_library_static {
],
static_libs: [
"junit",
- ]
+ ],
}
java_library_static {
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
index 71561c3c7023..39248730802f 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/UiAutomationShellWrapper.java
@@ -49,7 +49,7 @@ public class UiAutomationShellWrapper {
}
try {
if (isSet) {
- am.setActivityController(new DummyActivityController(), true);
+ am.setActivityController(new NoOpActivityController(), true);
} else {
am.setActivityController(null, true);
}
@@ -80,9 +80,9 @@ public class UiAutomationShellWrapper {
}
/**
- * Dummy, no interference, activity controller.
+ * No-op, no interference, activity controller.
*/
- private class DummyActivityController extends IActivityController.Stub {
+ private class NoOpActivityController extends IActivityController.Stub {
@Override
public boolean activityStarting(Intent intent, String pkg) throws RemoteException {
/* do nothing and let activity proceed normally */
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
index d862e1c2babb..e6fb7aa76e58 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/testrunner/UiAutomatorTestCase.java
@@ -45,7 +45,7 @@ import java.util.List;
public class UiAutomatorTestCase extends TestCase {
private static final String DISABLE_IME = "disable_ime";
- private static final String DUMMY_IME_PACKAGE = "com.android.testing.dummyime";
+ private static final String STUB_IME_PACKAGE = "com.android.testing.stubime";
private static final int NOT_A_SUBTYPE_ID = -1;
private UiDevice mUiDevice;
@@ -58,7 +58,7 @@ public class UiAutomatorTestCase extends TestCase {
super.setUp();
mShouldDisableIme = "true".equals(mParams.getString(DISABLE_IME));
if (mShouldDisableIme) {
- setDummyIme();
+ setStubIme();
}
}
@@ -128,7 +128,7 @@ public class UiAutomatorTestCase extends TestCase {
SystemClock.sleep(ms);
}
- private void setDummyIme() {
+ private void setStubIme() {
Context context = ActivityThread.currentApplication();
if (context == null) {
throw new RuntimeException("ActivityThread.currentApplication() is null.");
@@ -138,13 +138,13 @@ public class UiAutomatorTestCase extends TestCase {
List<InputMethodInfo> infos = im.getInputMethodList();
String id = null;
for (InputMethodInfo info : infos) {
- if (DUMMY_IME_PACKAGE.equals(info.getComponent().getPackageName())) {
+ if (STUB_IME_PACKAGE.equals(info.getComponent().getPackageName())) {
id = info.getId();
}
}
if (id == null) {
throw new RuntimeException(String.format(
- "Required testing fixture missing: IME package (%s)", DUMMY_IME_PACKAGE));
+ "Required testing fixture missing: IME package (%s)", STUB_IME_PACKAGE));
}
if (context.checkSelfPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 35cf39f1b056..bc8db029e06d 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -183,7 +183,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
// This is to work around a bug in b/34736819. This needs to be removed once app team
// fixes their side.
- private AnimatorListenerAdapter mDummyListener = new AnimatorListenerAdapter() {
+ private AnimatorListenerAdapter mAnimationEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mNodeMap.get(animation) == null) {
@@ -1186,7 +1186,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
}
private void startAnimation() {
- addDummyListener();
+ addAnimationEndListener();
// Register animation callback
addAnimationCallback(0);
@@ -1243,15 +1243,15 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
// This is to work around the issue in b/34736819, as the old behavior in AnimatorSet had
// masked a real bug in play movies. TODO: remove this and below once the root cause is fixed.
- private void addDummyListener() {
+ private void addAnimationEndListener() {
for (int i = 1; i < mNodes.size(); i++) {
- mNodes.get(i).mAnimation.addListener(mDummyListener);
+ mNodes.get(i).mAnimation.addListener(mAnimationEndListener);
}
}
- private void removeDummyListener() {
+ private void removeAnimationEndListener() {
for (int i = 1; i < mNodes.size(); i++) {
- mNodes.get(i).mAnimation.removeListener(mDummyListener);
+ mNodes.get(i).mAnimation.removeListener(mAnimationEndListener);
}
}
@@ -1301,7 +1301,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
tmpListeners.get(i).onAnimationEnd(this, mReversing);
}
}
- removeDummyListener();
+ removeAnimationEndListener();
mSelfPulse = true;
mReversing = false;
}
@@ -1346,7 +1346,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
anim.mNodeMap = new ArrayMap<Animator, Node>();
anim.mNodes = new ArrayList<Node>(nodeCount);
anim.mEvents = new ArrayList<AnimationEvent>();
- anim.mDummyListener = new AnimatorListenerAdapter() {
+ anim.mAnimationEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (anim.mNodeMap.get(animation) == null) {
@@ -1369,7 +1369,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
final Node node = mNodes.get(n);
Node nodeClone = node.clone();
// Remove the old internal listener from the cloned child
- nodeClone.mAnimation.removeListener(mDummyListener);
+ nodeClone.mAnimation.removeListener(mAnimationEndListener);
clonesMap.put(node, nodeClone);
anim.mNodes.add(nodeClone);
anim.mNodeMap.put(nodeClone.mAnimation, nodeClone);
@@ -2087,7 +2087,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
* animation starts.
*/
public Builder after(long delay) {
- // setup dummy ValueAnimator just to run the clock
+ // setup a ValueAnimator just to run the clock
ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
anim.setDuration(delay);
after(anim);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 4a982dd1a411..2be92826cf38 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -35,6 +35,7 @@ import android.annotation.RequiresPermission;
import android.annotation.StyleRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.annotation.UiContext;
import android.app.VoiceInteractor.Request;
import android.app.admin.DevicePolicyManager;
import android.app.assist.AssistContent;
@@ -726,6 +727,7 @@ import java.util.function.Consumer;
* upload, independent of whether the original activity is paused, stopped,
* or finished.
*/
+@UiContext
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index ef30cb46318c..9cf0d2a3a36a 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -448,7 +448,7 @@ public abstract class ActivityManagerInternal {
public abstract int broadcastIntent(Intent intent,
IIntentReceiver resultTo,
String[] requiredPermissions, boolean serialized,
- int userId, int[] appIdWhitelist);
+ int userId, int[] appIdAllowList);
/**
* Add uid to the ActivityManagerService PendingStartActivityUids list.
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 5e05506eb416..9833ed60fe46 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.StyleRes;
+import android.annotation.UiContext;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -101,6 +102,7 @@ public class Dialog implements DialogInterface, Window.Callback,
private final WindowManager mWindowManager;
@UnsupportedAppUsage
+ @UiContext
final Context mContext;
@UnsupportedAppUsage
final Window mWindow;
@@ -158,7 +160,7 @@ public class Dialog implements DialogInterface, Window.Callback,
* @param context the context in which the dialog should run
* @see android.R.styleable#Theme_dialogTheme
*/
- public Dialog(@NonNull Context context) {
+ public Dialog(@UiContext @NonNull Context context) {
this(context, 0, true);
}
@@ -177,11 +179,12 @@ public class Dialog implements DialogInterface, Window.Callback,
* @param themeResId a style resource describing the theme to use for the
* window, or {@code 0} to use the default dialog theme
*/
- public Dialog(@NonNull Context context, @StyleRes int themeResId) {
+ public Dialog(@UiContext @NonNull Context context, @StyleRes int themeResId) {
this(context, themeResId, true);
}
- Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
+ Dialog(@UiContext @NonNull Context context, @StyleRes int themeResId,
+ boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (themeResId == Resources.ID_NULL) {
final TypedValue outValue = new TypedValue();
@@ -222,7 +225,7 @@ public class Dialog implements DialogInterface, Window.Callback,
mCancelMessage = cancelCallback;
}
- protected Dialog(@NonNull Context context, boolean cancelable,
+ protected Dialog(@UiContext @NonNull Context context, boolean cancelable,
@Nullable OnCancelListener cancelListener) {
this(context);
mCancelable = cancelable;
@@ -234,7 +237,9 @@ public class Dialog implements DialogInterface, Window.Callback,
*
* @return Context The Context used by the Dialog.
*/
- public final @NonNull Context getContext() {
+ @UiContext
+ @NonNull
+ public final Context getContext() {
return mContext;
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index c5d343d168ca..0a80ccc13487 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -26,6 +26,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.annotation.UiContext;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -213,7 +214,6 @@ public class WallpaperManager {
private static final Object sSync = new Object[0];
@UnsupportedAppUsage
private static Globals sGlobals;
-
private final Context mContext;
private final boolean mWcgEnabled;
private final ColorManagementProxy mCmProxy;
@@ -539,7 +539,8 @@ public class WallpaperManager {
}
}
- /*package*/ WallpaperManager(IWallpaperManager service, Context context, Handler handler) {
+ /*package*/ WallpaperManager(IWallpaperManager service, @UiContext Context context,
+ Handler handler) {
mContext = context;
if (service != null) {
initGlobals(service, context.getMainLooper());
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index ec81ae3bc7c2..79f05a3caa93 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -310,7 +310,6 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
* Sets the maximum bounds to the provided {@link Rect}.
* @param rect the new bounds value.
* @see #getMaxBounds()
- * @hide
*/
public void setMaxBounds(@Nullable Rect rect) {
if (rect == null) {
@@ -364,10 +363,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
return mBounds;
}
- /**
- * @see #setMaxBounds(Rect)
- * @hide
- */
+ /** @see #setMaxBounds(Rect) */
+ @NonNull
public Rect getMaxBounds() {
return mMaxBounds;
}
diff --git a/core/java/android/app/WindowContext.java b/core/java/android/app/WindowContext.java
index cb416c923c60..5f72bac89d7b 100644
--- a/core/java/android/app/WindowContext.java
+++ b/core/java/android/app/WindowContext.java
@@ -20,6 +20,7 @@ import static android.view.WindowManagerGlobal.ADD_TOO_MANY_TOKENS;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UiContext;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Bundle;
@@ -42,6 +43,7 @@ import java.lang.ref.Reference;
* @see Context#createWindowContext(int, Bundle)
* @hide
*/
+@UiContext
public class WindowContext extends ContextWrapper {
private final WindowManagerImpl mWindowManager;
private final IWindowManager mWms;
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 20aa0647d261..a789169ade39 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -919,7 +919,7 @@ public abstract class BackupAgent extends ContextWrapper {
/**
* Only specialized platform agents should overload this entry point to support
- * restores to crazy non-app locations.
+ * restores to non-app locations.
* @hide
*/
protected void onRestoreFile(ParcelFileDescriptor data, long size,
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 4d73a61c972d..f2a054d16ccb 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -229,7 +229,8 @@ public final class UsageStats implements Parcelable {
}
/**
- * Get the total time this package spent in the foreground, measured in milliseconds.
+ * Get the total time this package spent in the foreground, measured in milliseconds. When in
+ * the foreground, the user is actively interacting with the app.
*/
public long getTotalTimeInForeground() {
return mTotalTimeInForeground;
@@ -237,6 +238,8 @@ public final class UsageStats implements Parcelable {
/**
* Get the total time this package's activity is visible in the UI, measured in milliseconds.
+ * Note: An app may be visible but not considered foreground. Apps in the foreground must be
+ * visible, so visible time includes time in the foreground.
*/
public long getTotalTimeVisible() {
return mTotalTimeVisible;
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 8a6cc95319fb..1345e66a355a 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -109,7 +109,7 @@ public final class UsageStatsManager {
/**
- * The app is whitelisted for some reason and the bucket cannot be changed.
+ * The app is exempted for some reason and the bucket cannot be changed.
* {@hide}
*/
@SystemApi
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index fb9746830d4e..fd605604a8f1 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1033,6 +1033,18 @@ public final class BluetoothDevice implements Parcelable {
}
/**
+ * Returns the anonymized hardware address of this BluetoothDevice. The first three octets
+ * will be suppressed for anonymization.
+ * <p> For example, "XX:XX:XX:AA:BB:CC".
+ *
+ * @return Anonymized bluetooth hardware address as string
+ * @hide
+ */
+ public String getAnonymizedAddress() {
+ return "XX:XX:XX" + getAddress().substring(8);
+ }
+
+ /**
* Get the friendly Bluetooth name of the remote device.
*
* <p>The local adapter will automatically retrieve remote names when
@@ -1482,7 +1494,7 @@ public final class BluetoothDevice implements Parcelable {
* present in the cache. Clients should use the {@link #getUuids} to get UUIDs
* if service discovery is not to be performed.
*
- * @return False if the sanity check fails, True if the process of initiating an ACL connection
+ * @return False if the check fails, True if the process of initiating an ACL connection
* to the remote device was started.
*/
@RequiresPermission(Manifest.permission.BLUETOOTH)
@@ -1516,7 +1528,7 @@ public final class BluetoothDevice implements Parcelable {
* The object type will match one of the SdpXxxRecord types, depending on the UUID searched
* for.
*
- * @return False if the sanity check fails, True if the process
+ * @return False if the check fails, True if the process
* of initiating an ACL connection to the remote device
* was started.
*/
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
index 2649fbee4246..cf9eeca0d739 100644
--- a/core/java/android/companion/BluetoothDeviceFilter.java
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -142,6 +142,16 @@ public final class BluetoothDeviceFilter implements DeviceFilter<BluetoothDevice
}
@Override
+ public String toString() {
+ return "BluetoothDeviceFilter{"
+ + "mNamePattern=" + mNamePattern
+ + ", mAddress='" + mAddress + '\''
+ + ", mServiceUuids=" + mServiceUuids
+ + ", mServiceUuidMasks=" + mServiceUuidMasks
+ + '}';
+ }
+
+ @Override
public int describeContents() {
return 0;
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 60ecf64dd0a9..33be50d34777 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -1620,13 +1620,12 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
* Implementation when a caller has performed an insert on the content
* provider, but that call has been rejected for the operation given
* to {@link #setAppOps(int, int)}. The default implementation simply
- * returns a dummy URI that is the base URI with a 0 path element
- * appended.
+ * returns a URI that is the base URI with a 0 path element appended.
*/
public Uri rejectInsert(Uri uri, ContentValues values) {
// If not allowed, we need to return some reasonable URI. Maybe the
// content provider should be responsible for this, but for now we
- // will just return the base URI with a dummy '0' tagged on to it.
+ // will just return the base URI with a '0' tagged on to it.
// You shouldn't be able to read if you can't write, anyway, so it
// shouldn't matter much what is returned.
return uri.buildUpon().appendPath("0").build();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 33f32fb6b9fe..b5eb043d847c 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -726,7 +726,7 @@ public abstract class ContentResolver implements ContentInterface {
/**
* In addition to {@link #SYNC_EXEMPTION_PROMOTE_BUCKET}, we put the sync adapter app in the
- * temp whitelist for 10 minutes, so that even RARE apps can run syncs right away.
+ * temp allowlist for 10 minutes, so that even RARE apps can run syncs right away.
* @hide
*/
public static final int SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP = 2;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 6f8923ffaf59..16cdf2334ad8 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -21,6 +21,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.CheckResult;
import android.annotation.ColorInt;
import android.annotation.ColorRes;
+import android.annotation.DisplayContext;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -33,6 +34,7 @@ import android.annotation.StyleableRes;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.annotation.UiContext;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.IApplicationThread;
@@ -3750,6 +3752,7 @@ public abstract class Context {
* @see #getSystemService(String)
* @see android.view.WindowManager
*/
+ @UiContext
public static final String WINDOW_SERVICE = "window";
/**
@@ -3760,6 +3763,7 @@ public abstract class Context {
* @see #getSystemService(String)
* @see android.view.LayoutInflater
*/
+ @UiContext
public static final String LAYOUT_INFLATER_SERVICE = "layout_inflater";
/**
@@ -3932,6 +3936,7 @@ public abstract class Context {
*
* @see #getSystemService(String)
*/
+ @UiContext
public static final String WALLPAPER_SERVICE = "wallpaper";
/**
@@ -5174,6 +5179,16 @@ public abstract class Context {
public static final String DREAM_SERVICE = "dream";
/**
+ * Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.telephony.SmsManager} for accessing Sms functionality.
+ *
+ * @see #getSystemService(String)
+
+ * @hide
+ */
+ public static final String SMS_SERVICE = "sms";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
@@ -5779,6 +5794,7 @@ public abstract class Context {
*
* @return A {@link Context} for the display.
*/
+ @DisplayContext
public abstract Context createDisplayContext(@NonNull Display display);
/**
@@ -5843,7 +5859,9 @@ public abstract class Context {
* the current number of window contexts without adding any view by
* {@link WindowManager#addView} <b>exceeds five</b>.
*/
- public @NonNull Context createWindowContext(@WindowType int type, @Nullable Bundle options) {
+ @UiContext
+ @NonNull
+ public Context createWindowContext(@WindowType int type, @Nullable Bundle options) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
}
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index b72eb040ea92..8d0baa7f53a5 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -273,7 +273,7 @@ public class SyncStatusInfo implements Parcelable {
totalStats.numSyncs - totalStats.numSourceLocal - totalStats.numSourcePoll
- totalStats.numSourceOther
- totalStats.numSourceUser;
- if (totalStats.numSourcePeriodic < 0) { // Sanity check.
+ if (totalStats.numSourcePeriodic < 0) { // Consistency check.
totalStats.numSourcePeriodic = 0;
}
} else {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 72246ee32186..200604801b97 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -917,7 +917,7 @@ public class PackageParser {
* Automatically detects if the package is a monolithic style (single APK
* file) or cluster style (directory of APKs).
* <p>
- * This performs sanity checking on cluster style packages, such as
+ * This performs checking on cluster style packages, such as
* requiring identical package name and version codes, a single base APK,
* and unique split names.
*
@@ -1038,7 +1038,7 @@ public class PackageParser {
* package is a monolithic style (single APK file) or cluster style
* (directory of APKs).
* <p>
- * This performs sanity checking on cluster style packages, such as
+ * This performs checking on cluster style packages, such as
* requiring identical package name and version codes, a single base APK,
* and unique split names.
* <p>
@@ -1072,7 +1072,7 @@ public class PackageParser {
/**
* Parse all APKs contained in the given directory, treating them as a
- * single package. This also performs sanity checking, such as requiring
+ * single package. This also performs checking, such as requiring
* identical package name and version codes, a single base APK, and unique
* split names.
* <p>
diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java
index cdb1d221d177..982fce918366 100644
--- a/core/java/android/content/pm/dex/DexMetadataHelper.java
+++ b/core/java/android/content/pm/dex/DexMetadataHelper.java
@@ -147,7 +147,7 @@ public class DexMetadataHelper {
/**
* Validate that the given file is a dex metadata archive.
- * This is just a sanity validation that the file is a zip archive.
+ * This is just a validation that the file is a zip archive.
*
* @throws PackageParserException if the file is not a .dm file.
*/
@@ -173,7 +173,7 @@ public class DexMetadataHelper {
* (for any foo.dm there should be either a 'foo' of a 'foo.apk' file).
* If that's not the case it throws {@code IllegalStateException}.
*
- * This is used to perform a basic sanity check during adb install commands.
+ * This is used to perform a basic check during adb install commands.
* (The installer does not support stand alone .dm files)
*/
public static void validateDexPaths(String[] paths) {
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 9480d369065d..6407f9b3c1b8 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1871,7 +1871,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
*/
public boolean isOtherSeqNewer(Configuration other) {
if (other == null) {
- // Sanity check.
+ // Validation check.
return false;
}
if (other.seq == 0) {
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 7c4692c9e3af..0efd883e8b55 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -219,7 +219,7 @@ public final class SQLiteDatabase extends SQLiteClosable {
* even a pathological LIKE or GLOB pattern of 50000 bytes relatively quickly.
* The denial of service problem only comes into play when the pattern length gets
* into millions of bytes. Nevertheless, since most useful LIKE or GLOB patterns
- * are at most a few dozen bytes in length, paranoid application developers may
+ * are at most a few dozen bytes in length, cautious application developers may
* want to reduce this parameter to something in the range of a few hundred
* if they know that external users are able to generate arbitrary patterns.
*/
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 15625cdeb8f4..decf05396c1f 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -683,6 +683,8 @@ public abstract class CameraDevice implements AutoCloseable {
*<p>BACKWARD_COMPATIBLE devices capable of streaming concurrently with other devices as described by
* {@link android.hardware.camera2.CameraManager#getConcurrentCameraIds} have the
* following guaranteed streams (when streaming concurrently with other devices)</p>
+ * <p> Note: The sizes mentioned for these concurrent streams are the maximum sizes guaranteed
+ * to be supported. Sizes smaller than these, obtained by {@link StreamConfigurationMap#getOutputSizes} for a particular format, are supported as well. </p>
*
* <table>
* <tr><th colspan="5">Concurrent stream guaranteed configurations</th></tr>
@@ -696,7 +698,7 @@ public abstract class CameraDevice implements AutoCloseable {
* </table><br>
* </p>
*
- * <p> Devices which are not backwards-compatible, support a mandatory single stream of size sVGA with image format {@code DEPTH16} during concurrent operation.
+ * <p> Devices which are not backwards-compatible, support a mandatory single stream of size sVGA with image format {@code DEPTH16} during concurrent operation. </p>
*
* <p> For guaranteed concurrent stream configurations:</p>
* <p> sVGA refers to the camera device's maximum resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 2579ee687827..da4d8e06ad48 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -24,6 +24,7 @@ import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.StringDef;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -39,6 +40,8 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ConcurrentUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -318,6 +321,37 @@ public final class HdmiControlManager {
/** The HdmiControlService will be disabled to standby. */
public static final int CONTROL_STATE_CHANGED_REASON_STANDBY = 3;
+ // -- Which devices the playback device can send a <Standby> message to upon going to sleep.
+ /**
+ * Send <Standby> to TV only.
+ *
+ * @hide
+ */
+ public static final String SEND_STANDBY_ON_SLEEP_TO_TV = "to_tv";
+ /**
+ * Broadcast <Standby> to all devices in the network.
+ *
+ * @hide
+ */
+ public static final String SEND_STANDBY_ON_SLEEP_BROADCAST = "broadcast";
+ /**
+ * Don't send any <Standby> message.
+ *
+ * @hide
+ */
+ public static final String SEND_STANDBY_ON_SLEEP_NONE = "none";
+ /**
+ * @hide
+ */
+ @StringDef({
+ SEND_STANDBY_ON_SLEEP_TO_TV,
+ SEND_STANDBY_ON_SLEEP_BROADCAST,
+ SEND_STANDBY_ON_SLEEP_NONE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StandbyBehavior {
+ }
+
// True if we have a logical device of type playback hosted in the system.
private final boolean mHasPlaybackDevice;
// True if we have a logical device of type TV hosted in the system.
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index c5a11abe1136..7250801eec81 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -32,6 +32,7 @@ import android.annotation.IntDef;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.Dialog;
import android.compat.annotation.UnsupportedAppUsage;
@@ -258,6 +259,7 @@ import java.util.Collections;
* @attr ref android.R.styleable#InputMethodService_imeExtractEnterAnimation
* @attr ref android.R.styleable#InputMethodService_imeExtractExitAnimation
*/
+@UiContext
public class InputMethodService extends AbstractInputMethodService {
static final String TAG = "InputMethodService";
static final boolean DEBUG = false;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ffb087f6ab24..5d4003afa753 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -608,7 +608,7 @@ public class ConnectivityManager {
public static final int TYPE_BLUETOOTH = 7;
/**
- * Dummy data connection. This should not be used on shipping devices.
+ * Fake data connection. This should not be used on shipping devices.
* @deprecated This is not used any more.
*/
@Deprecated
@@ -1084,9 +1084,9 @@ public class ConnectivityManager {
* to remove an existing always-on VPN configuration.
* @param lockdownEnabled {@code true} to disallow networking when the VPN is not connected or
* {@code false} otherwise.
- * @param lockdownWhitelist The list of packages that are allowed to access network directly
+ * @param lockdownAllowlist The list of packages that are allowed to access network directly
* when VPN is in lockdown mode but is not running. Non-existent packages are ignored so
- * this method must be called when a package that should be whitelisted is installed or
+ * this method must be called when a package that should be allowed is installed or
* uninstalled.
* @return {@code true} if the package is set as always-on VPN controller;
* {@code false} otherwise.
@@ -1094,10 +1094,10 @@ public class ConnectivityManager {
*/
@RequiresPermission(android.Manifest.permission.CONTROL_ALWAYS_ON_VPN)
public boolean setAlwaysOnVpnPackageForUser(int userId, @Nullable String vpnPackage,
- boolean lockdownEnabled, @Nullable List<String> lockdownWhitelist) {
+ boolean lockdownEnabled, @Nullable List<String> lockdownAllowlist) {
try {
return mService.setAlwaysOnVpnPackage(
- userId, vpnPackage, lockdownEnabled, lockdownWhitelist);
+ userId, vpnPackage, lockdownEnabled, lockdownAllowlist);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 482d2d2192b8..327e42bdd2f7 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -354,8 +354,7 @@ public abstract class NetworkAgent {
private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
// The subtype can be changed with (TODO) setLegacySubtype, but it starts
// with the type and an empty description.
- final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacyType,
- config.legacyTypeName, "");
+ final NetworkInfo ni = new NetworkInfo(config.legacyType, 0, config.legacyTypeName, "");
ni.setIsAvailable(true);
ni.setExtraInfo(config.getLegacyExtraInfo());
return ni;
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index e44961528708..713b6888376e 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -28,7 +28,7 @@ import android.util.Slog;
* @hide
*/
public class NetworkState implements Parcelable {
- private static final boolean SANITY_CHECK_ROAMING = false;
+ private static final boolean VALIDATE_ROAMING_STATE = false;
public static final NetworkState EMPTY = new NetworkState(null, null, null, null, null, null);
@@ -52,7 +52,7 @@ public class NetworkState implements Parcelable {
// This object is an atomic view of a network, so the various components
// should always agree on roaming state.
- if (SANITY_CHECK_ROAMING && networkInfo != null && networkCapabilities != null) {
+ if (VALIDATE_ROAMING_STATE && networkInfo != null && networkCapabilities != null) {
if (networkInfo.isRoaming() == networkCapabilities
.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)) {
Slog.wtf("NetworkState", "Roaming state disagreement between " + networkInfo
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index 3c1b86b9f196..51f09a0103ff 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -26,6 +26,7 @@ import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray;
import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray;
import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
+import static android.net.NetworkUtils.multiplySafeByRational;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.internal.util.ArrayUtils.total;
@@ -364,11 +365,12 @@ public class NetworkStatsHistory implements Parcelable {
if (overlap <= 0) continue;
// integer math each time is faster than floating point
- final long fracRxBytes = rxBytes * overlap / duration;
- final long fracRxPackets = rxPackets * overlap / duration;
- final long fracTxBytes = txBytes * overlap / duration;
- final long fracTxPackets = txPackets * overlap / duration;
- final long fracOperations = operations * overlap / duration;
+ final long fracRxBytes = multiplySafeByRational(rxBytes, overlap, duration);
+ final long fracRxPackets = multiplySafeByRational(rxPackets, overlap, duration);
+ final long fracTxBytes = multiplySafeByRational(txBytes, overlap, duration);
+ final long fracTxPackets = multiplySafeByRational(txPackets, overlap, duration);
+ final long fracOperations = multiplySafeByRational(operations, overlap, duration);
+
addLong(activeTime, i, overlap);
addLong(this.rxBytes, i, fracRxBytes); rxBytes -= fracRxBytes;
@@ -568,12 +570,24 @@ public class NetworkStatsHistory implements Parcelable {
if (overlap <= 0) continue;
// integer math each time is faster than floating point
- if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketSpan;
- if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketSpan;
- if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketSpan;
- if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketSpan;
- if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketSpan;
- if (operations != null) entry.operations += operations[i] * overlap / bucketSpan;
+ if (activeTime != null) {
+ entry.activeTime += multiplySafeByRational(activeTime[i], overlap, bucketSpan);
+ }
+ if (rxBytes != null) {
+ entry.rxBytes += multiplySafeByRational(rxBytes[i], overlap, bucketSpan);
+ }
+ if (rxPackets != null) {
+ entry.rxPackets += multiplySafeByRational(rxPackets[i], overlap, bucketSpan);
+ }
+ if (txBytes != null) {
+ entry.txBytes += multiplySafeByRational(txBytes[i], overlap, bucketSpan);
+ }
+ if (txPackets != null) {
+ entry.txPackets += multiplySafeByRational(txPackets[i], overlap, bucketSpan);
+ }
+ if (operations != null) {
+ entry.operations += multiplySafeByRational(operations[i], overlap, bucketSpan);
+ }
}
return entry;
}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 97a7ecc3fb15..1e5b6d5ab5c0 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -477,4 +477,35 @@ public class NetworkUtils {
return true;
}
+
+ /**
+ * Safely multiple a value by a rational.
+ * <p>
+ * Internally it uses integer-based math whenever possible, but switches
+ * over to double-based math if values would overflow.
+ * @hide
+ */
+ public static long multiplySafeByRational(long value, long num, long den) {
+ if (den == 0) {
+ throw new ArithmeticException("Invalid Denominator");
+ }
+ long x = value;
+ long y = num;
+
+ // Logic shamelessly borrowed from Math.multiplyExact()
+ long r = x * y;
+ long ax = Math.abs(x);
+ long ay = Math.abs(y);
+ if (((ax | ay) >>> 31 != 0)) {
+ // Some bits greater than 2^31 that might cause overflow
+ // Check the result using the divide operator
+ // and check for the special case of Long.MIN_VALUE * -1
+ if (((y != 0) && (r / y != x)) ||
+ (x == Long.MIN_VALUE && y == -1)) {
+ // Use double math to avoid overflowing
+ return (long) (((double) num / den) * value);
+ }
+ }
+ return r / den;
+ }
}
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index 8c6faf6d9970..f6852e681439 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -25,6 +25,7 @@ import com.android.internal.util.TrafficStatsConstants;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.Arrays;
/**
@@ -86,21 +87,26 @@ public class SntpClient {
* Sends an SNTP request to the given host and processes the response.
*
* @param host host name of the server.
- * @param timeout network timeout in milliseconds.
+ * @param timeout network timeout in milliseconds. the timeout doesn't include the DNS lookup
+ * time, and it applies to each individual query to the resolved addresses of
+ * the NTP server.
* @param network network over which to send the request.
* @return true if the transaction was successful.
*/
public boolean requestTime(String host, int timeout, Network network) {
final Network networkForResolv = network.getPrivateDnsBypassingCopy();
- InetAddress address = null;
try {
- address = networkForResolv.getByName(host);
- } catch (Exception e) {
+ final InetAddress[] addresses = networkForResolv.getAllByName(host);
+ for (int i = 0; i < addresses.length; i++) {
+ if (requestTime(addresses[i], NTP_PORT, timeout, networkForResolv)) return true;
+ }
+ } catch (UnknownHostException e) {
+ Log.w(TAG, "Unknown host: " + host);
EventLogTags.writeNtpFailure(host, e.toString());
- if (DBG) Log.d(TAG, "request time failed: " + e);
- return false;
}
- return requestTime(address, NTP_PORT, timeout, networkForResolv);
+
+ if (DBG) Log.d(TAG, "request time failed");
+ return false;
}
public boolean requestTime(InetAddress address, int port, int timeout, Network network) {
@@ -139,10 +145,11 @@ public class SntpClient {
final long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET);
final long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);
final long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET);
+ final long referenceTime = readTimeStamp(buffer, REFERENCE_TIME_OFFSET);
- /* do sanity check according to RFC */
+ /* Do validation according to RFC */
// TODO: validate originateTime == requestTime.
- checkValidServerReply(leap, mode, stratum, transmitTime);
+ checkValidServerReply(leap, mode, stratum, transmitTime, referenceTime);
long roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime);
// receiveTime = originateTime + transit + skew
@@ -218,7 +225,7 @@ public class SntpClient {
}
private static void checkValidServerReply(
- byte leap, byte mode, int stratum, long transmitTime)
+ byte leap, byte mode, int stratum, long transmitTime, long referenceTime)
throws InvalidServerReplyException {
if (leap == NTP_LEAP_NOSYNC) {
throw new InvalidServerReplyException("unsynchronized server");
@@ -232,6 +239,9 @@ public class SntpClient {
if (transmitTime == 0) {
throw new InvalidServerReplyException("zero transmitTime");
}
+ if (referenceTime == 0) {
+ throw new InvalidServerReplyException("zero reference timestamp");
+ }
}
/**
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 9c2c5b839302..8e90a119fe21 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -119,7 +119,7 @@ import java.util.Set;
* <p> The Android system starts a VPN in the background by calling
* {@link android.content.Context#startService startService()}. In Android 8.0
* (API level 26) and higher, the system places VPN apps on the temporary
- * whitelist for a short period so the app can start in the background. The VPN
+ * allowlist for a short period so the app can start in the background. The VPN
* app must promote itself to the foreground after it's launched or the system
* will shut down the app.
*
diff --git a/core/java/android/os/DropBoxManager.java b/core/java/android/os/DropBoxManager.java
index bb8d4fe19aa2..3dce130f5d61 100644
--- a/core/java/android/os/DropBoxManager.java
+++ b/core/java/android/os/DropBoxManager.java
@@ -276,7 +276,7 @@ public class DropBoxManager {
}
/**
- * Create a dummy instance for testing. All methods will fail unless
+ * Create an instance for testing. All methods will fail unless
* overridden with an appropriate mock implementation. To obtain a
* functional instance, use {@link android.content.Context#getSystemService}.
*/
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 87e70431bd12..70c924a46c17 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1306,7 +1306,7 @@ public final class FileUtils {
/** {@hide} */
public static int translateModeStringToPosix(String mode) {
- // Sanity check for invalid chars
+ // Quick check for invalid chars
for (int i = 0; i < mode.length(); i++) {
switch (mode.charAt(i)) {
case 'r':
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index df58a6c636f5..a6b869d19867 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -78,7 +78,7 @@ public class GraphicsEnvironment {
private static final String ACTION_ANGLE_FOR_ANDROID_TOAST_MESSAGE =
"android.app.action.ANGLE_FOR_ANDROID_TOAST_MESSAGE";
private static final String INTENT_KEY_A4A_TOAST_MESSAGE = "A4A Toast Message";
- private static final String GAME_DRIVER_WHITELIST_ALL = "*";
+ private static final String GAME_DRIVER_ALLOWLIST_ALL = "*";
private static final String GAME_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt";
private static final int VULKAN_1_0 = 0x00400000;
private static final int VULKAN_1_1 = 0x00401000;
@@ -142,19 +142,19 @@ public class GraphicsEnvironment {
+ "set to: '" + devOptIn + "'");
}
- // We only want to use ANGLE if the app is whitelisted or the developer has
+ // We only want to use ANGLE if the app is allowlisted or the developer has
// explicitly chosen something other than default driver.
- // The whitelist will be generated by the ANGLE APK at both boot time and
+ // The allowlist will be generated by the ANGLE APK at both boot time and
// ANGLE update time. It will only include apps mentioned in the rules file.
- final boolean whitelisted = checkAngleWhitelist(context, coreSettings, packageName);
+ final boolean allowlisted = checkAngleAllowlist(context, coreSettings, packageName);
final boolean requested = devOptIn.equals(sDriverMap.get(OpenGlDriverChoice.ANGLE));
- final boolean useAngle = (whitelisted || requested);
+ final boolean useAngle = (allowlisted || requested);
if (!useAngle) {
return false;
}
- if (whitelisted) {
- Log.v(TAG, "ANGLE whitelist includes " + packageName);
+ if (allowlisted) {
+ Log.v(TAG, "ANGLE allowlist includes " + packageName);
}
if (requested) {
Log.v(TAG, "ANGLE developer option for " + packageName + ": " + devOptIn);
@@ -564,17 +564,17 @@ public class GraphicsEnvironment {
}
/**
- * Pull ANGLE whitelist from GlobalSettings and compare against current package
+ * Pull ANGLE allowlist from GlobalSettings and compare against current package
*/
- private static boolean checkAngleWhitelist(Context context, Bundle bundle, String packageName) {
+ private static boolean checkAngleAllowlist(Context context, Bundle bundle, String packageName) {
final ContentResolver contentResolver = context.getContentResolver();
- final List<String> angleWhitelist =
+ final List<String> angleAllowlist =
getGlobalSettingsString(contentResolver, bundle,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST);
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST);
- if (DEBUG) Log.v(TAG, "ANGLE whitelist: " + angleWhitelist);
+ if (DEBUG) Log.v(TAG, "ANGLE allowlist: " + angleAllowlist);
- return angleWhitelist.contains(packageName);
+ return angleAllowlist.contains(packageName);
}
/**
@@ -584,7 +584,7 @@ public class GraphicsEnvironment {
* @param bundle
* @param packageName
* @return true: ANGLE setup successfully
- * false: ANGLE not setup (not on whitelist, ANGLE not present, etc.)
+ * false: ANGLE not setup (not on allowlist, ANGLE not present, etc.)
*/
public boolean setupAngle(Context context, Bundle bundle, PackageManager pm,
String packageName) {
@@ -750,8 +750,8 @@ public class GraphicsEnvironment {
// 2. GAME_DRIVER_OPT_OUT_APPS
// 3. GAME_DRIVER_PRERELEASE_OPT_IN_APPS
// 4. GAME_DRIVER_OPT_IN_APPS
- // 5. GAME_DRIVER_BLACKLIST
- // 6. GAME_DRIVER_WHITELIST
+ // 5. GAME_DRIVER_DENYLIST
+ // 6. GAME_DRIVER_ALLOWLIST
switch (coreSettings.getInt(Settings.Global.GAME_DRIVER_ALL_APPS, 0)) {
case GAME_DRIVER_GLOBAL_OPT_IN_OFF:
if (DEBUG) Log.v(TAG, "Game Driver is turned off on this device.");
@@ -790,21 +790,21 @@ public class GraphicsEnvironment {
final boolean isOptIn =
getGlobalSettingsString(null, coreSettings, Settings.Global.GAME_DRIVER_OPT_IN_APPS)
.contains(appPackageName);
- final List<String> whitelist =
- getGlobalSettingsString(null, coreSettings, Settings.Global.GAME_DRIVER_WHITELIST);
- if (!isOptIn && whitelist.indexOf(GAME_DRIVER_WHITELIST_ALL) != 0
- && !whitelist.contains(appPackageName)) {
- if (DEBUG) Log.v(TAG, "App is not on the whitelist for Game Driver.");
+ final List<String> allowlist =
+ getGlobalSettingsString(null, coreSettings, Settings.Global.GAME_DRIVER_ALLOWLIST);
+ if (!isOptIn && allowlist.indexOf(GAME_DRIVER_ALLOWLIST_ALL) != 0
+ && !allowlist.contains(appPackageName)) {
+ if (DEBUG) Log.v(TAG, "App is not on the allowlist for Game Driver.");
return null;
}
- // If the application is not opted-in, then check whether it's on the blacklist,
- // terminate early if it's on the blacklist and fallback to system driver.
+ // If the application is not opted-in, then check whether it's on the denylist,
+ // terminate early if it's on the denylist and fallback to system driver.
if (!isOptIn
&& getGlobalSettingsString(
- null, coreSettings, Settings.Global.GAME_DRIVER_BLACKLIST)
+ null, coreSettings, Settings.Global.GAME_DRIVER_DENYLIST)
.contains(appPackageName)) {
- if (DEBUG) Log.v(TAG, "App is on the blacklist for Game Driver.");
+ if (DEBUG) Log.v(TAG, "App is on the denylist for Game Driver.");
return null;
}
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index a7e326378228..b05ea39850f8 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -94,6 +94,11 @@ public final class Looper {
*/
private long mSlowDeliveryThresholdMs;
+ /**
+ * True if a message delivery takes longer than {@link #mSlowDeliveryThresholdMs}.
+ */
+ private boolean mSlowDeliveryDetected;
+
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
@@ -148,6 +153,105 @@ public final class Looper {
}
/**
+ * Poll and deliver single message, return true if the outer loop should continue.
+ */
+ private static boolean loopOnce(final Looper me,
+ final long ident, final int thresholdOverride) {
+ Message msg = me.mQueue.next(); // might block
+ if (msg == null) {
+ // No message indicates that the message queue is quitting.
+ return false;
+ }
+
+ // This must be in a local variable, in case a UI event sets the logger
+ final Printer logging = me.mLogging;
+ if (logging != null) {
+ logging.println(">>>>> Dispatching to " + msg.target + " "
+ + msg.callback + ": " + msg.what);
+ }
+ // Make sure the observer won't change while processing a transaction.
+ final Observer observer = sObserver;
+
+ final long traceTag = me.mTraceTag;
+ long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
+ long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
+ if (thresholdOverride > 0) {
+ slowDispatchThresholdMs = thresholdOverride;
+ slowDeliveryThresholdMs = thresholdOverride;
+ }
+ final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
+ final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);
+
+ final boolean needStartTime = logSlowDelivery || logSlowDispatch;
+ final boolean needEndTime = logSlowDispatch;
+
+ if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
+ Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
+ }
+
+ final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
+ final long dispatchEnd;
+ Object token = null;
+ if (observer != null) {
+ token = observer.messageDispatchStarting();
+ }
+ long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
+ try {
+ msg.target.dispatchMessage(msg);
+ if (observer != null) {
+ observer.messageDispatched(token, msg);
+ }
+ dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
+ } catch (Exception exception) {
+ if (observer != null) {
+ observer.dispatchingThrewException(token, msg, exception);
+ }
+ throw exception;
+ } finally {
+ ThreadLocalWorkSource.restore(origWorkSource);
+ if (traceTag != 0) {
+ Trace.traceEnd(traceTag);
+ }
+ }
+ if (logSlowDelivery) {
+ if (me.mSlowDeliveryDetected) {
+ if ((dispatchStart - msg.when) <= 10) {
+ Slog.w(TAG, "Drained");
+ me.mSlowDeliveryDetected = false;
+ }
+ } else {
+ if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
+ msg)) {
+ // Once we write a slow delivery log, suppress until the queue drains.
+ me.mSlowDeliveryDetected = true;
+ }
+ }
+ }
+ if (logSlowDispatch) {
+ showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
+ }
+
+ if (logging != null) {
+ logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
+ }
+
+ // Make sure that during the course of dispatching the
+ // identity of the thread wasn't corrupted.
+ final long newIdent = Binder.clearCallingIdentity();
+ if (ident != newIdent) {
+ Log.wtf(TAG, "Thread identity changed from 0x"
+ + Long.toHexString(ident) + " to 0x"
+ + Long.toHexString(newIdent) + " while dispatching to "
+ + msg.target.getClass().getName() + " "
+ + msg.callback + " what=" + msg.what);
+ }
+
+ msg.recycleUnchecked();
+
+ return true;
+ }
+
+ /**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
@@ -162,7 +266,6 @@ public final class Looper {
}
me.mInLoop = true;
- final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
@@ -177,99 +280,12 @@ public final class Looper {
+ Thread.currentThread().getName()
+ ".slow", 0);
- boolean slowDeliveryDetected = false;
+ me.mSlowDeliveryDetected = false;
for (;;) {
- Message msg = queue.next(); // might block
- if (msg == null) {
- // No message indicates that the message queue is quitting.
+ if (!loopOnce(me, ident, thresholdOverride)) {
return;
}
-
- // This must be in a local variable, in case a UI event sets the logger
- final Printer logging = me.mLogging;
- if (logging != null) {
- logging.println(">>>>> Dispatching to " + msg.target + " " +
- msg.callback + ": " + msg.what);
- }
- // Make sure the observer won't change while processing a transaction.
- final Observer observer = sObserver;
-
- final long traceTag = me.mTraceTag;
- long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
- long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs;
- if (thresholdOverride > 0) {
- slowDispatchThresholdMs = thresholdOverride;
- slowDeliveryThresholdMs = thresholdOverride;
- }
- final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0);
- final boolean logSlowDispatch = (slowDispatchThresholdMs > 0);
-
- final boolean needStartTime = logSlowDelivery || logSlowDispatch;
- final boolean needEndTime = logSlowDispatch;
-
- if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
- Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
- }
-
- final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
- final long dispatchEnd;
- Object token = null;
- if (observer != null) {
- token = observer.messageDispatchStarting();
- }
- long origWorkSource = ThreadLocalWorkSource.setUid(msg.workSourceUid);
- try {
- msg.target.dispatchMessage(msg);
- if (observer != null) {
- observer.messageDispatched(token, msg);
- }
- dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
- } catch (Exception exception) {
- if (observer != null) {
- observer.dispatchingThrewException(token, msg, exception);
- }
- throw exception;
- } finally {
- ThreadLocalWorkSource.restore(origWorkSource);
- if (traceTag != 0) {
- Trace.traceEnd(traceTag);
- }
- }
- if (logSlowDelivery) {
- if (slowDeliveryDetected) {
- if ((dispatchStart - msg.when) <= 10) {
- Slog.w(TAG, "Drained");
- slowDeliveryDetected = false;
- }
- } else {
- if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery",
- msg)) {
- // Once we write a slow delivery log, suppress until the queue drains.
- slowDeliveryDetected = true;
- }
- }
- }
- if (logSlowDispatch) {
- showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg);
- }
-
- if (logging != null) {
- logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
- }
-
- // Make sure that during the course of dispatching the
- // identity of the thread wasn't corrupted.
- final long newIdent = Binder.clearCallingIdentity();
- if (ident != newIdent) {
- Log.wtf(TAG, "Thread identity changed from 0x"
- + Long.toHexString(ident) + " to 0x"
- + Long.toHexString(newIdent) + " while dispatching to "
- + msg.target.getClass().getName() + " "
- + msg.callback + " what=" + msg.what);
- }
-
- msg.recycleUnchecked();
}
}
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 0ec4fb832801..40c291f14b67 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -16,6 +16,6 @@ per-file PowerManager.java = michaelwr@google.com, santoscordon@google.com
per-file PowerManagerInternal.java = michaelwr@google.com, santoscordon@google.com
# Zygote
-per-file ZygoteProcess.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
+per-file ZygoteProcess.java = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com
per-file GraphicsEnvironment.java = chrisforbes@google.com, cnorthrop@google.com, lpy@google.com, timvp@google.com, zzyiwei@google.com
diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java
index bedbba04255e..3d3759e695e0 100644
--- a/core/java/android/os/Parcelable.java
+++ b/core/java/android/os/Parcelable.java
@@ -17,6 +17,7 @@
package android.os;
import android.annotation.IntDef;
+import android.annotation.SystemApi;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -119,6 +120,7 @@ public interface Parcelable {
* @see ParcelableHolder
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int PARCELABLE_STABILITY_LOCAL = 0x0000;
/**
* Something that is meant to be used between system and vendor.
@@ -126,6 +128,7 @@ public interface Parcelable {
* @see ParcelableHolder
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int PARCELABLE_STABILITY_VINTF = 0x0001;
/**
diff --git a/core/java/android/os/TEST_MAPPING b/core/java/android/os/TEST_MAPPING
index f4645caee511..39c196d1a06c 100644
--- a/core/java/android/os/TEST_MAPPING
+++ b/core/java/android/os/TEST_MAPPING
@@ -1,6 +1,14 @@
{
"presubmit": [
- // TODO(159590499) add BugreportManagerTestCases
+ {
+ "file_patterns": ["Bugreport[^/]*\\.java"],
+ "name": "BugreportManagerTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.LargeTest"
+ }
+ ]
+ },
{
"file_patterns": ["Bugreport[^/]*\\.java"],
"name": "CtsBugreportTestCases",
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 39038f555044..ffede09f99d6 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -251,11 +251,11 @@ public class ZygoteProcess {
private final Object mLock = new Object();
/**
- * List of exemptions to the API blacklist. These are prefix matches on the runtime format
+ * List of exemptions to the API deny list. These are prefix matches on the runtime format
* symbol signature. Any matching symbol is treated by the runtime as being on the light grey
* list.
*/
- private List<String> mApiBlacklistExemptions = Collections.emptyList();
+ private List<String> mApiDenylistExemptions = Collections.emptyList();
/**
* Proportion of hidden API accesses that should be logged to the event log; 0 - 0x10000.
@@ -562,7 +562,7 @@ public class ZygoteProcess {
"--preload-package",
"--preload-app",
"--start-child-zygote",
- "--set-api-blacklist-exemptions",
+ "--set-api-denylist-exemptions",
"--hidden-api-log-sampling-rate",
"--hidden-api-statslog-sampling-rate",
"--invoke-with"
@@ -922,20 +922,20 @@ public class ZygoteProcess {
}
/**
- * Push hidden API blacklisting exemptions into the zygote process(es).
+ * Push hidden API deny-listing exemptions into the zygote process(es).
*
* <p>The list of exemptions will take affect for all new processes forked from the zygote after
* this call.
*
* @param exemptions List of hidden API exemption prefixes. Any matching members are treated as
- * whitelisted/public APIs (i.e. allowed, no logging of usage).
+ * allowed/public APIs (i.e. allowed, no logging of usage).
*/
- public boolean setApiBlacklistExemptions(List<String> exemptions) {
+ public boolean setApiDenylistExemptions(List<String> exemptions) {
synchronized (mLock) {
- mApiBlacklistExemptions = exemptions;
- boolean ok = maybeSetApiBlacklistExemptions(primaryZygoteState, true);
+ mApiDenylistExemptions = exemptions;
+ boolean ok = maybeSetApiDenylistExemptions(primaryZygoteState, true);
if (ok) {
- ok = maybeSetApiBlacklistExemptions(secondaryZygoteState, true);
+ ok = maybeSetApiDenylistExemptions(secondaryZygoteState, true);
}
return ok;
}
@@ -972,32 +972,32 @@ public class ZygoteProcess {
}
@GuardedBy("mLock")
- private boolean maybeSetApiBlacklistExemptions(ZygoteState state, boolean sendIfEmpty) {
+ private boolean maybeSetApiDenylistExemptions(ZygoteState state, boolean sendIfEmpty) {
if (state == null || state.isClosed()) {
- Slog.e(LOG_TAG, "Can't set API blacklist exemptions: no zygote connection");
+ Slog.e(LOG_TAG, "Can't set API denylist exemptions: no zygote connection");
return false;
- } else if (!sendIfEmpty && mApiBlacklistExemptions.isEmpty()) {
+ } else if (!sendIfEmpty && mApiDenylistExemptions.isEmpty()) {
return true;
}
try {
- state.mZygoteOutputWriter.write(Integer.toString(mApiBlacklistExemptions.size() + 1));
+ state.mZygoteOutputWriter.write(Integer.toString(mApiDenylistExemptions.size() + 1));
state.mZygoteOutputWriter.newLine();
- state.mZygoteOutputWriter.write("--set-api-blacklist-exemptions");
+ state.mZygoteOutputWriter.write("--set-api-denylist-exemptions");
state.mZygoteOutputWriter.newLine();
- for (int i = 0; i < mApiBlacklistExemptions.size(); ++i) {
- state.mZygoteOutputWriter.write(mApiBlacklistExemptions.get(i));
+ for (int i = 0; i < mApiDenylistExemptions.size(); ++i) {
+ state.mZygoteOutputWriter.write(mApiDenylistExemptions.get(i));
state.mZygoteOutputWriter.newLine();
}
state.mZygoteOutputWriter.flush();
int status = state.mZygoteInputStream.readInt();
if (status != 0) {
- Slog.e(LOG_TAG, "Failed to set API blacklist exemptions; status " + status);
+ Slog.e(LOG_TAG, "Failed to set API denylist exemptions; status " + status);
}
return true;
} catch (IOException ioe) {
- Slog.e(LOG_TAG, "Failed to set API blacklist exemptions", ioe);
- mApiBlacklistExemptions = Collections.emptyList();
+ Slog.e(LOG_TAG, "Failed to set API denylist exemptions", ioe);
+ mApiDenylistExemptions = Collections.emptyList();
return false;
}
}
@@ -1054,7 +1054,7 @@ public class ZygoteProcess {
primaryZygoteState =
ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);
- maybeSetApiBlacklistExemptions(primaryZygoteState, false);
+ maybeSetApiDenylistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
}
}
@@ -1069,7 +1069,7 @@ public class ZygoteProcess {
ZygoteState.connect(mZygoteSecondarySocketAddress,
mUsapPoolSecondarySocketAddress);
- maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
+ maybeSetApiDenylistExemptions(secondaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 346522a504c8..5acc11a868bf 100755..100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8728,16 +8728,6 @@ public final class Settings {
= "bubble_important_conversations";
/**
- * When enabled, notifications the notification assistant service has modified will show an
- * indicator. When tapped, this indicator will describe the adjustment made and solicit
- * feedback. This flag will also add a "automatic" option to the long press menu.
- *
- * The value 1 - enable, 0 - disable
- * @hide
- */
- public static final String NOTIFICATION_FEEDBACK_ENABLED = "notification_feedback_enabled";
-
- /**
* Whether notifications are dismissed by a right-to-left swipe (instead of a left-to-right
* swipe).
*
@@ -9794,6 +9784,21 @@ public final class Settings {
"hdmi_control_auto_device_off_enabled";
/**
+ * Property to decide which devices the playback device can send a <Standby> message to upon
+ * going to sleep. Supported values are:
+ * <ul>
+ * <li>{@link HdmiControlManager#SEND_STANDBY_ON_SLEEP_TO_TV} to TV only.</li>
+ * <li>{@link HdmiControlManager#SEND_STANDBY_ON_SLEEP_BROADCAST} to all devices in the
+ * network.</li>
+ * <li>{@link HdmiControlManager#SEND_STANDBY_ON_SLEEP_NONE} no <Standby> message sent.</li>
+ * </ul>
+ *
+ * @hide
+ */
+ public static final String HDMI_CONTROL_SEND_STANDBY_ON_SLEEP =
+ "hdmi_control_send_standby_on_sleep";
+
+ /**
* Whether or not media is shown automatically when bypassing as a heads up.
* @hide
*/
@@ -10840,17 +10845,6 @@ public final class Settings {
public static final String MODE_RINGER = "mode_ringer";
/**
- * Specifies whether Enhanced Connectivity is enabled or not. This setting allows the
- * Connectivity Thermal Power Manager to actively help the device to save power in 5G
- * scenarios
- * Type: int 1 is enabled, 0 is disabled
- *
- * @hide
- */
- public static final String ENHANCED_CONNECTIVITY_ENABLED =
- "enhanced_connectivity_enable";
-
- /**
* Overlay display devices setting.
* The associated value is a specially formatted string that describes the
* size and density of simulated secondary display devices.
@@ -12334,8 +12328,8 @@ public final class Settings {
* List of package names that should check ANGLE rules
* @hide
*/
- public static final String GLOBAL_SETTINGS_ANGLE_WHITELIST =
- "angle_whitelist";
+ public static final String GLOBAL_SETTINGS_ANGLE_ALLOWLIST =
+ "angle_allowlist";
/**
* Show the "ANGLE In Use" dialog box to the user when ANGLE is the OpenGL driver.
@@ -12377,24 +12371,24 @@ public final class Settings {
public static final String GAME_DRIVER_OPT_OUT_APPS = "game_driver_opt_out_apps";
/**
- * Apps on the blacklist that are forbidden to use Game Driver.
+ * Apps on the denylist that are forbidden to use Game Driver.
* @hide
*/
- public static final String GAME_DRIVER_BLACKLIST = "game_driver_blacklist";
+ public static final String GAME_DRIVER_DENYLIST = "game_driver_denylist";
/**
- * List of blacklists, each blacklist is a blacklist for a specific version of Game Driver.
+ * List of denylists, each denylist is a denylist for a specific version of Game Driver.
* @hide
*/
- public static final String GAME_DRIVER_BLACKLISTS = "game_driver_blacklists";
+ public static final String GAME_DRIVER_DENYLISTS = "game_driver_denylists";
/**
- * Apps on the whitelist that are allowed to use Game Driver.
+ * Apps on the allowlist that are allowed to use Game Driver.
* The string is a list of application package names, seperated by comma.
* i.e. <apk1>,<apk2>,...,<apkN>
* @hide
*/
- public static final String GAME_DRIVER_WHITELIST = "game_driver_whitelist";
+ public static final String GAME_DRIVER_ALLOWLIST = "game_driver_allowlist";
/**
* List of libraries in sphal accessible by Game Driver
@@ -14043,6 +14037,16 @@ public final class Settings {
"notification_snooze_options";
/**
+ * When enabled, notifications the notification assistant service has modified will show an
+ * indicator. When tapped, this indicator will describe the adjustment made and solicit
+ * feedback. This flag will also add a "automatic" option to the long press menu.
+ *
+ * The value 1 - enable, 0 - disable
+ * @hide
+ */
+ public static final String NOTIFICATION_FEEDBACK_ENABLED = "notification_feedback_enabled";
+
+ /**
* Settings key for the ratio of notification dismissals to notification views - one of the
* criteria for showing the notification blocking helper.
*
diff --git a/core/java/android/security/net/config/NetworkSecurityConfig.java b/core/java/android/security/net/config/NetworkSecurityConfig.java
index 57068fa2eb63..00872fb3b62d 100644
--- a/core/java/android/security/net/config/NetworkSecurityConfig.java
+++ b/core/java/android/security/net/config/NetworkSecurityConfig.java
@@ -216,7 +216,7 @@ public final class NetworkSecurityConfig {
* in {@link Builder#build()}, recursively if needed.
*/
public Builder setParent(Builder parent) {
- // Sanity check to avoid adding loops.
+ // Quick check to avoid adding loops.
Builder current = parent;
while (current != null) {
if (current == this) {
diff --git a/core/java/android/service/notification/NotificationStats.java b/core/java/android/service/notification/NotificationStats.java
index 8be114ca321e..2cd8b8ba42d9 100644
--- a/core/java/android/service/notification/NotificationStats.java
+++ b/core/java/android/service/notification/NotificationStats.java
@@ -73,6 +73,11 @@ public final class NotificationStats implements Parcelable {
* Notification has been dismissed from the notification shade.
*/
public static final int DISMISSAL_SHADE = 3;
+ /**
+ * Notification has been dismissed as a bubble.
+ * @hide
+ */
+ public static final int DISMISSAL_BUBBLE = 3;
/** @hide */
@IntDef(prefix = { "DISMISS_SENTIMENT_" }, value = {
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 0a47032354f5..a720601d81ff 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -26,10 +26,8 @@ import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.CallState;
import android.telephony.Annotation.DataActivityType;
-import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.NetworkType;
import android.telephony.Annotation.PreciseCallStates;
@@ -37,7 +35,6 @@ import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
-import android.telephony.data.ApnSetting;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
import android.util.Log;
@@ -402,17 +399,16 @@ public class TelephonyRegistryManager {
* @param subId for which data connection state changed.
* @param slotIndex for which data connections state changed. Can be derived from subId except
* when subId is invalid.
- * @param apnType the apn type bitmask, defined with {@code ApnSetting#TYPE_*} flags.
* @param preciseState the PreciseDataConnectionState
*
- * @see android.telephony.PreciseDataConnection
+ * @see PreciseDataConnectionState
* @see TelephonyManager#DATA_DISCONNECTED
*/
public void notifyDataConnectionForSubscriber(int slotIndex, int subId,
- @ApnType int apnType, @Nullable PreciseDataConnectionState preciseState) {
+ @NonNull PreciseDataConnectionState preciseState) {
try {
sRegistry.notifyDataConnectionForSubscriber(
- slotIndex, subId, apnType, preciseState);
+ slotIndex, subId, preciseState);
} catch (RemoteException ex) {
// system process is dead
}
@@ -612,25 +608,6 @@ public class TelephonyRegistryManager {
}
/**
- * Notify precise data connection failed cause on certain subscription.
- *
- * @param subId for which data connection failed.
- * @param slotIndex for which data conenction failed. Can be derived from subId except when
- * subId is invalid.
- * @param apnType the apn type bitmask, defined with {@code ApnSetting#TYPE_*} flags.
- * @param apn the APN {@link ApnSetting#getApnName()} of this data connection.
- * @param failCause data fail cause.
- */
- public void notifyPreciseDataConnectionFailed(int subId, int slotIndex, @ApnType int apnType,
- @Nullable String apn, @DataFailureCause int failCause) {
- try {
- sRegistry.notifyPreciseDataConnectionFailed(slotIndex, subId, apnType, apn, failCause);
- } catch (RemoteException ex) {
- // system process is dead
- }
- }
-
- /**
* Notify single Radio Voice Call Continuity (SRVCC) state change for the currently active call
* on certain subscription.
*
diff --git a/core/java/android/text/format/DateIntervalFormat.java b/core/java/android/text/format/DateIntervalFormat.java
index de9ec7ab9ea9..e8236fda42b6 100644
--- a/core/java/android/text/format/DateIntervalFormat.java
+++ b/core/java/android/text/format/DateIntervalFormat.java
@@ -62,7 +62,7 @@ public final class DateIntervalFormat {
/**
* Format a date range. This is our slightly more sensible internal API.
- * A truly sane replacement would take a skeleton instead of int flags.
+ * A truly reasonable replacement would take a skeleton instead of int flags.
*/
@VisibleForTesting(visibility = PACKAGE)
public static String formatDateRange(ULocale icuLocale, android.icu.util.TimeZone icuTimeZone,
diff --git a/core/java/android/util/proto/ProtoInputStream.java b/core/java/android/util/proto/ProtoInputStream.java
index cbe3734ce5fa..aa70d07ff787 100644
--- a/core/java/android/util/proto/ProtoInputStream.java
+++ b/core/java/android/util/proto/ProtoInputStream.java
@@ -96,7 +96,7 @@ public final class ProtoInputStream extends ProtoStream {
private byte mState = 0;
/**
- * Keeps track of the currently read nested Objects, for end object sanity checking and debug
+ * Keeps track of the currently read nested Objects, for end object checking and debug
*/
private ArrayList<Long> mExpectedObjectTokenStack = null;
@@ -513,7 +513,7 @@ public final class ProtoInputStream extends ProtoStream {
(int) fieldId, getOffset() + messageSize));
}
- // Sanity check
+ // Validation check
if (mDepth > 0
&& getOffsetFromToken(mExpectedObjectTokenStack.get(mDepth))
> getOffsetFromToken(mExpectedObjectTokenStack.get(mDepth - 1))) {
@@ -536,7 +536,7 @@ public final class ProtoInputStream extends ProtoStream {
* @param token - token
*/
public void end(long token) {
- // Sanity check to make sure user is keeping track of their embedded messages
+ // Make sure user is keeping track of their embedded messages
if (mExpectedObjectTokenStack.get(mDepth) != token) {
throw new ProtoParseException(
"end token " + token + " does not match current message token "
diff --git a/core/java/android/util/proto/ProtoOutputStream.java b/core/java/android/util/proto/ProtoOutputStream.java
index 5fcd38e2fd9c..afca4ab2c741 100644
--- a/core/java/android/util/proto/ProtoOutputStream.java
+++ b/core/java/android/util/proto/ProtoOutputStream.java
@@ -59,10 +59,10 @@ import java.io.UnsupportedEncodingException;
* cache the size, and then write the size-prefixed buffers.
*
* We are trying to avoid too much generated code here, but this class still
- * needs to have a somewhat sane API. We can't have the multiple passes be
- * done by the calling code. In addition, we want to avoid the memory high
- * water mark of duplicating all of the values into the traditional in-memory
- * Message objects. We need to find another way.
+ * needs to have API. We can't have the multiple passes be done by the
+ * calling code. In addition, we want to avoid the memory high water mark
+ * of duplicating all of the values into the traditional in-memory Message
+ * objects. We need to find another way.
*
* So what we do here is to let the calling code write the data into a
* byte[] (actually a collection of them wrapped in the EncodedBuffer class),
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 0cc469a2d5eb..c4048e5a032d 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -26,6 +26,7 @@ import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.app.KeyguardManager;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -1157,9 +1158,19 @@ public final class Display {
* </p><p>
* The real size may be smaller than the physical size of the screen when the
* window manager is emulating a smaller display (using adb shell wm size).
- * </p>
+ * </p><p>
+ * In general, {@link #getRealSize(Point)} and {@link WindowManager#getMaximumWindowMetrics()}
+ * report the same bounds except that certain areas of the display may not be available to
+ * windows created in the {@link WindowManager}'s {@link Context}.
+ *
+ * For example, imagine a device which has a multi-task mode that limits windows to half of the
+ * screen. In this case, {@link WindowManager#getMaximumWindowMetrics()} reports the
+ * bounds of the screen half where the window is located, while {@link #getRealSize(Point)}
+ * still reports the bounds of the whole display.
*
* @param outSize Set to the real size of the display.
+ *
+ * @see WindowManager#getMaximumWindowMetrics()
*/
public void getRealSize(Point outSize) {
synchronized (this) {
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 713cfb48c95f..064bc6947fc4 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -311,6 +311,9 @@ public class FocusFinder {
}
final int count = focusables.size();
+ if (count < 2) {
+ return null;
+ }
switch (direction) {
case View.FOCUS_FORWARD:
return getNextFocusable(focused, focusables, count);
@@ -373,29 +376,29 @@ public class FocusFinder {
}
private static View getNextFocusable(View focused, ArrayList<View> focusables, int count) {
+ if (count < 2) {
+ return null;
+ }
if (focused != null) {
int position = focusables.lastIndexOf(focused);
if (position >= 0 && position + 1 < count) {
return focusables.get(position + 1);
}
}
- if (!focusables.isEmpty()) {
- return focusables.get(0);
- }
- return null;
+ return focusables.get(0);
}
private static View getPreviousFocusable(View focused, ArrayList<View> focusables, int count) {
+ if (count < 2) {
+ return null;
+ }
if (focused != null) {
int position = focusables.indexOf(focused);
if (position > 0) {
return focusables.get(position - 1);
}
}
- if (!focusables.isEmpty()) {
- return focusables.get(count - 1);
- }
- return null;
+ return focusables.get(count - 1);
}
private static View getNextKeyboardNavigationCluster(
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 55c527ba6fa6..8a722184eb77 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -25,6 +25,7 @@ import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFI
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
import static com.android.internal.util.FrameworkStatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
+import android.annotation.UiContext;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
@@ -393,7 +394,7 @@ public class GestureDetector {
*
* @throws NullPointerException if {@code listener} is null.
*/
- public GestureDetector(Context context, OnGestureListener listener) {
+ public GestureDetector(@UiContext Context context, OnGestureListener listener) {
this(context, listener, null);
}
@@ -412,7 +413,8 @@ public class GestureDetector {
*
* @throws NullPointerException if {@code listener} is null.
*/
- public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
+ public GestureDetector(@UiContext Context context, OnGestureListener listener,
+ Handler handler) {
if (handler != null) {
mHandler = new GestureHandler(handler);
} else {
@@ -442,12 +444,12 @@ public class GestureDetector {
*
* @throws NullPointerException if {@code listener} is null.
*/
- public GestureDetector(Context context, OnGestureListener listener, Handler handler,
+ public GestureDetector(@UiContext Context context, OnGestureListener listener, Handler handler,
boolean unused) {
this(context, listener, handler);
}
- private void init(Context context) {
+ private void init(@UiContext Context context) {
if (mListener == null) {
throw new NullPointerException("OnGestureListener must not be null");
}
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 1afe11ea1acf..b925b492c04b 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.annotation.UiContext;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -94,6 +95,7 @@ public abstract class LayoutInflater {
* {@hide}
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @UiContext
protected final Context mContext;
// these are optional, set by the caller
@@ -277,7 +279,7 @@ public abstract class LayoutInflater {
/**
* Obtains the LayoutInflater from the given context.
*/
- public static LayoutInflater from(Context context) {
+ public static LayoutInflater from(@UiContext Context context) {
LayoutInflater LayoutInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (LayoutInflater == null) {
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index ecf97749d349..8cb8e1d12d8a 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -22,6 +22,7 @@ import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo.Translator;
import android.graphics.Canvas;
import android.graphics.ColorSpace;
@@ -1001,7 +1002,10 @@ public class Surface implements Parcelable {
mHardwareRenderer = new HardwareRenderer();
mHardwareRenderer.setContentRoot(mRenderNode);
mHardwareRenderer.setSurface(Surface.this, true);
- mHardwareRenderer.setWideGamut(isWideColorGamut);
+ mHardwareRenderer.setColorMode(
+ isWideColorGamut
+ ? ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT
+ : ActivityInfo.COLOR_MODE_DEFAULT);
mHardwareRenderer.setLightSourceAlpha(0.0f, 0.0f);
mHardwareRenderer.setLightSourceGeometry(0.0f, 0.0f, 0.0f, 0.0f);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 6beea8764ed1..50ed00cd0aa7 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -89,13 +89,10 @@ public final class SurfaceControl implements Parcelable {
private static native void nativeWriteToParcel(long nativeObject, Parcel out);
private static native void nativeRelease(long nativeObject);
private static native void nativeDisconnect(long nativeObject);
-
- private static native ScreenshotHardwareBuffer nativeScreenshot(IBinder displayToken,
- Rect sourceCrop, int width, int height, boolean useIdentityTransform, int rotation,
- boolean captureSecureLayers);
- private static native ScreenshotHardwareBuffer nativeCaptureLayers(IBinder displayToken,
- long layerObject, Rect sourceCrop, float frameScale, long[] excludeLayerObjects,
- int format);
+ private static native ScreenshotHardwareBuffer nativeCaptureDisplay(
+ DisplayCaptureArgs captureArgs);
+ private static native ScreenshotHardwareBuffer nativeCaptureLayers(
+ LayerCaptureArgs captureArgs);
private static native long nativeMirrorSurface(long mirrorOfObject);
private static native long nativeCreateTransaction();
private static native long nativeGetNativeTransactionFinalizer();
@@ -572,7 +569,8 @@ public final class SurfaceControl implements Parcelable {
* Create ScreenshotHardwareBuffer from an existing HardwareBuffer object.
* @param hardwareBuffer The existing HardwareBuffer object
* @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named}
- * @param containsSecureLayer Indicates whether this graphic buffer contains captured contents
+ * @param containsSecureLayers Indicates whether this graphic buffer contains captured
+ * contents
* of secure layers, in which case the screenshot should not be persisted.
*/
private static ScreenshotHardwareBuffer createFromNative(HardwareBuffer hardwareBuffer,
@@ -595,6 +593,260 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * A common arguments class used for various screenshot requests. This contains arguments that
+ * are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs}
+ * @hide
+ */
+ public abstract static class CaptureArgs {
+ private final int mPixelFormat;
+ private final Rect mSourceCrop = new Rect();
+ private final float mFrameScale;
+ private final boolean mCaptureSecureLayers;
+
+ private CaptureArgs(Builder<? extends Builder<?>> builder) {
+ mPixelFormat = builder.mPixelFormat;
+ mSourceCrop.set(builder.mSourceCrop);
+ mFrameScale = builder.mFrameScale;
+ mCaptureSecureLayers = builder.mCaptureSecureLayers;
+ }
+
+ /**
+ * The Builder class used to construct {@link CaptureArgs}
+ *
+ * @param <T> A builder that extends {@link Builder}
+ */
+ public abstract static class Builder<T extends Builder<T>> {
+ private int mPixelFormat = PixelFormat.RGBA_8888;
+ private final Rect mSourceCrop = new Rect();
+ private float mFrameScale = 1;
+ private boolean mCaptureSecureLayers;
+
+ /**
+ * The desired pixel format of the returned buffer.
+ */
+ public T setPixelFormat(int pixelFormat) {
+ mPixelFormat = pixelFormat;
+ return getThis();
+ }
+
+ /**
+ * The portion of the screen to capture into the buffer. Caller may pass in
+ * 'new Rect()' if no cropping is desired.
+ */
+ public T setSourceCrop(Rect sourceCrop) {
+ mSourceCrop.set(sourceCrop);
+ return getThis();
+ }
+
+ /**
+ * The desired scale of the returned buffer. The raw screen will be scaled up/down.
+ */
+ public T setFrameScale(float frameScale) {
+ mFrameScale = frameScale;
+ return getThis();
+ }
+
+ /**
+ * Whether to allow the screenshot of secure layers. Warning: This should only be done
+ * if the content will be placed in a secure SurfaceControl.
+ *
+ * @see ScreenshotHardwareBuffer#containsSecureLayers()
+ */
+ public T setCaptureSecureLayers(boolean captureSecureLayers) {
+ mCaptureSecureLayers = captureSecureLayers;
+ return getThis();
+ }
+
+ /**
+ * Each sub class should return itself to allow the builder to chain properly
+ */
+ abstract T getThis();
+ }
+ }
+
+ /**
+ * The arguments class used to make display capture requests.
+ *
+ * @see #nativeCaptureDisplay(DisplayCaptureArgs)
+ * @hide
+ */
+ public static class DisplayCaptureArgs extends CaptureArgs {
+ private final IBinder mDisplayToken;
+ private final int mWidth;
+ private final int mHeight;
+ private final boolean mUseIdentityTransform;
+ private final int mRotation;
+
+ private DisplayCaptureArgs(Builder builder) {
+ super(builder);
+ mDisplayToken = builder.mDisplayToken;
+ mWidth = builder.mWidth;
+ mHeight = builder.mHeight;
+ mUseIdentityTransform = builder.mUseIdentityTransform;
+ mRotation = builder.mRotation;
+ }
+
+ /**
+ * The Builder class used to construct {@link DisplayCaptureArgs}
+ */
+ public static class Builder extends CaptureArgs.Builder<Builder> {
+ private IBinder mDisplayToken;
+ 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
+ * remains valid.
+ */
+ public DisplayCaptureArgs build() {
+ if (mDisplayToken == null) {
+ throw new IllegalStateException(
+ "Can't take screenshot with null display token");
+ }
+ return new DisplayCaptureArgs(this);
+ }
+
+ public Builder(IBinder displayToken) {
+ setDisplayToken(displayToken);
+ }
+
+ /**
+ * The display to take the screenshot of.
+ */
+ public Builder setDisplayToken(IBinder displayToken) {
+ mDisplayToken = displayToken;
+ return this;
+ }
+
+ /**
+ * Set the desired size of the returned buffer. The raw screen will be scaled down to
+ * this size
+ *
+ * @param width The desired width of the returned buffer. Caller may pass in 0 if no
+ * scaling is desired.
+ * @param height The desired height of the returned buffer. Caller may pass in 0 if no
+ * scaling is desired.
+ */
+ public Builder setSize(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ return this;
+ }
+
+ /**
+ * Replace whatever transformation (rotation, scaling, translation) the surface
+ * layers are currently using with the identity transformation while taking the
+ * screenshot.
+ */
+ 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;
+ }
+ }
+ }
+
+ /**
+ * The arguments class used to make layer capture requests.
+ *
+ * @see #nativeCaptureLayers(LayerCaptureArgs)
+ * @hide
+ */
+ public static class LayerCaptureArgs extends CaptureArgs {
+ private final long mNativeLayer;
+ private final long[] mNativeExcludeLayers;
+ private final boolean mChildrenOnly;
+
+ private LayerCaptureArgs(Builder builder) {
+ super(builder);
+ mChildrenOnly = builder.mChildrenOnly;
+ mNativeLayer = builder.mLayer.mNativeObject;
+ if (builder.mExcludeLayers != null) {
+ mNativeExcludeLayers = new long[builder.mExcludeLayers.length];
+ for (int i = 0; i < builder.mExcludeLayers.length; i++) {
+ mNativeExcludeLayers[i] = builder.mExcludeLayers[i].mNativeObject;
+ }
+ } else {
+ mNativeExcludeLayers = null;
+ }
+ }
+
+ /**
+ * The Builder class used to construct {@link LayerCaptureArgs}
+ */
+ public static class Builder extends CaptureArgs.Builder<Builder> {
+ private SurfaceControl mLayer;
+ private SurfaceControl[] mExcludeLayers;
+ private boolean mChildrenOnly = true;
+
+ /**
+ * Construct a new {@link LayerCaptureArgs} with the set parameters. The builder
+ * remains valid.
+ */
+ public LayerCaptureArgs build() {
+ if (mLayer == null) {
+ throw new IllegalStateException(
+ "Can't take screenshot with null layer");
+ }
+ return new LayerCaptureArgs(this);
+ }
+
+ public Builder(SurfaceControl layer) {
+ setLayer(layer);
+ }
+
+ /**
+ * The root layer to capture.
+ */
+ public Builder setLayer(SurfaceControl layer) {
+ mLayer = layer;
+ return this;
+ }
+
+
+ /**
+ * An array of layer handles to exclude.
+ */
+ public Builder setExcludeLayers(@Nullable SurfaceControl[] excludeLayers) {
+ mExcludeLayers = excludeLayers;
+ return this;
+ }
+
+ /**
+ * Whether to include the layer itself in the screenshot or just the children and their
+ * descendants.
+ */
+ public Builder setChildrenOnly(boolean childrenOnly) {
+ mChildrenOnly = childrenOnly;
+ return this;
+ }
+
+ @Override
+ Builder getThis() {
+ return this;
+ }
+
+ }
+ }
+
+ /**
* Builder class for {@link SurfaceControl} objects.
*
* By default the surface will be hidden, and have "unset" bounds, meaning it can
@@ -1969,37 +2221,6 @@ public final class SurfaceControl implements Parcelable {
}
/**
- * @see SurfaceControl#screenshot(IBinder, Surface, Rect, int, int, boolean, int)
- * @hide
- */
- public static void screenshot(IBinder display, Surface consumer) {
- screenshot(display, consumer, new Rect(), 0, 0, false, 0);
- }
-
- /**
- * Copy the current screen contents into the provided {@link Surface}
- *
- * @param consumer The {@link Surface} to take the screenshot into.
- * @see SurfaceControl#screenshotToBuffer(IBinder, Rect, int, int, boolean, int)
- * @hide
- */
- public static void screenshot(IBinder display, Surface consumer, Rect sourceCrop, int width,
- int height, boolean useIdentityTransform, int rotation) {
- if (consumer == null) {
- throw new IllegalArgumentException("consumer must not be null");
- }
-
- final ScreenshotHardwareBuffer buffer = screenshotToBuffer(display, sourceCrop, width,
- height, useIdentityTransform, rotation);
- try {
- consumer.attachAndQueueBufferWithColorSpace(buffer.getHardwareBuffer(),
- buffer.getColorSpace());
- } catch (RuntimeException e) {
- Log.w(TAG, "Failed to take screenshot - " + e.getMessage());
- }
- }
-
- /**
* @see SurfaceControl#screenshot(Rect, int, int, boolean, int)}
* @hide
*/
@@ -2014,8 +2235,7 @@ public final class SurfaceControl implements Parcelable {
* a software Bitmap using {@link Bitmap#copy(Bitmap.Config, boolean)}
*
* 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 Surface} such as
- * {@link SurfaceControl#screenshot(IBinder, Surface)} or {@link HardwareBuffer} such as
+ * 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)}
@@ -2075,8 +2295,14 @@ public final class SurfaceControl implements Parcelable {
throw new IllegalArgumentException("displayToken must not be null");
}
- return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation,
- false /* captureSecureLayers */);
+ DisplayCaptureArgs captureArgs = new DisplayCaptureArgs.Builder(display)
+ .setSourceCrop(sourceCrop)
+ .setSize(width, height)
+ .setUseIdentityTransform(useIdentityTransform)
+ .setRotation(rotation)
+ .build();
+
+ return nativeCaptureDisplay(captureArgs);
}
/**
@@ -2096,8 +2322,15 @@ public final class SurfaceControl implements Parcelable {
throw new IllegalArgumentException("displayToken must not be null");
}
- return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation,
- true /* captureSecureLayers */);
+ 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) {
@@ -2147,24 +2380,30 @@ public final class SurfaceControl implements Parcelable {
*/
public static ScreenshotHardwareBuffer captureLayers(SurfaceControl layer, Rect sourceCrop,
float frameScale, int format) {
- final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
- return nativeCaptureLayers(displayToken, layer.mNativeObject, sourceCrop, frameScale, null,
- format);
+ LayerCaptureArgs captureArgs = new LayerCaptureArgs.Builder(layer)
+ .setSourceCrop(sourceCrop)
+ .setFrameScale(frameScale)
+ .setPixelFormat(format)
+ .build();
+
+ return nativeCaptureLayers(captureArgs);
}
/**
- * Like {@link captureLayers} but with an array of layer handles to exclude.
+ * Like {@link #captureLayers(SurfaceControl, Rect, float, int)} but with an array of layer
+ * handles to exclude.
* @hide
*/
public static ScreenshotHardwareBuffer captureLayersExcluding(SurfaceControl layer,
Rect sourceCrop, float frameScale, int format, SurfaceControl[] exclude) {
- final IBinder displayToken = SurfaceControl.getInternalDisplayToken();
- long[] nativeExcludeObjects = new long[exclude.length];
- for (int i = 0; i < exclude.length; i++) {
- nativeExcludeObjects[i] = exclude[i].mNativeObject;
- }
- return nativeCaptureLayers(displayToken, layer.mNativeObject, sourceCrop, frameScale,
- nativeExcludeObjects, PixelFormat.RGBA_8888);
+ LayerCaptureArgs captureArgs = new LayerCaptureArgs.Builder(layer)
+ .setSourceCrop(sourceCrop)
+ .setFrameScale(frameScale)
+ .setPixelFormat(format)
+ .setExcludeLayers(exclude)
+ .build();
+
+ return nativeCaptureLayers(captureArgs);
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index e951156ec4cc..0818abeff923 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -43,6 +43,7 @@ import android.annotation.Nullable;
import android.annotation.Size;
import android.annotation.StyleRes;
import android.annotation.TestApi;
+import android.annotation.UiContext;
import android.annotation.UiThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.AutofillOptions;
@@ -952,8 +953,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Prior to P, {@code #startDragAndDrop} accepts a builder which produces an empty drag shadow.
- * Currently zero size SurfaceControl cannot be created thus we create a dummy 1x1 surface
- * instead.
+ * Currently zero size SurfaceControl cannot be created thus we create a 1x1 surface instead.
*/
private static boolean sAcceptZeroSizeDragShadow;
@@ -4910,6 +4910,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
@ViewDebug.ExportedProperty(deepExport = true)
@UnsupportedAppUsage
+ @UiContext
protected Context mContext;
@UnsupportedAppUsage
@@ -15071,6 +15072,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return The view's Context.
*/
@ViewDebug.CapturedViewProperty
+ @UiContext
public final Context getContext() {
return mContext;
}
@@ -30023,7 +30025,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Dump all private flags in readable format, useful for documentation and
- * sanity checking.
+ * consistency checking.
*/
private static void dumpFlags() {
final HashMap<String, String> found = Maps.newHashMap();
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index ffeeb806ba54..ccf1fb07d0bb 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -20,6 +20,7 @@ import static android.os.StrictMode.vmIncorrectContextUseEnabled;
import android.annotation.FloatRange;
import android.annotation.TestApi;
+import android.annotation.UiContext;
import android.app.Activity;
import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
@@ -391,7 +392,7 @@ public class ViewConfiguration {
* @see #get(android.content.Context)
* @see android.util.DisplayMetrics
*/
- private ViewConfiguration(Context context) {
+ private ViewConfiguration(@UiContext Context context) {
mConstructedWithContext = true;
final Resources res = context.getResources();
final DisplayMetrics metrics = res.getDisplayMetrics();
@@ -498,7 +499,8 @@ public class ViewConfiguration {
* be {@link Activity} or other {@link Context} created with
* {@link Context#createWindowContext(int, Bundle)}.
*/
- public static ViewConfiguration get(Context context) {
+
+ public static ViewConfiguration get(@UiContext Context context) {
if (!context.isUiContext() && vmIncorrectContextUseEnabled()) {
final String errorMessage = "Tried to access UI constants from a non-visual Context:"
+ context;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6552e30dde69..64ddb2f4d9d9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -64,6 +64,7 @@ import android.animation.LayoutTransition;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ResourcesManager;
@@ -349,6 +350,7 @@ public final class ViewRootImpl implements ViewParent,
@GuardedBy("mWindowCallbacks")
final ArrayList<WindowCallbacks> mWindowCallbacks = new ArrayList<>();
@UnsupportedAppUsage
+ @UiContext
public final Context mContext;
@UnsupportedAppUsage
@@ -719,11 +721,11 @@ public final class ViewRootImpl implements ViewParent,
false /* useSfChoreographer */);
}
- public ViewRootImpl(Context context, Display display, IWindowSession session) {
+ public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session) {
this(context, display, session, false /* useSfChoreographer */);
}
- public ViewRootImpl(Context context, Display display, IWindowSession session,
+ public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
boolean useSfChoreographer) {
mContext = context;
mWindowSession = session;
@@ -1329,13 +1331,9 @@ public final class ViewRootImpl implements ViewParent,
final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0
|| insets.top != 0 || insets.bottom != 0;
final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
- final boolean wideGamut =
- mContext.getResources().getConfiguration().isScreenWideColorGamut()
- && attrs.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT;
-
mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent,
attrs.getTitle().toString());
- mAttachInfo.mThreadedRenderer.setWideGamut(wideGamut);
+ updateColorModeIfNeeded(attrs.getColorMode());
updateForceDarkMode();
if (mAttachInfo.mThreadedRenderer != null) {
mAttachInfo.mHardwareAccelerated =
@@ -2648,7 +2646,7 @@ public final class ViewRootImpl implements ViewParent,
& WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
final boolean alwaysConsumeSystemBarsChanged =
mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars;
- final boolean colorModeChanged = hasColorModeChanged(lp.getColorMode());
+ updateColorModeIfNeeded(lp.getColorMode());
surfaceCreated = !hadSurface && mSurface.isValid();
surfaceDestroyed = hadSurface && !mSurface.isValid();
surfaceReplaced = (surfaceGenerationId != mSurface.getGenerationId())
@@ -2677,10 +2675,6 @@ public final class ViewRootImpl implements ViewParent,
// hierarchy is measured below.
dispatchApplyInsets = true;
}
- if (colorModeChanged && mAttachInfo.mThreadedRenderer != null) {
- mAttachInfo.mThreadedRenderer.setWideGamut(
- lp.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
- }
if (surfaceCreated) {
// If we are creating a new surface, then we need to
@@ -2725,7 +2719,7 @@ public final class ViewRootImpl implements ViewParent,
mAttachInfo.mThreadedRenderer.destroy();
}
} else if ((surfaceReplaced
- || surfaceSizeChanged || windowRelayoutWasForced || colorModeChanged)
+ || surfaceSizeChanged || windowRelayoutWasForced)
&& mSurfaceHolder == null
&& mAttachInfo.mThreadedRenderer != null
&& mSurface.isValid()) {
@@ -4557,18 +4551,16 @@ public final class ViewRootImpl implements ViewParent,
}
}
- private boolean hasColorModeChanged(int colorMode) {
+ private void updateColorModeIfNeeded(int colorMode) {
if (mAttachInfo.mThreadedRenderer == null) {
- return false;
- }
- final boolean isWideGamut = colorMode == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT;
- if (mAttachInfo.mThreadedRenderer.isWideGamut() == isWideGamut) {
- return false;
+ return;
}
- if (isWideGamut && !mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
- return false;
+ // TODO: Centralize this sanitization? Why do we let setting bad modes?
+ // Alternatively, can we just let HWUI figure it out? Do we need to care here?
+ if (!mContext.getResources().getConfiguration().isScreenWideColorGamut()) {
+ colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
}
- return true;
+ mAttachInfo.mThreadedRenderer.setColorMode(colorMode);
}
@Override
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 446e7aa67bc5..1dbf37aca689 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -27,6 +27,7 @@ import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.annotation.UiContext;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -280,6 +281,7 @@ public abstract class Window {
public static final int DECOR_CAPTION_SHADE_DARK = 2;
@UnsupportedAppUsage
+ @UiContext
private final Context mContext;
@UnsupportedAppUsage
@@ -722,7 +724,7 @@ public abstract class Window {
}
- public Window(Context context) {
+ public Window(@UiContext Context context) {
mContext = context;
mFeatures = mLocalFeatures = getDefaultFeatures(context);
}
@@ -733,6 +735,7 @@ public abstract class Window {
*
* @return Context The Context that was supplied to the constructor.
*/
+ @UiContext
public final Context getContext() {
return mContext;
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 1d54d9251abb..7923ff0991d8 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -72,6 +72,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
+import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.IBinder;
@@ -346,6 +347,7 @@ public interface WindowManager extends ViewManager {
TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE,
TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION,
TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER,
+ TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION
})
@Retention(RetentionPolicy.SOURCE)
@interface TransitionFlags {}
@@ -473,9 +475,18 @@ public interface WindowManager extends ViewManager {
*
* Note that this might still be smaller than the size of the physical display if certain areas
* of the display are not available to windows created in this {@link Context}.
+ * <p>
+ * For example, given that there's a device which have a multi-task mode to limit activities
+ * to a half screen. In this case, {@link #getMaximumWindowMetrics()} reports the bounds of
+ * the half screen which the activity is located, while {@link Display#getRealSize(Point)} still
+ * reports the bounds of the whole physical display.
*
- * @see #getMaximumWindowMetrics()
+ * Despite this, {@link #getMaximumWindowMetrics()} and {@link Display#getRealSize(Point)}
+ * reports the same bounds in general.
+ *
+ * @see #getCurrentWindowMetrics()
* @see WindowMetrics
+ * @see Display#getRealSize(Point)
*/
default @NonNull WindowMetrics getMaximumWindowMetrics() {
throw new UnsupportedOperationException();
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 2fe7c021bb21..27fbfb6d4d17 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -25,11 +25,11 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import android.annotation.NonNull;
+import android.annotation.UiContext;
import android.app.ResourcesManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.graphics.Insets;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Bundle;
@@ -70,6 +70,7 @@ import java.util.List;
public final class WindowManagerImpl implements WindowManager {
@UnsupportedAppUsage
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
+ @UiContext
@VisibleForTesting
public final Context mContext;
private final Window mParentWindow;
@@ -233,17 +234,16 @@ public final class WindowManagerImpl implements WindowManager {
@Override
public WindowMetrics getMaximumWindowMetrics() {
- final Rect maxBounds = getMaximumBounds();
+ final Context context = mParentWindow != null ? mParentWindow.getContext() : mContext;
+ final Rect maxBounds = getMaximumBounds(context);
+
return new WindowMetrics(maxBounds, computeWindowInsets(maxBounds));
}
- private Rect getMaximumBounds() {
- // TODO(b/128338354): Current maximum bound is display size, but it should be displayArea
- // bound after displayArea feature is finished.
- final Display display = mContext.getDisplayNoVerify();
- final Point displaySize = new Point();
- display.getRealSize(displaySize);
- return new Rect(0, 0, displaySize.x, displaySize.y);
+ private static Rect getMaximumBounds(Context context) {
+ synchronized (ResourcesManager.getInstance()) {
+ return context.getResources().getConfiguration().windowConfiguration.getMaxBounds();
+ }
}
// TODO(b/150095967): Set window type to LayoutParams
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 708e27771ef2..2d0f05e3dc02 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -1768,7 +1768,7 @@ public class AccessibilityNodeInfo implements Parcelable {
* <strong>Note:</strong> The primary usage of this API is for UI test automation
* and in order to report the fully qualified view id if an {@link AccessibilityNodeInfo}
* the client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
- * flag when configuring their {@link android.accessibilityservice.AccessibilityService}.
+ * flag when configuring the {@link android.accessibilityservice.AccessibilityService}.
* </p>
* <p>
* <strong>Note:</strong> If this view hierarchy has a {@link SurfaceView} embedding another
@@ -3206,7 +3206,7 @@ public class AccessibilityNodeInfo implements Parcelable {
* <strong>Note:</strong> The primary usage of this API is for UI test automation
* and in order to report the source view id of an {@link AccessibilityNodeInfo} the
* client has to set the {@link AccessibilityServiceInfo#FLAG_REPORT_VIEW_IDS}
- * flag when configuring their {@link android.accessibilityservice.AccessibilityService}.
+ * flag when configuring the {@link android.accessibilityservice.AccessibilityService}.
* </p>
* @return The id resource name.
diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl
index 2d05591a8131..2343bf3e8d19 100644
--- a/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IWindowMagnificationConnectionCallback.aidl
@@ -19,7 +19,7 @@ package android.view.accessibility;
import android.graphics.Rect;
/**
- * interface to notify the change of the window magnifier bounds and request to change
+ * interface to notify the changes of the window magnification and request to change
* the magnification mode.
*
* @hide
@@ -27,12 +27,13 @@ import android.graphics.Rect;
oneway interface IWindowMagnificationConnectionCallback {
/**
- * Called when the bounds of the window magnifier is changed.
+ * Called when the bounds of the mirrow window is changed.
*
* @param displayId The logical display id.
* @param bounds The window magnifier bounds in screen coordinates.
*/
void onWindowMagnifierBoundsChanged(int displayId, in Rect bounds);
+
/**
* Changes the magnification mode on specified display. It is invoked by System UI when the
* switch button is toggled.
@@ -41,4 +42,12 @@ import android.graphics.Rect;
* @param magnificationMode new magnification mode.
*/
void onChangeMagnificationMode(int displayId, int magnificationMode);
+
+ /**
+ * Called when the magnified bounds is changed.
+ *
+ * @param displayId The logical display id.
+ * @param sourceBounds The magnified bounds in screen coordinates.
+ */
+ void onSourceBoundsChanged(int displayId, in Rect sourceBounds);
}
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index cce109074d82..6300320f5eb5 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -47,6 +47,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
/**
* Max number of suggestions expected from the response. It must be a positive value.
* Defaults to {@code SUGGESTION_COUNT_UNLIMITED} if not set.
+ *
+ * <p>In practice, it is recommended that the max suggestion count does not exceed <b>5</b>
+ * for performance reasons.</p>
*/
private final int mMaxSuggestionCount;
@@ -67,6 +70,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
/**
* The IME provided locales for the request. If non-empty, the inline suggestions should
* return languages from the supported locales. If not provided, it'll default to system locale.
+ *
+ * <p>Note for Autofill Providers: It is <b>recommended</b> for the returned inline suggestions
+ * to have one locale to guarantee consistent UI rendering.</p>
*/
private @NonNull LocaleList mSupportedLocales;
@@ -227,6 +233,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
/**
* Max number of suggestions expected from the response. It must be a positive value.
* Defaults to {@code SUGGESTION_COUNT_UNLIMITED} if not set.
+ *
+ * <p>In practice, it is recommended that the max suggestion count does not exceed <b>5</b>
+ * for performance reasons.</p>
*/
@DataClass.Generated.Member
public int getMaxSuggestionCount() {
@@ -256,6 +265,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
/**
* The IME provided locales for the request. If non-empty, the inline suggestions should
* return languages from the supported locales. If not provided, it'll default to system locale.
+ *
+ * <p>Note for Autofill Providers: It is <b>recommended</b> for the returned inline suggestions
+ * to have one locale to guarantee consistent UI rendering.</p>
*/
@DataClass.Generated.Member
public @NonNull LocaleList getSupportedLocales() {
@@ -458,6 +470,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
/**
* Max number of suggestions expected from the response. It must be a positive value.
* Defaults to {@code SUGGESTION_COUNT_UNLIMITED} if not set.
+ *
+ * <p>In practice, it is recommended that the max suggestion count does not exceed <b>5</b>
+ * for performance reasons.</p>
*/
@DataClass.Generated.Member
public @NonNull Builder setMaxSuggestionCount(int value) {
@@ -508,6 +523,9 @@ public final class InlineSuggestionsRequest implements Parcelable {
/**
* The IME provided locales for the request. If non-empty, the inline suggestions should
* return languages from the supported locales. If not provided, it'll default to system locale.
+ *
+ * <p>Note for Autofill Providers: It is <b>recommended</b> for the returned inline suggestions
+ * to have one locale to guarantee consistent UI rendering.</p>
*/
@DataClass.Generated.Member
public @NonNull Builder setSupportedLocales(@NonNull LocaleList value) {
@@ -604,7 +622,7 @@ public final class InlineSuggestionsRequest implements Parcelable {
}
@DataClass.Generated(
- time = 1588109685838L,
+ time = 1595457701315L,
codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsRequest.java",
inputSignatures = "public static final int SUGGESTION_COUNT_UNLIMITED\nprivate final int mMaxSuggestionCount\nprivate final @android.annotation.NonNull java.util.List<android.widget.inline.InlinePresentationSpec> mInlinePresentationSpecs\nprivate @android.annotation.NonNull java.lang.String mHostPackageName\nprivate @android.annotation.NonNull android.os.LocaleList mSupportedLocales\nprivate @android.annotation.NonNull android.os.Bundle mExtras\nprivate @android.annotation.Nullable android.os.IBinder mHostInputToken\nprivate int mHostDisplayId\npublic void setHostInputToken(android.os.IBinder)\nprivate boolean extrasEquals(android.os.Bundle)\nprivate void parcelHostInputToken(android.os.Parcel,int)\nprivate @android.annotation.Nullable android.os.IBinder unparcelHostInputToken(android.os.Parcel)\npublic void setHostDisplayId(int)\nprivate void onConstructed()\npublic void filterContentTypes()\nprivate static int defaultMaxSuggestionCount()\nprivate static java.lang.String defaultHostPackageName()\nprivate static android.os.LocaleList defaultSupportedLocales()\nprivate static @android.annotation.Nullable android.os.IBinder defaultHostInputToken()\nprivate static @android.annotation.Nullable int defaultHostDisplayId()\nprivate static @android.annotation.NonNull android.os.Bundle defaultExtras()\nclass InlineSuggestionsRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setInlinePresentationSpecs(java.util.List<android.widget.inline.InlinePresentationSpec>)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostPackageName(java.lang.String)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostInputToken(android.os.IBinder)\nabstract android.view.inputmethod.InlineSuggestionsRequest.Builder setHostDisplayId(int)\nclass BaseBuilder extends java.lang.Object implements []")
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsResponse.java b/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
index be833df61ec4..b393c67d7876 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
@@ -32,7 +32,18 @@ import java.util.List;
*/
@DataClass(genEqualsHashCode = true, genToString = true, genHiddenConstructor = true)
public final class InlineSuggestionsResponse implements Parcelable {
- private final @NonNull List<InlineSuggestion> mInlineSuggestions;
+ /**
+ * List of {@link InlineSuggestion}s returned as a part of this response.
+ *
+ * <p>When the host app requests to inflate this <b>ordered</b> list of inline suggestions by
+ * calling {@link InlineSuggestion#inflate}, it is the host's responsibility to track the
+ * order of the inflated {@link android.view.View}s. These views are to be added in
+ * order to the view hierarchy, because the inflation calls will return asynchronously.</p>
+ *
+ * <p>The inflation ordering does not apply to the pinned icon.</p>
+ */
+ @NonNull
+ private final List<InlineSuggestion> mInlineSuggestions;
/**
* Creates a new {@link InlineSuggestionsResponse}, for testing purpose.
@@ -48,7 +59,7 @@ public final class InlineSuggestionsResponse implements Parcelable {
- // Code below generated by codegen v1.0.14.
+ // Code below generated by codegen v1.0.15.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -64,6 +75,15 @@ public final class InlineSuggestionsResponse implements Parcelable {
/**
* Creates a new InlineSuggestionsResponse.
*
+ * @param inlineSuggestions
+ * List of {@link InlineSuggestion}s returned as a part of this response.
+ *
+ * <p>When the host app requests to inflate this <b>ordered</b> list of inline suggestions by
+ * calling {@link InlineSuggestion#inflate}, it is the host's responsibility to track the
+ * order of the inflated {@link android.view.View}s. These views are to be added in
+ * order to the view hierarchy, because the inflation calls will return asynchronously.</p>
+ *
+ * <p>The inflation ordering does not apply to the pinned icon.</p>
* @hide
*/
@DataClass.Generated.Member
@@ -76,6 +96,16 @@ public final class InlineSuggestionsResponse implements Parcelable {
// onConstructed(); // You can define this method to get a callback
}
+ /**
+ * List of {@link InlineSuggestion}s returned as a part of this response.
+ *
+ * <p>When the host app requests to inflate this <b>ordered</b> list of inline suggestions by
+ * calling {@link InlineSuggestion#inflate}, it is the host's responsibility to track the
+ * order of the inflated {@link android.view.View}s. These views are to be added in
+ * order to the view hierarchy, because the inflation calls will return asynchronously.</p>
+ *
+ * <p>The inflation ordering does not apply to the pinned icon.</p>
+ */
@DataClass.Generated.Member
public @NonNull List<InlineSuggestion> getInlineSuggestions() {
return mInlineSuggestions;
@@ -164,8 +194,8 @@ public final class InlineSuggestionsResponse implements Parcelable {
};
@DataClass.Generated(
- time = 1578972149519L,
- codegenVersion = "1.0.14",
+ time = 1595891876037L,
+ codegenVersion = "1.0.15",
sourceFile = "frameworks/base/core/java/android/view/inputmethod/InlineSuggestionsResponse.java",
inputSignatures = "private final @android.annotation.NonNull java.util.List<android.view.inputmethod.InlineSuggestion> mInlineSuggestions\npublic static @android.annotation.TestApi @android.annotation.NonNull android.view.inputmethod.InlineSuggestionsResponse newInlineSuggestionsResponse(java.util.List<android.view.inputmethod.InlineSuggestion>)\nclass InlineSuggestionsResponse extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genHiddenConstructor=true)")
@Deprecated
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 793d94097862..f6671d86cf7b 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -22,6 +22,7 @@ import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION;
import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION;
+import android.annotation.DisplayContext;
import android.annotation.DrawableRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1193,7 +1194,7 @@ public final class InputMethodManager {
* @hide
*/
@NonNull
- public static InputMethodManager forContext(Context context) {
+ public static InputMethodManager forContext(@DisplayContext Context context) {
final int displayId = context.getDisplayId();
// For better backward compatibility, we always use Looper.getMainLooper() for the default
// display case.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 16e87f8bca9a..97e0689ce64f 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1514,7 +1514,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mOnScrollListener != null) {
mOnScrollListener.onScroll(this, mFirstPosition, getChildCount(), mItemCount);
}
- onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
+ // placeholder values, View's implementation does not use these.
+ onScrollChanged(0, 0, 0, 0);
}
/**
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 8c0061d6e750..d969a8894181 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -431,7 +431,8 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
mSelectedCenterOffset = childLeft + childCenter - galleryCenter;
}
- onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
+ // placeholder values, View's implementation does not use these.
+ onScrollChanged(0, 0, 0, 0);
invalidate();
}
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index e58f08a79965..b4379ec75205 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -505,7 +505,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
public void reset() {
count = 0;
- // by default there is at least one dummy view type
+ // by default there is at least one placeholder view type
viewTypeCount = 1;
hasStableIds = true;
loadingTemplate = null;
@@ -948,7 +948,7 @@ public class RemoteViewsAdapter extends BaseAdapter implements Handler.Callback
private void updateTemporaryMetaData(IRemoteViewsFactory factory) {
try {
// get the properties/first view (so that we can use it to
- // measure our dummy views)
+ // measure our placeholder views)
boolean hasStableIds = factory.hasStableIds();
int viewTypeCount = factory.getViewTypeCount();
int count = factory.getCount();
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 6ef570cdc784..2eadb56c0f36 100755
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -1789,7 +1789,7 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
return createIntent(action, dataUri, extraData, query, actionKey, actionMsg);
} catch (RuntimeException e ) {
int rowNum;
- try { // be really paranoid now
+ try { // be really defensive now
rowNum = c.getPosition();
} catch (RuntimeException e2 ) {
rowNum = -1;
diff --git a/core/java/android/widget/TEST_MAPPING b/core/java/android/widget/TEST_MAPPING
index f089f48368a0..df3024eda4b6 100644
--- a/core/java/android/widget/TEST_MAPPING
+++ b/core/java/android/widget/TEST_MAPPING
@@ -17,6 +17,45 @@
}
],
"file_patterns": ["Toast\\.java"]
+ },
+ {
+ "name": "CtsAutoFillServiceTestCases",
+ "options": [
+ {
+ "include-filter": "android.autofillservice.cts.LoginActivityTest"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.AppModeFull"
+ }
+ ]
+ },
+ {
+ "name": "CtsAutoFillServiceTestCases",
+ "options": [
+ {
+ "include-filter": "android.autofillservice.cts.AutofillValueTest"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsAutoFillServiceTestCases",
+ "options": [
+ {
+ "include-filter": "android.autofillservice.cts.CheckoutActivityTest"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.AppModeFull"
+ }
+ ]
}
]
}
diff --git a/core/java/android/widget/inline/InlineContentView.java b/core/java/android/widget/inline/InlineContentView.java
index 9712311aab7c..699a7735bbee 100644
--- a/core/java/android/widget/inline/InlineContentView.java
+++ b/core/java/android/widget/inline/InlineContentView.java
@@ -59,7 +59,7 @@ import java.util.function.Consumer;
*/
public class InlineContentView extends ViewGroup {
- private static final String TAG = "InlineContentView";
+ private static final String TAG = "InlineContentView_test2";
private static final boolean DEBUG = false;
diff --git a/core/java/android/widget/inline/TEST_MAPPING b/core/java/android/widget/inline/TEST_MAPPING
new file mode 100644
index 000000000000..0baad5c31af9
--- /dev/null
+++ b/core/java/android/widget/inline/TEST_MAPPING
@@ -0,0 +1,15 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsAutoFillServiceTestCases",
+ "options": [
+ {
+ "include-filter": "android.autofillservice.cts.inline"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/com/android/internal/app/LocalePicker.java b/core/java/com/android/internal/app/LocalePicker.java
index 6fdb182e5a62..105e05a4a6c3 100644
--- a/core/java/com/android/internal/app/LocalePicker.java
+++ b/core/java/com/android/internal/app/LocalePicker.java
@@ -16,6 +16,8 @@
package com.android.internal.app;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.IActivityManager;
@@ -29,6 +31,7 @@ import android.os.Bundle;
import android.os.LocaleList;
import android.os.RemoteException;
import android.provider.Settings;
+import android.sysprop.LocalizationProperties;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -44,6 +47,9 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
public class LocalePicker extends ListFragment {
private static final String TAG = "LocalePicker";
@@ -93,7 +99,38 @@ public class LocalePicker extends ListFragment {
}
public static String[] getSupportedLocales(Context context) {
- return context.getResources().getStringArray(R.array.supported_locales);
+ String[] allLocales = context.getResources().getStringArray(R.array.supported_locales);
+
+ Predicate<String> localeFilter = getLocaleFilter();
+ if (localeFilter == null) {
+ return allLocales;
+ }
+
+ List<String> result = new ArrayList<>(allLocales.length);
+ for (String locale : allLocales) {
+ if (localeFilter.test(locale)) {
+ result.add(locale);
+ }
+ }
+
+ int localeCount = result.size();
+ return (localeCount == allLocales.length) ? allLocales
+ : result.toArray(new String[localeCount]);
+ }
+
+ @Nullable
+ private static Predicate<String> getLocaleFilter() {
+ try {
+ return LocalizationProperties.locale_filter()
+ .map(filter -> Pattern.compile(filter).asPredicate())
+ .orElse(null);
+ } catch (SecurityException e) {
+ Log.e(TAG, "Failed to read locale filter.", e);
+ } catch (PatternSyntaxException e) {
+ Log.e(TAG, "Bad locale filter format (\"" + e.getPattern() + "\"), skipping.");
+ }
+
+ return null;
}
public static List<LocaleInfo> getAllAssetLocales(Context context, boolean isInDeveloperMode) {
@@ -266,6 +303,11 @@ public class LocalePicker extends ListFragment {
*/
@UnsupportedAppUsage
public static void updateLocales(LocaleList locales) {
+ if (locales != null) {
+ locales = removeExcludedLocales(locales);
+ }
+ // Note: the empty list case is covered by Configuration.setLocales().
+
try {
final IActivityManager am = ActivityManager.getService();
final Configuration config = am.getConfiguration();
@@ -282,6 +324,26 @@ public class LocalePicker extends ListFragment {
}
}
+ @NonNull
+ private static LocaleList removeExcludedLocales(@NonNull LocaleList locales) {
+ Predicate<String> localeFilter = getLocaleFilter();
+ if (localeFilter == null) {
+ return locales;
+ }
+
+ int localeCount = locales.size();
+ ArrayList<Locale> filteredLocales = new ArrayList<>(localeCount);
+ for (int i = 0; i < localeCount; ++i) {
+ Locale locale = locales.get(i);
+ if (localeFilter.test(locale.toString())) {
+ filteredLocales.add(locale);
+ }
+ }
+
+ return (localeCount == filteredLocales.size()) ? locales
+ : new LocaleList(filteredLocales.toArray(new Locale[0]));
+ }
+
/**
* Get the locale list.
*
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index 7195b45a4055..b2852eaeef2a 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -437,7 +437,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
mBinding = true;
final int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
- | mBindingFlags;
+ | Context.BIND_INCLUDE_CAPABILITIES | mBindingFlags;
final boolean willBind = mContext.bindServiceAsUser(mIntent, mServiceConnection, flags,
mHandler, new UserHandle(mUserId));
diff --git a/core/java/com/android/internal/os/ChildZygoteInit.java b/core/java/com/android/internal/os/ChildZygoteInit.java
index 1f816c18f886..749ff84358d9 100644
--- a/core/java/com/android/internal/os/ChildZygoteInit.java
+++ b/core/java/com/android/internal/os/ChildZygoteInit.java
@@ -116,7 +116,7 @@ public class ChildZygoteInit {
try {
server.registerServerSocketAtAbstractName(socketName);
- // Add the abstract socket to the FD whitelist so that the native zygote code
+ // Add the abstract socket to the FD allow list so that the native zygote code
// can properly detach it after forking.
Zygote.nativeAllowFileAcrossFork("ABSTRACT/" + socketName);
diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS
index 928310549e6e..afc94329dc4d 100644
--- a/core/java/com/android/internal/os/OWNERS
+++ b/core/java/com/android/internal/os/OWNERS
@@ -1 +1 @@
-per-file ZygoteArguments.java,ZygoteConnection.java,ZygoteInit.java,Zygote.java,ZygoteServer.java = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
+per-file ZygoteArguments.java,ZygoteConnection.java,ZygoteInit.java,Zygote.java,ZygoteServer.java = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 2989a5eb99b2..1ca9250f2d27 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -816,9 +816,9 @@ public final class Zygote {
throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--preload-app");
} else if (args.mStartChildZygote) {
throw new IllegalArgumentException(USAP_ERROR_PREFIX + "--start-child-zygote");
- } else if (args.mApiBlacklistExemptions != null) {
+ } else if (args.mApiDenylistExemptions != null) {
throw new IllegalArgumentException(
- USAP_ERROR_PREFIX + "--set-api-blacklist-exemptions");
+ USAP_ERROR_PREFIX + "--set-api-denylist-exemptions");
} else if (args.mHiddenApiAccessLogSampleRate != -1) {
throw new IllegalArgumentException(
USAP_ERROR_PREFIX + "--hidden-api-log-sampling-rate=");
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 94c1f71a26db..22082d02d9f6 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -192,10 +192,10 @@ class ZygoteArguments {
boolean mBootCompleted;
/**
- * Exemptions from API blacklisting. These are sent to the pre-forked zygote at boot time, or
- * when they change, via --set-api-blacklist-exemptions.
+ * Exemptions from API deny-listing. These are sent to the pre-forked zygote at boot time, or
+ * when they change, via --set-api-denylist-exemptions.
*/
- String[] mApiBlacklistExemptions;
+ String[] mApiDenylistExemptions;
/**
* Sampling rate for logging hidden API accesses to the event log. This is sent to the
@@ -416,10 +416,10 @@ class ZygoteArguments {
expectRuntimeArgs = false;
} else if (arg.equals("--start-child-zygote")) {
mStartChildZygote = true;
- } else if (arg.equals("--set-api-blacklist-exemptions")) {
+ } else if (arg.equals("--set-api-denylist-exemptions")) {
// consume all remaining args; this is a stand-alone command, never included
// with the regular fork command.
- mApiBlacklistExemptions = Arrays.copyOfRange(args, curArg + 1, args.length);
+ mApiDenylistExemptions = Arrays.copyOfRange(args, curArg + 1, args.length);
curArg = args.length;
expectRuntimeArgs = false;
} else if (arg.startsWith("--hidden-api-log-sampling-rate=")) {
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index ec1b05a455f1..5a576ebbc442 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -185,8 +185,8 @@ class ZygoteConnection {
return null;
}
- if (parsedArgs.mApiBlacklistExemptions != null) {
- return handleApiBlacklistExemptions(zygoteServer, parsedArgs.mApiBlacklistExemptions);
+ if (parsedArgs.mApiDenylistExemptions != null) {
+ return handleApiDenylistExemptions(zygoteServer, parsedArgs.mApiDenylistExemptions);
}
if (parsedArgs.mHiddenApiAccessLogSampleRate != -1
@@ -367,11 +367,11 @@ class ZygoteConnection {
}
/**
- * Makes the necessary changes to implement a new API blacklist exemption policy, and then
+ * Makes the necessary changes to implement a new API deny list exemption policy, and then
* responds to the system server, letting it know that the task has been completed.
*
* This necessitates a change to the internal state of the Zygote. As such, if the USAP
- * pool is enabled all existing USAPs have an incorrect API blacklist exemption list. To
+ * pool is enabled all existing USAPs have an incorrect API deny list exemption list. To
* properly handle this request the pool must be emptied and refilled. This process can return
* a Runnable object that must be returned to ZygoteServer.runSelectLoop to be invoked.
*
@@ -380,9 +380,9 @@ class ZygoteConnection {
* @return A Runnable object representing a new app in any USAPs spawned from here; the
* zygote process will always receive a null value from this function.
*/
- private Runnable handleApiBlacklistExemptions(ZygoteServer zygoteServer, String[] exemptions) {
+ private Runnable handleApiDenylistExemptions(ZygoteServer zygoteServer, String[] exemptions) {
return stateChangeWithUsapPoolReset(zygoteServer,
- () -> ZygoteInit.setApiBlacklistExemptions(exemptions));
+ () -> ZygoteInit.setApiDenylistExemptions(exemptions));
}
private Runnable handleUsapPoolStatusChange(ZygoteServer zygoteServer, boolean newStatus) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 5fd93339570b..32e7fdc51d6c 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -583,7 +583,10 @@ public class ZygoteInit {
VMRuntime.registerAppInfo(profilePath, codePaths);
}
- public static void setApiBlacklistExemptions(String[] exemptions) {
+ /**
+ * Sets the list of classes/methods for the hidden API
+ */
+ public static void setApiDenylistExemptions(String[] exemptions) {
VMRuntime.getRuntime().setHiddenApiExemptions(exemptions);
}
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index a0b50df52e86..bb1733738643 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -451,7 +451,7 @@ class ZygoteServer {
* For reasons of correctness the USAP pool pipe and event FDs
* must be processed before the session and server sockets. This
* is to ensure that the USAP pool accounting information is
- * accurate when handling other requests like API blacklist
+ * accurate when handling other requests like API deny list
* exemptions.
*/
diff --git a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
index 0e703fa686e0..205c5fd735ea 100644
--- a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
+++ b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
@@ -103,8 +103,11 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
final DisplayMetrics dm = userRes.getDisplayMetrics();
final float defaultInset = userRes.getDimension(
com.android.internal.R.dimen.config_backGestureInset) / dm.density;
- final float backGestureInset = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_SYSTEMUI,
- BACK_GESTURE_EDGE_WIDTH, defaultInset);
+ // Only apply the back gesture config if there is an existing inset
+ final float backGestureInset = defaultInset > 0
+ ? DeviceConfig.getFloat(DeviceConfig.NAMESPACE_SYSTEMUI,
+ BACK_GESTURE_EDGE_WIDTH, defaultInset)
+ : defaultInset;
final float inset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, backGestureInset,
dm);
final float scale = Settings.Secure.getFloatForUser(
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 0a3fe096279d..053b06f3d407 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -35,6 +35,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BA
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UiContext;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.app.SearchManager;
@@ -342,7 +343,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
static final RotationWatcher sRotationWatcher = new RotationWatcher();
@UnsupportedAppUsage
- public PhoneWindow(Context context) {
+ public PhoneWindow(@UiContext Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
mRenderShadowsInCompositor = Settings.Global.getInt(context.getContentResolver(),
@@ -352,7 +353,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
/**
* Constructor for main window of an activity.
*/
- public PhoneWindow(Context context, Window preservedWindow,
+ public PhoneWindow(@UiContext Context context, Window preservedWindow,
ActivityConfigCallback activityConfigCallback) {
this(context);
// Only main activity windows use decor context, all the other windows depend on whatever
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 5a04992a35b4..ea09fc8cd34a 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -65,9 +65,7 @@ interface ITelephonyRegistry {
void notifyDataActivity(int state);
void notifyDataActivityForSubscriber(in int subId, int state);
void notifyDataConnectionForSubscriber(
- int phoneId, int subId, int apnType, in PreciseDataConnectionState preciseState);
- @UnsupportedAppUsage
- void notifyDataConnectionFailed(String apnType);
+ int phoneId, int subId, in PreciseDataConnectionState preciseState);
// Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
void notifyCellLocation(in CellIdentity cellLocation);
void notifyCellLocationForSubscriber(in int subId, in CellIdentity cellLocation);
@@ -77,8 +75,6 @@ interface ITelephonyRegistry {
int foregroundCallState, int backgroundCallState);
void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
int preciseDisconnectCause);
- void notifyPreciseDataConnectionFailed(int phoneId, int subId, int apnType, String apn,
- int failCause);
void notifyCellInfoForSubscriber(in int subId, in List<CellInfo> cellInfo);
void notifySrvccStateChanged(in int subId, in int lteState);
void notifySimActivationStateChangedForPhoneId(in int phoneId, in int subId,
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index c6a1153c747f..6b754ca301f3 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -19,6 +19,7 @@ package com.android.server;
import static com.android.internal.util.ArrayUtils.appendInt;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.pm.FeatureInfo;
@@ -245,6 +246,14 @@ public class SystemConfig {
*/
private Map<String, Map<String, String>> mNamedActors = null;
+ // Package name of the package pre-installed on a read-only
+ // partition that is used to verify if an overlay package fulfills
+ // the 'config_signature' policy by comparing their signatures:
+ // if the overlay package is signed with the same certificate as
+ // the package declared in 'config-signature' tag, then the
+ // overlay package fulfills the 'config_signature' policy.
+ private String mOverlayConfigSignaturePackage;
+
public static SystemConfig getInstance() {
if (!isSystemProcess()) {
Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
@@ -432,6 +441,12 @@ public class SystemConfig {
return mNamedActors != null ? mNamedActors : Collections.emptyMap();
}
+ @Nullable
+ public String getOverlayConfigSignaturePackage() {
+ return TextUtils.isEmpty(mOverlayConfigSignaturePackage)
+ ? null : mOverlayConfigSignaturePackage;
+ }
+
/**
* Only use for testing. Do NOT use in production code.
* @param readPermissions false to create an empty SystemConfig; true to read the permissions.
@@ -1137,6 +1152,27 @@ public class SystemConfig {
}
XmlUtils.skipCurrentTag(parser);
} break;
+ case "overlay-config-signature": {
+ if (allowAll) {
+ String pkgName = parser.getAttributeValue(null, "package");
+ if (pkgName == null) {
+ Slog.w(TAG, "<" + name + "> without package in " + permFile
+ + " at " + parser.getPositionDescription());
+ } else {
+ if (TextUtils.isEmpty(mOverlayConfigSignaturePackage)) {
+ mOverlayConfigSignaturePackage = pkgName.intern();
+ } else {
+ throw new IllegalStateException("Reference signature package "
+ + "defined as both "
+ + mOverlayConfigSignaturePackage
+ + " and " + pkgName);
+ }
+ }
+ } else {
+ logNotAllowedInPartition(name, permFile, parser);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ } break;
case "rollback-whitelisted-app": {
String pkgname = parser.getAttributeValue(null, "package");
if (pkgname == null) {
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index d7d8621a3640..7d80993afc6e 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -17,4 +17,4 @@ per-file android_view_*MotionEvent.* = michaelwr@google.com, svv@google.com
per-file android_view_PointerIcon.* = michaelwr@google.com, svv@google.com
# Zygote
-per-file com_android_internal_os_Zygote.*,fd_utils.* = chriswailes@google.com, ngeoffray@google.com, sehr@google.com, narayan@google.com, maco@google.com
+per-file com_android_internal_os_Zygote.*,fd_utils.* = calin@google.com, chriswailes@google.com, maco@google.com, narayan@google.com, ngeoffray@google.com
diff --git a/core/jni/android_hardware_input_InputApplicationHandle.cpp b/core/jni/android_hardware_input_InputApplicationHandle.cpp
index 350f35828418..ff73c74e125e 100644
--- a/core/jni/android_hardware_input_InputApplicationHandle.cpp
+++ b/core/jni/android_hardware_input_InputApplicationHandle.cpp
@@ -61,8 +61,8 @@ bool NativeInputApplicationHandle::updateInfo() {
mInfo.name = getStringField(env, obj, gInputApplicationHandleClassInfo.name, "<null>");
- mInfo.dispatchingTimeout = decltype(mInfo.dispatchingTimeout)(
- env->GetLongField(obj, gInputApplicationHandleClassInfo.dispatchingTimeoutNanos));
+ mInfo.dispatchingTimeoutNanos =
+ env->GetLongField(obj, gInputApplicationHandleClassInfo.dispatchingTimeoutNanos);
jobject tokenObj = env->GetObjectField(obj,
gInputApplicationHandleClassInfo.token);
@@ -77,32 +77,28 @@ bool NativeInputApplicationHandle::updateInfo() {
return mInfo.token.get() != nullptr;
}
-
// --- Global functions ---
-sp<InputApplicationHandle> android_view_InputApplicationHandle_getHandle(
+std::shared_ptr<InputApplicationHandle> android_view_InputApplicationHandle_getHandle(
JNIEnv* env, jobject inputApplicationHandleObj) {
if (!inputApplicationHandleObj) {
return NULL;
}
AutoMutex _l(gHandleMutex);
-
jlong ptr = env->GetLongField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr);
- NativeInputApplicationHandle* handle;
+ std::shared_ptr<NativeInputApplicationHandle>* handle;
if (ptr) {
- handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
+ handle = reinterpret_cast<std::shared_ptr<NativeInputApplicationHandle>*>(ptr);
} else {
jweak objWeak = env->NewWeakGlobalRef(inputApplicationHandleObj);
- handle = new NativeInputApplicationHandle(objWeak);
- handle->incStrong((void*)android_view_InputApplicationHandle_getHandle);
+ handle = new std::shared_ptr(std::make_shared<NativeInputApplicationHandle>(objWeak));
env->SetLongField(inputApplicationHandleObj, gInputApplicationHandleClassInfo.ptr,
reinterpret_cast<jlong>(handle));
}
- return handle;
+ return *handle;
}
-
// --- JNI ---
static void android_view_InputApplicationHandle_nativeDispose(JNIEnv* env, jobject obj) {
@@ -112,8 +108,9 @@ static void android_view_InputApplicationHandle_nativeDispose(JNIEnv* env, jobje
if (ptr) {
env->SetLongField(obj, gInputApplicationHandleClassInfo.ptr, 0);
- NativeInputApplicationHandle* handle = reinterpret_cast<NativeInputApplicationHandle*>(ptr);
- handle->decStrong((void*)android_view_InputApplicationHandle_getHandle);
+ std::shared_ptr<NativeInputApplicationHandle>* handle =
+ reinterpret_cast<std::shared_ptr<NativeInputApplicationHandle>*>(ptr);
+ delete handle;
}
}
diff --git a/core/jni/android_hardware_input_InputApplicationHandle.h b/core/jni/android_hardware_input_InputApplicationHandle.h
index 52ab3e614ba1..ec99d6da5b8e 100644
--- a/core/jni/android_hardware_input_InputApplicationHandle.h
+++ b/core/jni/android_hardware_input_InputApplicationHandle.h
@@ -39,8 +39,7 @@ private:
jweak mObjWeak;
};
-
-extern sp<InputApplicationHandle> android_view_InputApplicationHandle_getHandle(
+extern std::shared_ptr<InputApplicationHandle> android_view_InputApplicationHandle_getHandle(
JNIEnv* env, jobject inputApplicationHandleObj);
} // namespace android
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index bdb4544f4aae..796c5c4cc521 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -168,8 +168,8 @@ bool NativeInputWindowHandle::updateInfo() {
jobject inputApplicationHandleObj = env->GetObjectField(obj,
gInputWindowHandleClassInfo.inputApplicationHandle);
if (inputApplicationHandleObj) {
- sp<InputApplicationHandle> inputApplicationHandle =
- android_view_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
+ std::shared_ptr<InputApplicationHandle> inputApplicationHandle =
+ android_view_InputApplicationHandle_getHandle(env, inputApplicationHandleObj);
if (inputApplicationHandle != nullptr) {
inputApplicationHandle->updateInfo();
mInfo.applicationInfo = *(inputApplicationHandle->getInfo());
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 22bb2102a6e1..1f625443c96e 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -974,7 +974,7 @@ static jint convertAudioPortConfigFromNative(JNIEnv *env,
if (jHandle == NULL) {
return (jint)AUDIO_JAVA_ERROR;
}
- // create dummy port and port config objects with just the correct handle
+ // create placeholder port and port config objects with just the correct handle
// and configuration data. The actual AudioPortConfig objects will be
// constructed by java code with correct class type (device, mix etc...)
// and reference to AudioPort instance in this client
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index e56809f66dc7..8d4c4e5311f8 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -93,13 +93,13 @@ static void android_net_utils_attachDropAllBPFFilter(JNIEnv *env, jobject clazz,
static void android_net_utils_detachBPFFilter(JNIEnv *env, jobject clazz, jobject javaFd)
{
- int dummy = 0;
+ int optval_ignored = 0;
int fd = jniGetFDFromFileDescriptor(env, javaFd);
- if (setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &dummy, sizeof(dummy)) != 0) {
+ if (setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &optval_ignored, sizeof(optval_ignored)) !=
+ 0) {
jniThrowExceptionFmt(env, "java/net/SocketException",
"setsockopt(SO_DETACH_FILTER): %s", strerror(errno));
}
-
}
static jboolean android_net_utils_bindProcessToNetwork(JNIEnv *env, jobject thiz, jint netId)
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index d6e8531fa6ca..ef0eeec2c7af 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -920,7 +920,7 @@ int register_android_os_Debug(JNIEnv *env)
{
jclass clazz = env->FindClass("android/os/Debug$MemoryInfo");
- // Sanity check the number of other statistics expected in Java matches here.
+ // Check the number of other statistics expected in Java matches here.
jfieldID numOtherStats_field = env->GetStaticFieldID(clazz, "NUM_OTHER_STATS", "I");
jint numOtherStats = env->GetStaticIntField(clazz, numOtherStats_field);
jfieldID numDvkStats_field = env->GetStaticFieldID(clazz, "NUM_DVK_STATS", "I");
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 2000ecbbcf89..7cfe3bc1020a 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -330,7 +330,7 @@ static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, j
if (parcel != NULL) {
int32_t len = parcel->readInt32();
- // sanity check the stored length against the true data size
+ // Validate the stored length against the true data size
if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
ret = env->NewByteArray(len);
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 885b0a33e43c..e1180384fcc9 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -962,7 +962,7 @@ static jlong android_os_Binder_clearCallingIdentity()
static void android_os_Binder_restoreCallingIdentity(JNIEnv* env, jobject clazz, jlong token)
{
- // XXX temporary sanity check to debug crashes.
+ // XXX temporary validation check to debug crashes.
int uid = (int)(token>>32);
if (uid > 0 && uid < 999) {
// In Android currently there are no uids in this range.
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 3ca43ce915cf..ac680f6e2611 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -144,9 +144,8 @@ status_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent
event->getAction(), event->getActionButton(),
event->getFlags(), event->getEdgeFlags(),
event->getMetaState(), event->getButtonState(),
- event->getClassification(), event->getXScale(),
- event->getYScale(), event->getXOffset(),
- event->getYOffset(), event->getXPrecision(),
+ event->getClassification(),
+ event->getTransform(), event->getXPrecision(),
event->getYPrecision(),
event->getRawXCursorPosition(),
event->getRawYCursorPosition(),
diff --git a/core/jni/android_view_InputQueue.cpp b/core/jni/android_view_InputQueue.cpp
index 24c3ff80badd..70a9be740810 100644
--- a/core/jni/android_view_InputQueue.cpp
+++ b/core/jni/android_view_InputQueue.cpp
@@ -176,8 +176,8 @@ void InputQueue::enqueueEvent(InputEvent* event) {
Mutex::Autolock _l(mLock);
mPendingEvents.push(event);
if (mPendingEvents.size() == 1) {
- char dummy = 0;
- int res = TEMP_FAILURE_RETRY(write(mDispatchWriteFd, &dummy, sizeof(dummy)));
+ char payload = '\0';
+ int res = TEMP_FAILURE_RETRY(write(mDispatchWriteFd, &payload, sizeof(payload)));
if (res < 0 && errno != EAGAIN) {
ALOGW("Failed writing to dispatch fd: %s", strerror(errno));
}
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 15a91107cbb1..2e396f247979 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -369,13 +369,14 @@ static jlong android_view_MotionEvent_nativeInitialize(
env->DeleteLocalRef(pointerCoordsObj);
}
+ ui::Transform transform;
+ transform.set(xOffset, yOffset);
event->initialize(InputEvent::nextId(), deviceId, source, displayId, INVALID_HMAC, action, 0,
flags, edgeFlags, metaState, buttonState,
- static_cast<MotionClassification>(classification), 1 /*xScale*/, 1 /*yScale*/,
- xOffset, yOffset, xPrecision, yPrecision,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- downTimeNanos, eventTimeNanos, pointerCount, pointerProperties,
- rawPointerCoords);
+ static_cast<MotionClassification>(classification), transform, xPrecision,
+ yPrecision, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, downTimeNanos, eventTimeNanos,
+ pointerCount, pointerProperties, rawPointerCoords);
return reinterpret_cast<jlong>(event.release());
}
@@ -569,9 +570,9 @@ static void android_view_MotionEvent_nativeTransform(JNIEnv* env, jclass clazz,
jlong nativePtr, jobject matrixObj) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
- float m[9];
- AMatrix_getContents(env, matrixObj, m);
- event->transform(m);
+ std::array<float, 9> matrix;
+ AMatrix_getContents(env, matrixObj, matrix.data());
+ event->transform(matrix);
}
// ----------------- @CriticalNative ------------------------------
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a965ab310205..814a07e7f2df 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -104,6 +104,27 @@ static struct {
jfieldID top;
} gRectClassInfo;
+static struct {
+ jfieldID pixelFormat;
+ jfieldID sourceCrop;
+ jfieldID frameScale;
+ jfieldID captureSecureLayers;
+} gCaptureArgsClassInfo;
+
+static struct {
+ jfieldID displayToken;
+ jfieldID width;
+ jfieldID height;
+ jfieldID useIdentityTransform;
+ jfieldID rotation;
+} gDisplayCaptureArgsClassInfo;
+
+static struct {
+ jfieldID layer;
+ jfieldID excludeLayers;
+ jfieldID childrenOnly;
+} gLayerCaptureArgsClassInfo;
+
// Implements SkMallocPixelRef::ReleaseProc, to delete the screenshot on unref.
void DeleteScreenshot(void* addr, void* context) {
delete ((ScreenshotClient*) context);
@@ -276,55 +297,79 @@ static Rect rectFromObj(JNIEnv* env, jobject rectObj) {
return Rect(left, top, right, bottom);
}
-static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
- jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
- bool useIdentityTransform, int rotation, bool captureSecureLayers) {
- sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
- if (displayToken == NULL) {
+static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs& captureArgs) {
+ captureArgs.pixelFormat = static_cast<ui::PixelFormat>(
+ env->GetIntField(captureArgsObject, gCaptureArgsClassInfo.pixelFormat));
+ captureArgs.sourceCrop =
+ rectFromObj(env,
+ env->GetObjectField(captureArgsObject, gCaptureArgsClassInfo.sourceCrop));
+ captureArgs.frameScale =
+ env->GetFloatField(captureArgsObject, gCaptureArgsClassInfo.frameScale);
+ captureArgs.captureSecureLayers =
+ env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.captureSecureLayers);
+}
+
+static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
+ jobject displayCaptureArgsObject) {
+ DisplayCaptureArgs captureArgs;
+ getCaptureArgs(env, displayCaptureArgsObject, captureArgs);
+
+ captureArgs.displayToken =
+ ibinderForJavaObject(env,
+ env->GetObjectField(displayCaptureArgsObject,
+ gDisplayCaptureArgsClassInfo.displayToken));
+ captureArgs.width =
+ env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.width);
+ captureArgs.height =
+ env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.height);
+ captureArgs.useIdentityTransform =
+ env->GetBooleanField(displayCaptureArgsObject,
+ gDisplayCaptureArgsClassInfo.useIdentityTransform);
+ captureArgs.rotation = ui::toRotation(
+ env->GetIntField(displayCaptureArgsObject, gDisplayCaptureArgsClassInfo.rotation));
+ return captureArgs;
+}
+
+static jobject nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject) {
+ const DisplayCaptureArgs captureArgs =
+ displayCaptureArgsFromObject(env, displayCaptureArgsObject);
+
+ if (captureArgs.displayToken == NULL) {
return NULL;
}
- const ui::ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(displayToken);
- const ui::Dataspace dataspace = pickDataspaceFromColorMode(colorMode);
-
- Rect sourceCrop = rectFromObj(env, sourceCropObj);
- sp<GraphicBuffer> buffer;
- bool capturedSecureLayers = false;
- status_t res = ScreenshotClient::capture(displayToken, dataspace,
- ui::PixelFormat::RGBA_8888,
- sourceCrop, width, height,
- useIdentityTransform, ui::toRotation(rotation),
- captureSecureLayers, &buffer, capturedSecureLayers);
+
+ ScreenCaptureResults captureResults;
+ status_t res = ScreenshotClient::captureDisplay(captureArgs, captureResults);
if (res != NO_ERROR) {
return NULL;
}
- jobject jhardwareBuffer =
- android_hardware_HardwareBuffer_createFromAHardwareBuffer(env,
- buffer->toAHardwareBuffer());
- const jint namedColorSpace = fromDataspaceToNamedColorSpaceValue(dataspace);
+ jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer(
+ env, captureResults.buffer->toAHardwareBuffer());
+ const jint namedColorSpace =
+ fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace);
return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz,
gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer,
- namedColorSpace, capturedSecureLayers);
+ namedColorSpace, captureResults.capturedSecureLayers);
}
-static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject displayTokenObj,
- jlong layerObject, jobject sourceCropObj, jfloat frameScale,
- jlongArray excludeObjectArray, jint format) {
-
- auto layer = reinterpret_cast<SurfaceControl *>(layerObject);
- if (layer == NULL) {
- return NULL;
- }
-
- Rect sourceCrop;
- if (sourceCropObj != NULL) {
- sourceCrop = rectFromObj(env, sourceCropObj);
+static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject) {
+ LayerCaptureArgs captureArgs;
+ getCaptureArgs(env, layerCaptureArgsObject, captureArgs);
+ SurfaceControl* layer = reinterpret_cast<SurfaceControl*>(
+ env->GetLongField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.layer));
+ if (layer == nullptr) {
+ return nullptr;
}
- std::unordered_set<sp<IBinder>,ISurfaceComposer::SpHash<IBinder>> excludeHandles;
+ captureArgs.layerHandle = layer->getHandle();
+ captureArgs.childrenOnly =
+ env->GetBooleanField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.childrenOnly);
+ jlongArray excludeObjectArray = reinterpret_cast<jlongArray>(
+ env->GetObjectField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.excludeLayers));
if (excludeObjectArray != NULL) {
const jsize len = env->GetArrayLength(excludeObjectArray);
- excludeHandles.reserve(len);
+ captureArgs.excludeHandles.reserve(len);
const jlong* objects = env->GetLongArrayElements(excludeObjectArray, nullptr);
for (jsize i = 0; i < len; i++) {
@@ -333,33 +378,24 @@ static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject displayTok
jniThrowNullPointerException(env, "Exclude layer is null");
return NULL;
}
- excludeHandles.emplace(excludeObject->getHandle());
+ captureArgs.excludeHandles.emplace(excludeObject->getHandle());
}
env->ReleaseLongArrayElements(excludeObjectArray, const_cast<jlong*>(objects), JNI_ABORT);
}
- sp<GraphicBuffer> buffer;
- ui::Dataspace dataspace = ui::Dataspace::V0_SRGB;
- sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
- if (displayToken != nullptr) {
- const ui::ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(displayToken);
- dataspace = pickDataspaceFromColorMode(colorMode);
- }
- status_t res = ScreenshotClient::captureChildLayers(layer->getHandle(), dataspace,
- static_cast<ui::PixelFormat>(format),
- sourceCrop, excludeHandles, frameScale,
- &buffer);
+ ScreenCaptureResults captureResults;
+ status_t res = ScreenshotClient::captureLayers(captureArgs, captureResults);
if (res != NO_ERROR) {
return NULL;
}
- jobject jhardwareBuffer =
- android_hardware_HardwareBuffer_createFromAHardwareBuffer(env,
- buffer->toAHardwareBuffer());
- const jint namedColorSpace = fromDataspaceToNamedColorSpaceValue(dataspace);
+ jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer(
+ env, captureResults.buffer->toAHardwareBuffer());
+ const jint namedColorSpace =
+ fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace);
return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz,
gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer,
- namedColorSpace, false /* capturedSecureLayers */);
+ namedColorSpace, captureResults.capturedSecureLayers);
}
static void nativeApplyTransaction(JNIEnv* env, jclass clazz, jlong transactionObj, jboolean sync) {
@@ -1614,13 +1650,12 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSeverChildren } ,
{"nativeSetOverrideScalingMode", "(JJI)V",
(void*)nativeSetOverrideScalingMode },
- {"nativeScreenshot",
- "(Landroid/os/IBinder;Landroid/graphics/Rect;IIZIZ)"
+ {"nativeCaptureDisplay",
+ "(Landroid/view/SurfaceControl$DisplayCaptureArgs;)"
"Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;",
- (void*)nativeScreenshot },
+ (void*)nativeCaptureDisplay },
{"nativeCaptureLayers",
- "(Landroid/os/IBinder;JLandroid/graphics/Rect;"
- "F[JI)"
+ "(Landroid/view/SurfaceControl$LayerCaptureArgs;)"
"Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;",
(void*)nativeCaptureLayers },
{"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V",
@@ -1795,6 +1830,36 @@ int register_android_view_SurfaceControl(JNIEnv* env)
gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMax =
GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "appRequestRefreshRateMax", "F");
+ jclass captureArgsClazz = FindClassOrDie(env, "android/view/SurfaceControl$CaptureArgs");
+ gCaptureArgsClassInfo.pixelFormat = GetFieldIDOrDie(env, captureArgsClazz, "mPixelFormat", "I");
+ gCaptureArgsClassInfo.sourceCrop =
+ GetFieldIDOrDie(env, captureArgsClazz, "mSourceCrop", "Landroid/graphics/Rect;");
+ gCaptureArgsClassInfo.frameScale = GetFieldIDOrDie(env, captureArgsClazz, "mFrameScale", "F");
+ gCaptureArgsClassInfo.captureSecureLayers =
+ GetFieldIDOrDie(env, captureArgsClazz, "mCaptureSecureLayers", "Z");
+
+ jclass displayCaptureArgsClazz =
+ FindClassOrDie(env, "android/view/SurfaceControl$DisplayCaptureArgs");
+ gDisplayCaptureArgsClassInfo.displayToken =
+ GetFieldIDOrDie(env, displayCaptureArgsClazz, "mDisplayToken", "Landroid/os/IBinder;");
+ gDisplayCaptureArgsClassInfo.width =
+ GetFieldIDOrDie(env, displayCaptureArgsClazz, "mWidth", "I");
+ gDisplayCaptureArgsClassInfo.height =
+ 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");
+ gLayerCaptureArgsClassInfo.layer =
+ GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeLayer", "J");
+ gLayerCaptureArgsClassInfo.excludeLayers =
+ GetFieldIDOrDie(env, layerCaptureArgsClazz, "mNativeExcludeLayers", "[J");
+ gLayerCaptureArgsClassInfo.childrenOnly =
+ GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z");
+
return err;
}
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 097af763038c..5b22e3126eaf 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2693,4 +2693,9 @@ enum PageId {
// CATEGORY: SETTINGS
// OS: R QPR
SETTINGS_SWIPE_BOTTOM_TO_NOTIFICATION = 1846;
+
+ // OPEN: Settings > System > Gestures > Emergency SOS Gesture
+ // CATEGORY: SETTINGS
+ // OS: S
+ EMERGENCY_SOS_GESTURE_SETTINGS = 1847;
}
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index ac143ac1a147..e4a142b3335b 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -445,14 +445,14 @@ message GlobalSettingsProto {
// i.e. <pkg1>,<pkg2>,...,<pkgN>
optional SettingProto game_driver_opt_out_apps = 10;
// Game Driver - List of Apps that are forbidden to use Game Driver
- optional SettingProto game_driver_blacklist = 11;
+ optional SettingProto game_driver_denylist = 11;
// Game Driver - List of Apps that are allowed to use Game Driver
- optional SettingProto game_driver_whitelist = 12;
+ optional SettingProto game_driver_allowlist = 12;
// ANGLE - List of Apps that can check ANGLE rules
- optional SettingProto angle_whitelist = 13;
- // Game Driver - List of blacklists, each blacklist is a blacklist for
+ optional SettingProto angle_allowlist = 13;
+ // Game Driver - List of denylists, each denylist is a denylist for
// a specific Game Driver version
- optional SettingProto game_driver_blacklists = 14;
+ optional SettingProto game_driver_denylists = 14;
// ANGLE - Show a dialog box when ANGLE is selected for the currently running PKG
optional SettingProto show_angle_in_use_dialog = 15;
// Game Driver - List of libraries in sphal accessible by Game Driver
diff --git a/core/proto/android/server/alarm/alarmmanagerservice.proto b/core/proto/android/server/alarm/alarmmanagerservice.proto
index b74991d525af..e1240245d20f 100644
--- a/core/proto/android/server/alarm/alarmmanagerservice.proto
+++ b/core/proto/android/server/alarm/alarmmanagerservice.proto
@@ -59,9 +59,10 @@ message AlarmManagerServiceDumpProto {
// Time since the last wakeup was set.
optional int64 time_since_last_wakeup_set_ms = 15;
optional int64 time_change_event_count = 16;
- // The current set of user whitelisted apps for device idle mode, meaning
+ // The current set of user exempted apps for device idle mode, meaning
// these are allowed to freely schedule alarms. These are app IDs, not UIDs.
- repeated int32 device_idle_user_whitelist_app_ids = 17;
+ // This field is currently unused.
+ repeated int32 device_idle_user_exempt_app_ids = 17;
repeated AlarmClockMetadataProto next_alarm_clock_metadata = 18;
diff --git a/core/proto/android/server/appstatetracker.proto b/core/proto/android/server/appstatetracker.proto
index 51e88451c7c2..f5583d4f476f 100644
--- a/core/proto/android/server/appstatetracker.proto
+++ b/core/proto/android/server/appstatetracker.proto
@@ -41,14 +41,14 @@ message AppStateTrackerProto {
// UIDs currently in the foreground.
repeated int32 foreground_uids = 11;
- // App ids that are in power-save whitelist.
- repeated int32 power_save_whitelist_app_ids = 3;
+ // App ids that are in power-save exemption list.
+ repeated int32 power_save_exempt_app_ids = 3;
- // App ids that are in power-save user whitelist.
- repeated int32 power_save_user_whitelist_app_ids = 12;
+ // App ids that are in power-save user exemption list.
+ repeated int32 power_save_user_exempt_app_ids = 12;
- // App ids that are in temporary power-save whitelist.
- repeated int32 temp_power_save_whitelist_app_ids = 4;
+ // App ids that are in temporary power-save exemption list.
+ repeated int32 temp_power_save_exempt_app_ids = 4;
message RunAnyInBackgroundRestrictedPackages {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -79,5 +79,5 @@ message AppStateTrackerProto {
}
// Packages that are in the EXEMPT bucket.
- repeated ExemptedPackage exempted_packages = 10;
+ repeated ExemptedPackage exempted_bucket_packages = 10;
}
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index c21663811756..ff0ba8dd5ad4 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -204,6 +204,7 @@ message DisplayAreaProto {
optional WindowContainerProto window_container = 1;
optional string name = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
repeated DisplayAreaChildProto children = 3 [deprecated=true];
+ optional bool is_task_display_area = 4;
}
/* represents a generic child of a DisplayArea */
@@ -275,7 +276,7 @@ message TaskProto {
optional bool adjusted_for_ime = 23;
optional float adjust_ime_amount = 24;
optional float adjust_divider_amount = 25;
- optional bool animating_bounds = 26;
+ optional bool animating_bounds = 26 [deprecated = true];
optional float minimize_amount = 27;
optional bool created_by_organizer = 28;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index bae3bf905082..fe290f3e97e8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -355,7 +355,6 @@
<protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_ALLOWED_CARRIER" />
<protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_DISALLOWED_CARRIER" />
<protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_DISMISSED" />
- <protected-broadcast android:name="com.android.server.wifi.action.CarrierNetwork.USER_CLICKED" />
<protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.USER_DISMISSED_NOTIFICATION" />
<protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.CONNECT_TO_NETWORK" />
<protected-broadcast android:name="com.android.server.wifi.ConnectToNetworkNotification.PICK_WIFI_NETWORK" />
diff --git a/core/res/res/drawable-car/car_dialog_button_background.xml b/core/res/res/drawable-car/car_dialog_button_background.xml
index a7d40bcd759a..72e5af308c01 100644
--- a/core/res/res/drawable-car/car_dialog_button_background.xml
+++ b/core/res/res/drawable-car/car_dialog_button_background.xml
@@ -16,11 +16,18 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true">
- <ripple android:color="#4b9eff">
- <item android:id="@android:id/mask">
- <color android:color="@*android:color/car_white_1000"/>
+ <layer-list>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="#3D94CBFF"/>
+ </shape>
</item>
- </ripple>
+ <item>
+ <shape android:shape="rectangle">
+ <stroke android:width="8dp" android:color="#94CBFF"/>
+ </shape>
+ </item>
+ </layer-list>
</item>
<item>
<ripple android:color="?android:attr/colorControlHighlight">
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 03c682fd74af..f5facea7fc26 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Druk kieslys om oop te sluit of maak noodoproep."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Druk kieslys om oop te maak."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Teken patroon om te ontsluit"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Noodoproep"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Keer terug na oproep"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Reg!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Probeer weer"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index f80da896d8fa..b1183689c5ee 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"ለመክፈት ምናሌ ተጫንወይም የአደጋ ጊዜ ጥሪ አድርግ።"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"ለመክፈት ምናሌ ተጫን"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"ለመክፈት ስርዓተ ጥለት ሳል"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"የአደጋ ጊዜ ጥሪ"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"ወደ ጥሪ ተመለስ"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ትክክል!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"እንደገና ሞክር"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 41e3e26afc2c..26dac618ee7e 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -844,8 +844,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"اضغط على \"القائمة\" لإلغاء التأمين أو إجراء اتصال بالطوارئ."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"اضغط على \"القائمة\" لإلغاء التأمين."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"رسم نقش لإلغاء التأمين"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"مكالمة طوارئ"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"العودة إلى الاتصال"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"صحيح!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"أعد المحاولة"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index c6c8bb502ba8..d0ed635e69a8 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"আনলক কৰিবলৈ বা জৰুৰীকালীন কল কৰিবলৈ মেনু টিপক।"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"আনলক কৰিবলৈ মেনু টিপক।"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"আনলক কৰিবলৈ আর্হি আঁকক"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"জৰুৰীকালীন কল"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"কললৈ উভতি যাওক"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"শুদ্ধ!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"আকৌ চেষ্টা কৰক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index f0ff88365173..c721bbf8c829 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Təcili zəng kilidini açmaq və ya yerləşdirmək üçün Menyu düyməsinə basın."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Kilidi açmaq üçün Menyu düyməsinə basın."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Kilidi açmaq üçün model çəkin"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Təcili zəng"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Zəngə qayıt"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Düzdür!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Bir də cəhd edin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 8319da7ca7ee..93ddbe521ac5 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -835,8 +835,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pritisnite „Meni“ da biste otključali telefon ili uputite hitan poziv."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Pritisnite „Meni“ za otključavanje."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Unesite šablon za otključavanje"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Hitni poziv"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Nazad na poziv"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Tačno!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Probajte ponovo"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 3540516fd9f3..cff1218bd81b 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -568,7 +568,7 @@
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Аўтэнтыфікацыя па адбітках пальцаў скасавана карыстальнікам."</string>
<string name="fingerprint_error_lockout" msgid="7853461265604738671">"Занадта шмат спроб. Паспрабуйце яшчэ раз пазней."</string>
<string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Занадта шмат спроб. Сканер адбіткаў пальцаў выключаны."</string>
- <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Паспрабуйце яшчэ раз."</string>
+ <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Паўтарыце спробу."</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Адбіткі пальцаў не зарэгістраваны."</string>
<string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На гэтай прыладзе няма сканера адбіткаў пальцаў."</string>
<string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Датчык часова выключаны."</string>
@@ -838,11 +838,10 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Націсніце \"Меню\", каб разблакаваць, або зрабіце экстраны выклік."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Націсніце \"Меню\", каб разблакаваць."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Намалюйце камбінацыю разблакоўкі, каб разблакаваць"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Экстранны выклік"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Вярнуцца да выкліку"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Правільна!"</string>
- <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Паспрабуйце яшчэ раз"</string>
+ <string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Паўтарыце спробу"</string>
<string name="lockscreen_password_wrong" msgid="8605355913868947490">"Паўтарыце спробу"</string>
<string name="lockscreen_storage_locked" msgid="634993789186443380">"Разблакіраваць для ўсіх функцый і даных"</string>
<string name="faceunlock_multiple_failures" msgid="681991538434031708">"Перавышана максімальная колькасць спроб разблакоўкі праз Фэйскантроль"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 6643bcfa822c..e49ae26a93ac 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Натиснете „Меню“, за да отключите или да извършите спешно обаждане."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Натиснете „Меню“, за да отключите."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Нарисувайте фигура, за да отключите"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Спешно обаждане"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Назад към обаждането"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Правилно!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Опитайте отново"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index cbec4ac51d09..ffc9ecf02b18 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"আনলক করতে বা জরুরি কল করতে মেনু টিপুন৷"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"আনলক করতে মেনু টিপুন৷"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"আনলক করতে প্যাটার্ন আঁকুন"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"জরুরি কল"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"কলে ফিরুন"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"সঠিক!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"আবার চেষ্টা করুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 87b02f553037..0e176b53f236 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -835,8 +835,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pritisnite dugme Meni kako biste otključali uređaj ili obavili hitni poziv."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Pritisnite dugme Meni za otključavanje uređaja."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Nacrtajte uzorak za otključavanje"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Hitni poziv"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Povratak na poziv"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Ispravno!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Pokušajte ponovo"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 5fadc92d2970..2e4169e15c3b 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -543,7 +543,7 @@
<string name="biometric_error_user_canceled" msgid="6732303949695293730">"S\'ha cancel·lat l\'autenticació"</string>
<string name="biometric_not_recognized" msgid="5106687642694635888">"No s\'ha reconegut"</string>
<string name="biometric_error_canceled" msgid="8266582404844179778">"S\'ha cancel·lat l\'autenticació"</string>
- <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No s\'ha establert cap PIN, patró o contrasenya"</string>
+ <string name="biometric_error_device_not_secured" msgid="3129845065043995924">"No s\'ha definit cap PIN, patró o contrasenya"</string>
<string name="biometric_error_generic" msgid="6784371929985434439">"Error en l\'autenticació"</string>
<string name="fingerprint_acquired_partial" msgid="8532380671091299342">"S\'ha detectat una empremta digital parcial. Torna-ho a provar."</string>
<string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"No s\'ha pogut processar l\'empremta digital. Torna-ho a provar."</string>
@@ -832,7 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Premeu Menú per desbloquejar-lo o per fer una trucada d\'emergència."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Premeu Menú per desbloquejar."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Dibuixeu el patró de desbloqueig"</string>
- <string name="lockscreen_emergency_call" msgid="7500692654885445299">"Emergència"</string>
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Trucada d\'emergència"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Torna a la trucada"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correcte!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Torna-ho a provar"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index c69ca37d0f1c..34e6efb2bf78 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -838,8 +838,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Chcete-li odemknout telefon nebo provést tísňové volání, stiskněte Menu."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Telefon odemknete stisknutím tlačítka Menu."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Odblokujte pomocí gesta"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Tísňové volání"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Zavolat zpět"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Správně!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Zkusit znovu"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index fb100773dfa6..117fecb0ffd0 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Tryk på Menu for at låse op eller foretage et nødopkald."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Tryk på Menu for at låse op."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Tegn oplåsningsmønster"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Nødopkald"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Tilbage til opkald"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Rigtigt!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Prøv igen"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 4adcf0ae48ec..faa78df458e0 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Drücke die Menütaste, um das Telefon zu entsperren oder einen Notruf zu tätigen."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Zum Entsperren die Menütaste drücken"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Muster zum Entsperren zeichnen"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Notruf"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Zurück zum Anruf"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Korrekt!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Erneut versuchen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 23895f4fbf57..2e1b56ad9ff9 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Πατήστε \"Menu\" για ξεκλείδωμα ή για κλήση έκτακτης ανάγκης."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Σχεδιασμός μοτίβου για ξεκλείδωμα"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Κλήση έκτακτης ανάγκης"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Επιστροφή στην κλήση"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Σωστό!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Προσπαθήστε ξανά"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 0484ccd8abaa..dcfbf5a49748 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Press Menu to unlock or place emergency call."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Press Menu to unlock."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Draw pattern to unlock"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Emergency call"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Return to call"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correct!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Try again"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 9981c1212123..65f2426b6e08 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Press Menu to unlock or place emergency call."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Press Menu to unlock."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Draw pattern to unlock"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Emergency call"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Return to call"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correct!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Try again"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 02cdf69a2cd8..d38e2fe844ad 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Press Menu to unlock or place emergency call."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Press Menu to unlock."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Draw pattern to unlock"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Emergency call"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Return to call"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correct!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Try again"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 3b18aca951f7..30a9bf88619d 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Press Menu to unlock or place emergency call."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Press Menu to unlock."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Draw pattern to unlock"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Emergency call"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Return to call"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correct!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Try again"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 7e8a89aa5a94..27ff3f0d4531 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Presiona el Menú para desbloquear o realizar una llamada de emergencia."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Presionar Menú para desbloquear."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Dibujar el patrón de desbloqueo"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Llamada de emergencia"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Regresar a llamada"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correcto"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Vuelve a intentarlo."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 02aafa75945a..67350cb04fe1 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pulsa la tecla de menú para desbloquear el teléfono o realizar una llamada de emergencia."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Pulsa la tecla de menú para desbloquear la pantalla."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Dibujar patrón de desbloqueo"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Llamada de emergencia"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Volver a llamada"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correcto"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Vuelve a intentarlo"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 813629417a8e..3929ed4d50da 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Vajutage avamiseks või hädaabikõne tegemiseks menüünuppu"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Vajutage avamiseks menüüklahvi."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Avamiseks joonistage muster"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Hädaabikõne"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Kõne juurde tagasi"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Õige."</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Proovige uuesti"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 1b88f2708782..ecce980c613f 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -350,11 +350,11 @@
<string name="permlab_receiveMms" msgid="4000650116674380275">"jaso testu-mezuak (MMSak)"</string>
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"desbideratu sare mugikor bidezko igorpen-mezuak"</string>
- <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sare mugikor bidezko igorpen-modulura lotzeko baimena ematen dio aplikazioari, sare mugikor bidezko igorpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko igorpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-igorpenak jasotzean, aplikazio maltzurrek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string>
+ <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sare mugikor bidezko igorpen-modulura lotzeko baimena ematen dio aplikazioari, sare mugikor bidezko igorpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko igorpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-igorpenak jasotzean, aplikazio gaiztoek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"irakurri sare mugikor bidezko igorpen-mezuak"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Gailuak jasotako sare mugikor bidezko igorpenen mezuak irakurtzeko baimena ematen die aplikazioei. Sare mugikor bidezko igorpen-alertak kokapen batzuetan ematen dira larrialdi-egoeren berri emateko. Aplikazio gaiztoek gailuaren errendimendua edo funtzionamendua oztopa dezakete larrialdi-igorpen horietako bat jasotzen denean."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"irakurri harpidetutako jarioak"</string>
- <string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"Unean sinkronizatutako jarioei buruzko xehetasunak lortzeko baimena ematen die aplikazioei."</string>
+ <string name="permdesc_subscribedFeedsRead" msgid="6911349196661811865">"Une horretan sinkronizatutako jarioei buruzko xehetasunak lortzeko baimena ematen die aplikazioei."</string>
<string name="permlab_sendSms" msgid="7757368721742014252">"bidali eta ikusi SMS mezuak"</string>
<string name="permdesc_sendSms" msgid="6757089798435130769">"SMS mezuak bidaltzeko baimena ematen die aplikazioei. Horrela, ustekabeko gastuak eragin daitezke. Aplikazio gaiztoek erabil dezakete zuk berretsi gabeko mezuak bidalita gastuak eragiteko."</string>
<string name="permlab_readSms" msgid="5164176626258800297">"irakurri testu-mezuak (SMSak edo MMSak)"</string>
@@ -364,7 +364,7 @@
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"jaso testu-mezuak (WAP bidezkoak)"</string>
<string name="permdesc_receiveWapPush" msgid="1638677888301778457">"WAP mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak, besteak beste, gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
<string name="permlab_getTasks" msgid="7460048811831750262">"eskuratu abian diren aplikazioak"</string>
- <string name="permdesc_getTasks" msgid="7388138607018233726">"Unean edo duela gutxi exekutatutako zereginei buruzko informazioa lortzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailuan erabiltzen ari diren aplikazioei buruzko informazioa ezagut dezake."</string>
+ <string name="permdesc_getTasks" msgid="7388138607018233726">"Une honetan edo duela gutxi exekutatutako zereginei buruzko informazioa lortzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailuan erabiltzen ari diren aplikazioei buruzko informazioa ezagut dezake."</string>
<string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"kudeatu profilen eta gailuen jabeak"</string>
<string name="permdesc_manageProfileAndDeviceOwners" msgid="7304240671781989283">"Profilaren eta gailuaren jabeak zehazteko baimena ematen die aplikazioei."</string>
<string name="permlab_reorderTasks" msgid="7598562301992923804">"ordenatu abian diren aplikazioak"</string>
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Desblokeatzeko edo larrialdi-deia egiteko, sakatu Menua."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Desblokeatzeko, sakatu Menua."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Desblokeatzeko, marraztu eredua"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Larrialdi-deia"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Itzuli deira"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Eredua zuzena da!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Saiatu berriro"</string>
@@ -882,7 +881,7 @@
<string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"Pasahitza"</string>
<string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"Hasi saioa"</string>
<string name="lockscreen_glogin_invalid_input" msgid="4369219936865697679">"Erabiltzaile-izen edo pasahitz baliogabea."</string>
- <string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"Erabiltzaile-izena edo pasahitza ahaztu zaizu?\nZoaz "<b>"google.com/accounts/recovery"</b>" helbidera."</string>
+ <string name="lockscreen_glogin_account_recovery_hint" msgid="1683405808525090649">"Erabiltzaile-izena edo pasahitza ahaztu zaizu?\nJoan "<b>"google.com/accounts/recovery"</b>" helbidera."</string>
<string name="lockscreen_glogin_checking_password" msgid="2607271802803381645">"Egiaztatzen…"</string>
<string name="lockscreen_unlock_label" msgid="4648257878373307582">"Desblokeatu"</string>
<string name="lockscreen_sound_on_label" msgid="1660281470535492430">"Soinua aktibatuta"</string>
@@ -1604,7 +1603,7 @@
<string name="kg_login_password_hint" msgid="3330530727273164402">"Pasahitza"</string>
<string name="kg_login_submit_button" msgid="893611277617096870">"Hasi saioa"</string>
<string name="kg_login_invalid_input" msgid="8292367491901220210">"Erabiltzaile-izen edo pasahitz baliogabea."</string>
- <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Erabiltzaile-izena edo pasahitza ahaztu zaizu?\nZoaz "<b>"google.com/accounts/recovery"</b>" helbidera."</string>
+ <string name="kg_login_account_recovery_hint" msgid="4892466171043541248">"Erabiltzaile-izena edo pasahitza ahaztu zaizu?\nJoan "<b>"google.com/accounts/recovery"</b>" helbidera."</string>
<string name="kg_login_checking_password" msgid="4676010303243317253">"Kontua egiaztatzen…"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="23741434207544038">"PINa oker idatzi duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="3328686432962224215">"Pasahitza oker idatzi duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 506a7ee79dcb..1ee4be59733b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -829,11 +829,10 @@
<string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"شماره اضطراری"</string>
<string name="lockscreen_carrier_default" msgid="6192313772955399160">"بدون سرویس"</string>
<string name="lockscreen_screen_locked" msgid="7364905540516041817">"صفحه قفل شد."</string>
- <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"برای بازگشایی قفل یا انجام تماس اضطراری روی منو فشار دهید."</string>
+ <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"برای بازکردن قفل یا انجام تماس اضطراری روی «منو» فشار دهید."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"برای بازگشایی قفل روی منو فشار دهید."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"الگو را بکشید تا قفل آن باز شود"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"تماس اضطراری"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"بازگشت به تماس"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"صحیح است!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"دوباره امتحان کنید"</string>
@@ -1927,7 +1926,7 @@
<string name="time_picker_header_text" msgid="9073802285051516688">"تنظیم زمان"</string>
<string name="time_picker_input_error" msgid="8386271930742451034">"زمان معتبری وارد کنید"</string>
<string name="time_picker_prompt_label" msgid="303588544656363889">"زمان را تایپ کنید"</string>
- <string name="time_picker_text_input_mode_description" msgid="4761160667516611576">"برای وارد کردن زمان، به حالت وارد کردن نوشتار تغییر وضعیت دهید."</string>
+ <string name="time_picker_text_input_mode_description" msgid="4761160667516611576">"برای وارد کردن زمان، به حالت ورودی نوشتاری تغییر وضعیت دهید."</string>
<string name="time_picker_radial_mode_description" msgid="1222342577115016953">"برای وارد کردن زمان، به حالت ساعت تغییر وضعیت دهید."</string>
<string name="autofill_picker_accessibility_title" msgid="4425806874792196599">"گزینه‌های تکمیل خودکار"</string>
<string name="autofill_save_accessibility_title" msgid="1523225776218450005">"ذخیره کردن برای تکمیل خودکار"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 01db781a6ccd..1eff983e803f 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Poista lukitus tai soita hätäpuhelu painamalla Valikko-painiketta."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Poista lukitus painamalla Valikko-painiketta."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Poista lukitus piirtämällä kuvio"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Hätäpuhelu"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Palaa puheluun"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Oikein!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Yritä uudelleen"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index f5adc779e082..c6f347b1833b 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Appuyez sur \"Menu\" pour débloquer le téléphone ou appeler un numéro d\'urgence."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Appuyez sur \"Menu\" pour déverrouiller l\'appareil."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Dessinez un schéma pour déverrouiller le téléphone"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Appel d\'urgence"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Retour à l\'appel"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"C\'est exact!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Réessayer"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 8880dc63428f..6307c354317b 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Appuyez sur \"Menu\" pour déverrouiller le téléphone ou appeler un numéro d\'urgence"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Appuyez sur \"Menu\" pour déverrouiller le téléphone."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Dessinez un schéma pour déverrouiller le téléphone"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Appel d\'urgence"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Retour à l\'appel"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Combinaison correcte !"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Veuillez réessayer."</string>
@@ -1938,7 +1937,7 @@
<item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggestions de saisie automatique</item>
</plurals>
<string name="autofill_save_title" msgid="7719802414283739775">"Enregistrer dans "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ?"</string>
- <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ?"</string>
+ <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Enregistrer la <xliff:g id="TYPE">%1$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ?"</string>
<string name="autofill_save_title_with_2types" msgid="3783270967447869241">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ?"</string>
<string name="autofill_save_title_with_3types" msgid="6598228952100102578">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ?"</string>
<string name="autofill_update_title" msgid="3630695947047069136">"Mettre à jour cet élément dans "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ?"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index dffca1c2abcd..b3a4542614ac 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Preme Menú para desbloquear ou realizar unha chamada de emerxencia."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Preme Menú para desbloquear."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Crea o padrón de desbloqueo"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Chamada de emerxencia"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Volver á chamada"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correcto!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Téntao de novo"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 784e85f9a174..ca35a681f636 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"અનલૉક કરવા માટે અથવા કટોકટીનો કૉલ કરવા માટે મેનૂ દબાવો."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"અનલૉક કરવા માટે મેનૂ દબાવો."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"અનલૉક કરવા માટે પૅટર્ન દોરો."</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"ઇમર્જન્સી કૉલ"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"કૉલ પર પાછા ફરો"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"સાચું!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ફરી પ્રયાસ કરો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 82a106295acb..7b0bd238d7f7 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"लॉक खोलने के लिए मेन्यू दबाएं या आपातलकालीन कॉल करें."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"अनलॉक करने के लिए आकार आरेखित करें"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"आपातकालीन कॉल"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"कॉल पर वापस लौटें"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"सही!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"फिर से कोशिश करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index f1bcd398c65f..eb41c9f8f6f8 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -835,8 +835,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pritisnite Izbornik za otključavanje ili pozivanje hitnih službi."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Pritisnite Izbornik za otključavanje."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Iscrtajte uzorak za otključavanje"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Hitni poziv"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Uzvrati poziv"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Ispravno!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Pokušajte ponovo"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 3106371a2a33..0004ff1a3f13 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"A feloldáshoz vagy segélyhívás kezdeményezéséhez nyomja meg a Menü gombot."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"A feloldáshoz nyomja meg a Menü gombot."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Rajzolja le a mintát a feloldáshoz"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Segélyhívás"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Hívás folytatása"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Helyes!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Próbálja újra"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 85afc27bb14c..b115025fd63d 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Ապակողպելու կամ շտապ կանչ անելու համար սեղմեք «Ընտրացանկ»"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Ապակողպելու համար սեղմեք Ցանկը:"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Հավաքեք սխեման` ապակողպելու համար"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Շտապ կանչ"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Վերադառնալ զանգին"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Ճիշտ է:"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Կրկին փորձեք"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 8ec1f50eaceb..688996d87dba 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Tekan Menu untuk membuka atau melakukan panggilan darurat."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Tekan Menu untuk membuka."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Buat pola untuk membuka"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Panggilan darurat"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Kembali ke panggilan"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Perbaiki!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Coba lagi"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 1b0c2fe24521..899fa52fbb9f 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Ýttu á valmyndartakkann til að taka úr lás eða hringja neyðarsímtal."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Ýttu á valmyndartakkann til að taka úr lás."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Teiknaðu mynstur til að taka úr lás"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Neyðarsímtal"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Aftur í símtal"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Rétt!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Reyndu aftur"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d2bf62d94a40..400c44a4ef9c 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Premi Menu per sbloccare o effettuare chiamate di emergenza."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Premi Menu per sbloccare."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Traccia la sequenza di sblocco"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Chiamata di emergenza"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Torna a chiamata"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Corretta."</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Riprova"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 4d6d8155a981..2c4274532a02 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -838,7 +838,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"לחץ על \'תפריט\' כדי לבטל את הנעילה או כדי לבצע שיחת חירום."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"לחץ על \'תפריט\' כדי לבטל את הנעילה."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"שרטט קו לביטול נעילת המסך"</string>
- <string name="lockscreen_emergency_call" msgid="7500692654885445299">"חירום"</string>
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"שיחת חירום"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"חזרה לשיחה"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"נכון!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"כדאי לנסות שוב"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index f9674bd0db11..fdb505b696dc 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"MENUキーでロック解除(または緊急通報)"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"MENUキーでロック解除"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"パターンを入力"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"緊急通報"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"通話に戻る"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"一致しました"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"もう一度お試しください"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 3d1e9c799a4d..3d0d88b9e823 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"განბლოკვისთვის ან გადაუდებელი ზარისთვის დააჭირეთ მენიუს."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"განბლოკვისთვის დააჭირეთ მენიუს."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"განსაბლოკად დახატეთ ნიმუში"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"გადაუდებელი ზარი"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"ზარზე დაბრუნება"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"სწორია!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"კიდევ სცადეთ"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 38a50abfe6e7..6d063b647c41 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Бекітпесін ашу үшін немесе төтенше қоңырауды табу үшін Мәзір тармағын басыңыз."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Ашу үшін Мәзір пернесін басыңыз."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Бекітпесін ашу үшін кескінді сызыңыз"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Құтқару қызметіне қоңырау шалу"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Қоңырауға оралу"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Дұрыс!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Қайталап көріңіз"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 4e646c5d2a07..b9378def3491 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"ចុច​ម៉ឺនុយ ដើម្បី​ដោះ​សោ​ ឬ​ហៅ​ពេល​អាសន្ន។"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"ចុច​ម៉ឺនុយ ដើម្បី​ដោះ​សោ។"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"គូរ​លំនាំ ដើម្បី​ដោះ​សោ"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"ហៅទៅលេខសង្គ្រោះបន្ទាន់"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"ត្រឡប់​ទៅ​ការ​ហៅ"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ត្រឹមត្រូវ!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ព្យាយាម​ម្ដង​ទៀត"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 8d742156ca2c..cbb9ca2606f2 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ ಇಲ್ಲವೇ ತುರ್ತು ಕರೆಯನ್ನು ಮಾಡಿ."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಪ್ಯಾಟರ್ನ್ ಚಿತ್ರಿಸಿ"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"ತುರ್ತು ಕರೆ"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"ಕರೆಗೆ ಹಿಂತಿರುಗು"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ಸರಿಯಾಗಿದೆ!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 5d960dcc0aa7..78c3286eecf3 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"비상 전화를 걸거나 잠금해제하려면 메뉴를 누르세요."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"잠금해제하려면 메뉴를 누르세요."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"잠금해제를 위해 패턴 그리기"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"긴급 전화"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"통화로 돌아가기"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"맞습니다."</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"다시 시도"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index c97324f738b3..671863d68035 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -47,7 +47,7 @@
<string name="mismatchPin" msgid="2929611853228707473">"Терилген PIN\'дер дал келбейт."</string>
<string name="invalidPin" msgid="7542498253319440408">"Узундугу 4төн 8ге чейинки сандан турган PIN-кодду териңиз."</string>
<string name="invalidPuk" msgid="8831151490931907083">"Узундугу 8 же көбүрөөк сандан турган PUK-кодду териңиз."</string>
- <string name="needPuk" msgid="7321876090152422918">"SIM картаңыз PUK менен кулпуланган. Кулпусун ачуу үчүн PUK-кодду териңиз."</string>
+ <string name="needPuk" msgid="7321876090152422918">"SIM картаңыз PUK менен кулпуланган. Кулпусун ачуу үчүн, PUK-кодду териңиз."</string>
<string name="needPuk2" msgid="7032612093451537186">"SIM картаны бөгөттөн чыгаруу үчүн PUK2 кодун териңиз."</string>
<string name="enablePin" msgid="2543771964137091212">"Оңунан чыкпады, SIM/RUIM бөгөттөөсүн жандырыңыз."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
@@ -241,7 +241,7 @@
<string name="global_action_power_off" msgid="4404936470711393203">"Өчүрүү"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"Кубат"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Өчүрүп күйгүзүү"</string>
- <string name="global_action_emergency" msgid="1387617624177105088">"Тез жардам"</string>
+ <string name="global_action_emergency" msgid="1387617624177105088">"Шашылыш чалуу"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Ката тууралуу билдирүү"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Сеансты бүтүрүү"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"Скриншот"</string>
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Кулпусун ачып же Шашылыш чалуу аткаруу үчүн менюну басыңыз."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Бөгөттөн чыгаруу үчүн Менюну басыңыз."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Кулпуну ачуу үчүн, үлгүнү тартыңыз"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Шашылыш чалуу"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Чалууга кайтуу"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Туура!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Дагы аракет кылыңыз"</string>
@@ -1321,7 +1320,7 @@
<string name="console_running_notification_title" msgid="6087888939261635904">"Сериялык консоль иштетилди"</string>
<string name="console_running_notification_message" msgid="7892751888125174039">"Майнаптуулугуна таасири тиет. Аны өчүрүү үчүн операциялык тутумду жүктөгүчтү текшериңиз."</string>
<string name="usb_contaminant_detected_title" msgid="4359048603069159678">"USB портунда суюктук же урандылар бар"</string>
- <string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB порт автоматтык түрдө өчүрүлдү. Кененирээк маалымат алуу үчүн таптап коюңуз."</string>
+ <string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB порт автоматтык түрдө өчүрүлдү. Кененирээк маалымат алуу үчүн, таптап коюңуз."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"USB портун колдонууга болот"</string>
<string name="usb_contaminant_not_detected_message" msgid="892863190942660462">"Телефон суюктук менен урандыларды аныктаган жок."</string>
<string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"Мүчүлүштүк тууралуу кабар алынууда…"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index c1b3fe473aed..44511398c694 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"ກົດ ເມນູ ເພື່ອປົດລັອກ ຫຼື ໂທອອກຫາເບີສຸກເສີນ."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"ແຕ້ມຮູບແບບເພື່ອປົດລັອກ"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"ການໂທສຸກເສີນ"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"ກັບໄປຫາການໂທ"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ຖືກຕ້ອງ!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ລອງໃໝ່ອີກຄັ້ງ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index fc5709c0e089..fa0797846de4 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -838,8 +838,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Paspauskite „Meniu“, kad atrakintumėte ar skambintumėte pagalbos numeriu."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Paspauskite „Meniu“, jei norite atrakinti."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Nustatyti modelį, kad atrakintų"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Skambutis pagalbos numeriu"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"grįžti prie skambučio"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Teisingai!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Bandykite dar kartą"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index d780b14ae11a..e8107fb0c744 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -835,8 +835,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Nospiediet Izvēlne, lai atbloķētu, vai veiciet ārkārtas zvanu."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Lai atbloķētu, nospiediet vienumu Izvēlne."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Zīmējiet kombināciju, lai atbloķētu."</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Ārkārtas izsaukums"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Atpakaļ pie zvana"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Pareizi!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Mēģināt vēlreiz"</string>
@@ -1816,8 +1815,8 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Atjaunināja administrators"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Dzēsa administrators"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Labi"</string>
- <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Lai paildzinātu akumulatora darbības laiku, ieslēdzot akumulatora jaudas taupīšanas režīmu, tiek veiktas tālāk norādītās darbības.\n\n• Tiek ieslēgts tumšais motīvs.\n• Tiek izslēgtas vai ierobežotas fonā veiktās darbības, daži vizuālie efekti un citas funkcijas, piemēram, “Ok Google”.\n\n"<annotation id="url">"Uzzināt vairāk"</annotation></string>
- <string name="battery_saver_description" msgid="6794188153647295212">"Lai paildzinātu akumulatora darbības laiku, ieslēdzot akumulatora jaudas taupīšanas režīmu, tiek veiktas tālāk norādītās darbības.\n\n• Tiek ieslēgts tumšais motīvs.\n• Tiek izslēgtas vai ierobežotas fonā veiktās darbības, daži vizuālie efekti un citas funkcijas, piemēram, “Ok Google”."</string>
+ <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Lai paildzinātu akumulatora darbības laiku, ieslēdzot akumulatora enerģijas taupīšanas režīmu, tiek veiktas tālāk norādītās darbības.\n\n• Tiek ieslēgts tumšais motīvs.\n• Tiek izslēgtas vai ierobežotas fonā veiktās darbības, daži vizuālie efekti un citas funkcijas, piemēram, “Ok Google”.\n\n"<annotation id="url">"Uzzināt vairāk"</annotation></string>
+ <string name="battery_saver_description" msgid="6794188153647295212">"Lai paildzinātu akumulatora darbības laiku, ieslēdzot akumulatora enerģijas taupīšanas režīmu, tiek veiktas tālāk norādītās darbības.\n\n• Tiek ieslēgts tumšais motīvs.\n• Tiek izslēgtas vai ierobežotas fonā veiktās darbības, daži vizuālie efekti un citas funkcijas, piemēram, “Ok Google”."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Lai samazinātu datu lietojumu, datu lietojuma samazinātājs neļauj dažām lietotnēm fonā nosūtīt vai saņemt datus. Lietotne, kuru pašlaik izmantojat, var piekļūt datiem, bet, iespējams, piekļūs tiem retāk (piemēram, attēli tiks parādīti tikai tad, kad tiem pieskarsieties)."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Vai ieslēgt datu lietojuma samazinātāju?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Ieslēgt"</string>
@@ -2034,9 +2033,9 @@
<string name="notification_feedback_indicator" msgid="663476517711323016">"Sniegt atsauksmes"</string>
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Informatīvs paziņojums par akumulatoru"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Akumulators var izlādēties pirms parastā uzlādes laika"</string>
- <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Aktivizēts akumulatora jaudas taupīšanas režīms, lai palielinātu akumulatora darbības ilgumu"</string>
- <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akumulatora jaudas taupīšanas režīms"</string>
- <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akumulatora jaudas taupīšanas režīms ir izslēgts"</string>
+ <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Aktivizēts akumulatora enerģijas taupīšanas režīms, lai palielinātu akumulatora darbības ilgumu"</string>
+ <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Akumulatora enerģijas taupīšanas režīms"</string>
+ <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Akumulatora enerģijas taupīšanas režīms ir izslēgts"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Tālruņa uzlādes līmenis ir pietiekams. Funkcijas vairs netiek ierobežotas."</string>
<string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Planšetdatora uzlādes līmenis ir pietiekams. Funkcijas vairs netiek ierobežotas."</string>
<string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Ierīces uzlādes līmenis ir pietiekams. Funkcijas vairs netiek ierobežotas."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index b50c608190e4..8871293c1b2f 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Притисни „Мени“ да се отклучи или да направи итен повик."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Притиснете „Мени“ за да се отклучи."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Употребете ја шемата за да се отклучи"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Итен повик"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Врати се на повик"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Точно!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Обидете се повторно"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index b769fd23ab1e..af75969910d2 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"അൺലോക്ക് ചെയ്യുന്നതിനായി മെനു അമർത്തുക അല്ലെങ്കിൽ അടിയന്തര കോൾ വിളിക്കുക."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"അൺലോക്കുചെയ്യാൻ മെനു അമർത്തുക."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"അൺലോക്ക് ചെയ്യാൻ പാറ്റേൺ വരയ്‌ക്കുക"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"എമർജൻസി കോൾ"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"കോളിലേക്ക് മടങ്ങുക"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ശരി!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"വീണ്ടും ശ്രമിക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 7b41501e6a0f..a65f80c9332f 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Яаралтай дуудлага хийх буюу эсвэл түгжээг тайлах бол цэсийг дарна уу."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Тайлах бол цэсийг дарна уу."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Тайлах хээгээ зурна уу"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Яаралтай дуудлага"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Дуудлагаруу буцах"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Зөв!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Дахин оролдох"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 577803334c33..ec240c1c36fc 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"अनलॉक करण्‍यासाठी मेनू दाबा किंवा आणीबाणीचा कॉल करा."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"अनलॉक करण्यासाठी मेनू दाबा."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"अनलॉक करण्यासाठी पॅटर्न काढा"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"आणीबाणी कॉल"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"कॉलवर परत या"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"अचूक!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"पुन्हा प्रयत्न करा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index c30bcfc1800f..2e78b45cbb67 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Tekan Menu untuk menyahsekat atau membuat panggilan kecemasan."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Tekan Menu untuk membuka kunci."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Lukiskan corak untuk membuka kunci"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Panggilan kecemasan"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Kembali ke panggilan"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Betul!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Cuba lagi"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 243357eca3c2..1ebafa47f76e 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"ဖွင့်ရန်သို့မဟုတ်အရေးပေါ်ခေါ်ဆိုခြင်းပြုလုပ်ရန် မီနူးကိုနှိပ်ပါ"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"မီးနူးကို နှိပ်ခြင်းဖြင့် သော့ဖွင့်ပါ"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"ဖွင့်ရန်ပုံစံဆွဲပါ"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"အရေးပေါ် ခေါ်ဆိုမှု"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"ခေါ်ဆိုမှုထံပြန်သွားရန်"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"မှန်ပါသည်"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ထပ် စမ်းပါ"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 0a31b49c555c..ac21aec0080e 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Trykk på menyknappen for å låse opp eller ringe et nødnummer."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Trykk på menyknappen for å låse opp."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Tegn mønster for å låse opp"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Nødanrop"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Tilbake til samtale"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Riktig!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Prøv på nytt"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 9712b480b97b..fd7b1b2ab55a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"अनलक वा आपतकालीन कल गर्न मेनु थिच्नुहोस्।"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"अनलक गर्न मेनु थिच्नुहोस्।"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"अनलक गर्नु ढाँचा खिच्नुहोस्"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"आपतकालीन कल"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"कलमा फर्किनुहोस्"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"सही!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"फेरि प्रयास गर्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index d1a342c99590..f63e64760957 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -326,7 +326,7 @@
<string name="capability_title_canControlMagnification" msgid="7701572187333415795">"Schermvergroting bedienen"</string>
<string name="capability_desc_canControlMagnification" msgid="2206586716709254805">"Het zoomniveau en de positionering van het scherm bedienen."</string>
<string name="capability_title_canPerformGestures" msgid="9106545062106728987">"Gebaren uitvoeren"</string>
- <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan tikken, vegen, samenknijpen en andere gebaren uitvoeren."</string>
+ <string name="capability_desc_canPerformGestures" msgid="6619457251067929726">"Kan tikken, swipen, knijpen en andere gebaren uitvoeren."</string>
<string name="capability_title_canCaptureFingerprintGestures" msgid="1189053104594608091">"Vingerafdrukgebaren"</string>
<string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"Kan gebaren registreren die op de vingerafdruksensor van het apparaat worden getekend."</string>
<string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot maken"</string>
@@ -451,7 +451,7 @@
<string name="permlab_accessImsCallService" msgid="442192920714863782">"toegang tot IMS-service voor bellen"</string>
<string name="permdesc_accessImsCallService" msgid="6328551241649687162">"Hiermee kan de app de IMS-service gebruiken om te bellen zonder je tussenkomst."</string>
<string name="permlab_readPhoneState" msgid="8138526903259297969">"telefoonstatus en -identiteit lezen"</string>
- <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Hiermee kan de app toegang krijgen tot de telefoonfuncties van het apparaat, Met deze toestemming kan de app het telefoonnummer en de apparaat-ID\'s bepalen, of een gesprek actief is, en het andere telefoonnummer waarmee wordt gebeld."</string>
+ <string name="permdesc_readPhoneState" msgid="7229063553502788058">"Hiermee kan de app toegang krijgen tot de telefoonfuncties van het apparaat, Met deze rechten kan de app het telefoonnummer en de apparaat-ID\'s bepalen, of een gesprek actief is, en het andere telefoonnummer waarmee wordt gebeld."</string>
<string name="permlab_manageOwnCalls" msgid="9033349060307561370">"gesprekken doorschakelen via het systeem"</string>
<string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"Hiermee kan de app de bijbehorende gesprekken doorschakelen via het systeem om de belfunctionaliteit te verbeteren."</string>
<string name="permlab_callCompanionApp" msgid="3654373653014126884">"gesprekken via het systeem bekijken en beheren"</string>
@@ -489,7 +489,7 @@
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"netwerkverbindingen weergeven"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Hiermee kan de app informatie bekijken over netwerkverbindingen, zoals welke netwerken er zijn en welke verbonden zijn."</string>
<string name="permlab_createNetworkSockets" msgid="3224420491603590541">"volledige netwerktoegang"</string>
- <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"Hiermee kan de app netwerksockets maken en aangepaste netwerkprotocollen gebruiken. De browser en andere apps bieden mogelijkheden om gegevens via internet te verzenden, dus deze toestemming is niet vereist om gegevens via internet te verzenden."</string>
+ <string name="permdesc_createNetworkSockets" msgid="7722020828749535988">"Hiermee kan de app netwerksockets maken en aangepaste netwerkprotocollen gebruiken. De browser en andere apps bieden mogelijkheden om gegevens via internet te verzenden, dus deze rechten zijn niet vereist om gegevens via internet te verzenden."</string>
<string name="permlab_changeNetworkState" msgid="8945711637530425586">"netwerkverbinding wijzigen"</string>
<string name="permdesc_changeNetworkState" msgid="649341947816898736">"Hiermee kan de app de status van de netwerkverbinding wijzigen."</string>
<string name="permlab_changeTetherState" msgid="9079611809931863861">"getetherde verbinding wijzigen"</string>
@@ -569,7 +569,7 @@
<string name="fingerprint_name_template" msgid="8941662088160289778">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string>
<string-array name="fingerprint_error_vendor">
</string-array>
- <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdruk-pictogram"</string>
+ <string name="fingerprint_icon_content_description" msgid="4741068463175388817">"Vingerafdruk-icoon"</string>
<string name="permlab_manageFace" msgid="4569549381889283282">"hardware voor ontgrendelen via gezichtsherkenning beheren"</string>
<string name="permdesc_manageFace" msgid="6204569688492710471">"Hiermee kan de app methoden aanroepen om gezichtstemplates toe te voegen en te verwijderen voor gebruik."</string>
<string name="permlab_useFaceAuthentication" msgid="1011430526454859030">"hardware voor ontgrendelen via gezichtsherkenning gebruiken"</string>
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Druk op \'Menu\' om te ontgrendelen of noodoproep te plaatsen."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Druk op \'Menu\' om te ontgrendelen."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Patroon tekenen om te ontgrendelen"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Noodoproep"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Terug naar gesprek"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Juist!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Opnieuw proberen"</string>
@@ -954,12 +953,12 @@
<string name="autofill_parish" msgid="6847960518334530198">"Gemeente"</string>
<string name="autofill_area" msgid="8289022370678448983">"Gebied"</string>
<string name="autofill_emirate" msgid="2544082046790551168">"Emiraat"</string>
- <string name="permlab_readHistoryBookmarks" msgid="9102293913842539697">"je webbladwijzers en -geschiedenis lezen"</string>
- <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"Hiermee kan de app de geschiedenis lezen van alle URL\'s die in de systeemeigen browser zijn bezocht, en alle bookmarks in de systeemeigen browser. Let op: deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
- <string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"webbladwijzers en -geschiedenis schrijven"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bookmarks die zijn opgeslagen op je tablet. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden.."</string>
+ <string name="permlab_readHistoryBookmarks" msgid="9102293913842539697">"je webbookmarks en -geschiedenis lezen"</string>
+ <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"Hiermee kan de app de geschiedenis lezen van alle URL\'s die in de systeemeigen browser zijn bezocht, en alle bookmarks in de systeemeigen browser. Let op: deze rechten kunnen niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
+ <string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"webbookmarks en -geschiedenis schrijven"</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bookmarks die zijn opgeslagen op je tablet. Deze rechten kunnen niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
<string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"Hiermee kan de app de browsergeschiedenis of opgeslagen bookmarks bewerken op je Android TV-apparaat. Hierdoor kan de app mogelijk browsergegevens wissen of aanpassen. Opmerking: Dit recht kan niet worden afgedwongen door andere browsers of andere apps met internetmogelijkheden."</string>
- <string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bookmarks die zijn opgeslagen op je telefoon. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bookmarks die zijn opgeslagen op je telefoon. Deze rechten kunnen niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"een wekker instellen"</string>
<string name="permdesc_setAlarm" msgid="2185033720060109640">"Hiermee kan de app een wekker instellen in een geïnstalleerde wekker-app. Deze functie wordt door sommige wekker-apps niet geïmplementeerd."</string>
<string name="permlab_addVoicemail" msgid="4770245808840814471">"voicemail toevoegen"</string>
@@ -970,7 +969,7 @@
<string name="save_password_notnow" msgid="2878327088951240061">"Niet nu"</string>
<string name="save_password_remember" msgid="6490888932657708341">"Onthouden"</string>
<string name="save_password_never" msgid="6776808375903410659">"Nooit"</string>
- <string name="open_permission_deny" msgid="5136793905306987251">"Je hebt geen toestemming om deze pagina te openen."</string>
+ <string name="open_permission_deny" msgid="5136793905306987251">"Je hebt geen rechten om deze pagina te openen."</string>
<string name="text_copied" msgid="2531420577879738860">"Tekst naar klembord gekopieerd."</string>
<string name="copied" msgid="4675902854553014676">"Gekopieerd"</string>
<string name="more_item_label" msgid="7419249600215749115">"Meer"</string>
@@ -1398,7 +1397,7 @@
<string name="permlab_requestDeletePackages" msgid="2541172829260106795">"verwijdering van pakketten aanvragen"</string>
<string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"Hiermee kan een app verwijdering van pakketten aanvragen."</string>
<string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"vragen om batterijoptimalisatie te negeren"</string>
- <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Hiermee kan een app toestemming vragen om batterijoptimalisatie voor die app te negeren."</string>
+ <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"Hiermee kan een app rechten vragen om batterijoptimalisatie voor die app te negeren."</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"Tik twee keer voor zoomregeling"</string>
<string name="gadget_host_error_inflating" msgid="2449961590495198720">"Kan widget niet toevoegen."</string>
<string name="ime_action_go" msgid="5536744546326495436">"Ga"</string>
@@ -1410,13 +1409,13 @@
<string name="ime_action_default" msgid="8265027027659800121">"Uitvoeren"</string>
<string name="dial_number_using" msgid="6060769078933953531">"Nummer bellen\nmet <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="create_contact_using" msgid="6200708808003692594">"Contact maken\nmet <xliff:g id="NUMBER">%s</xliff:g>"</string>
- <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"De volgende apps verzoeken om toegang tot je account, nu en in de toekomst."</string>
+ <string name="grant_credentials_permission_message_header" msgid="5365733888842570481">"De volgende apps willen toegangsrechten voor je account, nu en in de toekomst."</string>
<string name="grant_credentials_permission_message_footer" msgid="1886710210516246461">"Wil je dit verzoek toestaan?"</string>
<string name="grant_permissions_header_text" msgid="3420736827804657201">"Verzoek om toegang"</string>
<string name="allow" msgid="6195617008611933762">"Toestaan"</string>
<string name="deny" msgid="6632259981847676572">"Weigeren"</string>
- <string name="permission_request_notification_title" msgid="1810025922441048273">"Toestemming gevraagd"</string>
- <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Toestemming gevraagd\nvoor account <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
+ <string name="permission_request_notification_title" msgid="1810025922441048273">"Rechten gevraagd"</string>
+ <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">"Rechten gevraagd\nvoor account <xliff:g id="ACCOUNT">%s</xliff:g>."</string>
<string name="forward_intent_to_owner" msgid="4620359037192871015">"Je gebruikt deze app buiten je werkprofiel"</string>
<string name="forward_intent_to_work" msgid="3620262405636021151">"U gebruikt deze app in je werkprofiel"</string>
<string name="input_method_binding_label" msgid="1166731601721983656">"Invoermethode"</string>
@@ -1502,7 +1501,7 @@
<string name="shareactionprovider_share_with" msgid="2753089758467748982">"Delen met"</string>
<string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"Delen met <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="content_description_sliding_handle" msgid="982510275422590757">"Schuifgreep. Tikken en blijven aanraken."</string>
- <string name="description_target_unlock_tablet" msgid="7431571180065859551">"Vegen om te ontgrendelen"</string>
+ <string name="description_target_unlock_tablet" msgid="7431571180065859551">"Swipen om te ontgrendelen"</string>
<string name="action_bar_home_description" msgid="1501655419158631974">"Navigeren naar startpositie"</string>
<string name="action_bar_up_description" msgid="6611579697195026932">"Omhoog navigeren"</string>
<string name="action_menu_overflow_description" msgid="4579536843510088170">"Meer opties"</string>
@@ -1773,7 +1772,7 @@
</plurals>
<string name="restr_pin_try_later" msgid="5897719962541636727">"Probeer het later opnieuw"</string>
<string name="immersive_cling_title" msgid="2307034298721541791">"Volledig scherm wordt weergegeven"</string>
- <string name="immersive_cling_description" msgid="7092737175345204832">"Veeg omlaag vanaf de bovenkant van het scherm om af te sluiten."</string>
+ <string name="immersive_cling_description" msgid="7092737175345204832">"Swipe omlaag vanaf de bovenkant van het scherm om af te sluiten."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Ik snap het"</string>
<string name="done_label" msgid="7283767013231718521">"Gereed"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Ronde schuifregelaar voor uren"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 84815f7a6133..a1fd3f022555 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"ଅନଲକ୍‌ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ କିମ୍ବା ଜରୁରୀକାଳୀନ କଲ୍‌ କରନ୍ତୁ।"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"ଅନଲକ୍‌ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"ଅନଲକ୍‌ କରିବା ପାଇଁ ପାଟର୍ନ ଆଙ୍କନ୍ତୁ"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"ଜରୁରୀକାଳୀନ କଲ୍"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"କଲ୍‌କୁ ଫେରନ୍ତୁ"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ଠିକ୍!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index c29308fd4c5b..903ff83a0572 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਮੀਨੂ ਦਬਾਓ ਜਾਂ ਸੰਕਟਕਾਲੀਨ ਕਾਲ ਕਰੋ।"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਮੀਨੂ ਦਬਾਓ।"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪੈਟਰਨ ਡ੍ਰਾ ਕਰੋ"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"ਸੰਕਟਕਾਲੀਨ ਕਾਲ"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"ਕਾਲ ਤੇ ਵਾਪਸ ਜਾਓ"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ਸਹੀ!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index df56457da65a..aeebf8845567 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -838,8 +838,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Naciśnij Menu, aby odblokować lub wykonać połączenie alarmowe."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Naciśnij Menu, aby odblokować."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Narysuj wzór, aby odblokować"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Połączenie alarmowe"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Powrót do połączenia"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Poprawnie!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Spróbuj ponownie."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 3ecf28d34ffd..aedc0471ac6f 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pressione Menu para desbloquear ou fazer uma chamada de emergência."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Pressione Menu para desbloquear."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Desenhe o padrão para desbloquear"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Chamada de emergência"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Retornar à chamada"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correto!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Tente novamente"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index dcc8e17609ac..883e4bf09251 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Prima Menu para desbloquear ou efectuar uma chamada de emergência."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Prima Menu para desbloquear."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Desenhar padrão para desbloquear"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Chamada de emergência"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Regressar à chamada"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correcto!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Tentar novamente"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 3ecf28d34ffd..aedc0471ac6f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pressione Menu para desbloquear ou fazer uma chamada de emergência."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Pressione Menu para desbloquear."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Desenhe o padrão para desbloquear"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Chamada de emergência"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Retornar à chamada"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Correto!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Tente novamente"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 64936689ee6e..ebc5827c2a7a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -835,8 +835,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Apăsați Meniu pentru a debloca sau pentru a efectua apeluri de urgență."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Apăsați Meniu pentru deblocare."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Desenați modelul pentru a debloca"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Apel de urgență"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Reveniți la apel"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Corect!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Încercați din nou"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 07abf6dbb28d..f3d13ceec060 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -838,8 +838,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Нажмите \"Меню\", чтобы разблокировать экран или вызвать службу экстренной помощи."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Для разблокировки нажмите \"Меню\"."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Введите графический ключ"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Экстренный вызов"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Вернуться к вызову"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Правильно!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Повторите попытку"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index d494a36520bf..cc6783a4fb3d 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"අගුළු හැරීමට මෙනුව ඔබන්න හෝ හදිසි ඇමතුම ලබාගන්න."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"අගුළු හැරීමට මෙනු ඔබන්න."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"අගුළු ඇරීමට රටාව අඳින්න"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"හදිසි ඇමතුම"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"ඇමතුම වෙත නැවත යන්න"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"නිවැරදියි!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"නැවත උත්සාහ කරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 52c53015743b..b6125657f408 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -838,8 +838,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Ak chcete odomknúť telefón alebo uskutočniť tiesňové volanie, stlačte Menu."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Telefón odomknete stlačením tlačidla Menu."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Odomknite nakreslením vzoru"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Tiesňové volanie"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Zavolať späť"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Správne!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Skúsiť znova"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index a43c900fb585..9f23a76de1d2 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -838,8 +838,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Če želite odkleniti napravo ali opraviti klic v sili, pritisnite meni."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Če želite odkleniti, pritisnite meni."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Če želite odkleniti, narišite vzorec"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Klic v sili"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Nazaj na klic"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Pravilno."</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Poskusi znova"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 625962fb9bd1..3e7ca92681c5 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Shtyp \"Meny\" për të shkyçur ose për të kryer telefonatë urgjence."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Shtyp \"Meny\" për të shkyçur."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Vizato modelin për ta shkyçur"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Telefonata e urgjencës"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Kthehu te telefonata"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Saktë!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Provo sërish"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6101dac65f95..a3eb3e412c55 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -835,8 +835,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Притисните „Мени“ да бисте откључали телефон или упутите хитан позив."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Притисните „Мени“ за откључавање."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Унесите шаблон за откључавање"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Хитни позив"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Назад на позив"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Тачно!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Пробајте поново"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index e30bb14384f9..e1442437df77 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Tryck på Menu för att låsa upp eller ringa nödsamtal."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Tryck på Menu för att låsa upp."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Rita grafiskt lösenord för att låsa upp"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Nödsamtal"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Tillbaka till samtal"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Korrekt!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Försök igen"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 4e4c0f656c9f..22736d8bca87 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Bonyeza Menyu ili kufungua au kupiga simu ya dharura."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Bonyeza Menyu ili kufungua."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Chora ruwaza ili kufungua"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Simu ya dharura"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Rudi kwa kupiga simu"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Sahihi!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Jaribu tena"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index a617248071e0..42b2d9c2f273 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"தடைநீக்க மெனுவை அழுத்தவும் அல்லது அவசர அழைப்பை மேற்கொள்ளவும்."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"திறக்க, மெனுவை அழுத்தவும்."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"திறக்க வடிவத்தை வரையவும்"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"அவசர அழைப்பு"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"அழைப்பிற்குத் திரும்பு"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"சரி!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"மீண்டும் முயற்சிக்கவும்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 794fec85bcf7..854427b983a0 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"అన్‌లాక్ చేయడానికి లేదా అత్యవసర కాల్ చేయడానికి మెను నొక్కండి."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"అన్‌లాక్ చేయడానికి మెను నొక్కండి."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"అన్‌లాక్ చేయడానికి నమూనాను గీయండి"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"ఎమర్జెన్సీ కాల్"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"కాల్‌కు తిరిగి వెళ్లు"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"సరైనది!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"మళ్లీ ప్రయత్నించండి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 3deb9b2b7b82..4b39c63a1bdf 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"กด เมนู เพื่อปลดล็อกหรือโทรฉุกเฉิน"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"กด เมนู เพื่อปลดล็อก"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"วาดรูปแบบเพื่อปลดล็อก"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"หมายเลขฉุกเฉิน"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"กลับสู่การโทร"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"ถูกต้อง!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"ลองอีกครั้ง"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ccda1c46059e..beebbd23448c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pindutin ang Menu upang i-unlock o magsagawa ng pang-emergency na tawag."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Pindutin ang Menu upang i-unlock."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Iguhit ang pattern upang i-unlock"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Emergency na tawag"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Bumalik sa tawag"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Tama!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Subukang muli"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 85c69860eb81..17852a6615de 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Kilidi açmak veya acil çağrı yapmak için Menü\'ye basın."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Kilidi açmak için Menü\'ye basın."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Kilit açmak için deseni çizin"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Acil durum araması"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Çağrıya dön"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Doğru!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Tekrar deneyin"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 8ae20a50f7f3..31684e0d1b29 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -838,8 +838,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Натис. меню, щоб розбл. чи зробити авар. виклик."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Натисн. меню, щоб розбл."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Намал. ключ, щоб розбл."</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Екстрений виклик"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Поверн. до дзвін."</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Правильно!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Повторіть спробу"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 94c6cd450a6c..ed32b2453bf3 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"غیر مقفل کرنے کیلئے مینو دبائیں یا ہنگامی کال کریں۔"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"غیر مقفل کرنے کیلئے مینو دبائیں۔"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"غیر مقفل کرنے کیلئے پیٹرن کو ڈرا کریں"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"ہنگامی کال"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"کال پر واپس جائیں"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"صحیح!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"دوبارہ کوشش کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 74676dfcf226..4f196440334c 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Qulfdan chiqarish yoki favqulodda qo‘ng‘iroqni amalga oshirish uchun \"Menyu\"ni bosing."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Qulfni ochish uchun \"Menyu\"ga bosing."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Qulfni ochish uchun grafik kalitni chizing"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Favqulodda chaqiruv"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Qo‘ng‘iroqni qaytarish"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"To‘g‘ri!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Qaytadan urining"</string>
@@ -902,7 +901,7 @@
<string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"Foydalanuvchi tanlagichi"</string>
<string name="keyguard_accessibility_status" msgid="6792745049712397237">"Holati"</string>
<string name="keyguard_accessibility_camera" msgid="7862557559464986528">"Kamera"</string>
- <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Media boshqaruvlari"</string>
+ <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"Media boshqaruvi"</string>
<string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"Vidjetlarni saralashni boshlandi."</string>
<string name="keyguard_accessibility_widget_reorder_end" msgid="1083806817600593490">"Vidjetlarni saralash tugatildi."</string>
<string name="keyguard_accessibility_widget_deleted" msgid="1509738950119878705">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> vidjeti o‘chirildi."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 48f38583220d..3cb264da95c3 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Nhấn vào Menu để mở khóa hoặc thực hiện cuộc gọi khẩn cấp."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Nhấn vào Menu để mở khóa."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Vẽ hình để mở khóa"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Cuộc gọi khẩn cấp"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Quay lại cuộc gọi"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Chính xác!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Thử lại"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index bf381ec53751..0a241dab0954 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"按 Menu 解锁或进行紧急呼救。"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"按 MENU 解锁。"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"绘制解锁图案"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"紧急呼叫"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"返回通话"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"正确!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"重试"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index a3b20d128726..6e584d6182d9 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"按選單鍵解鎖或撥打緊急電話。"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"按選單鍵解鎖。"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"畫出解鎖圖形以解除鎖定螢幕"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"緊急電話"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"返回通話"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"正確!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"再試一次"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index f6543c9285d2..ab1a42375871 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"按下 [Menu] 解鎖或撥打緊急電話。"</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"按下 Menu 鍵解鎖。"</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"畫出解鎖圖案"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"緊急電話"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"返回通話"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"正確!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"再試一次"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 85f54e9f9f5e..582d4350882c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -832,8 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Chofoza Menyu ukuvula noma ukwenza ikholi ephuthumayo."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Chofoza Menyu ukuvula."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Dweba iphathini ukuvula"</string>
- <!-- no translation found for lockscreen_emergency_call (7549683825868928636) -->
- <skip />
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Ikholi ephuthumayo"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Buyela ekholini"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Lungile!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Zama futhi"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bc4c099cbceb..8913e8b18750 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -983,7 +983,7 @@
with the modem or some other restricted hardware, add "/dev/bus/usb/001/"
to this list. If this is empty, no parts of the host USB bus will be excluded.
-->
- <string-array name="config_usbHostBlacklist" translatable="false">
+ <string-array name="config_usbHostDenylist" translatable="false">
</string-array>
<!-- List of paths to serial ports that are available to the serial manager.
@@ -2802,6 +2802,9 @@
eutran : eutranSupportedRelease
nfc : contactlessSupportedRelease
crl : rspCrlSupportedVersion
+ nrepc : nrEpcSupportedRelease
+ nr5gc : nr5gcSupportedRelease
+ eutran5gc : eutran5gcSupportedRelease
-->
<string-array translatable="false" name="config_telephonyEuiccDeviceCapabilities">
<!-- Example:
@@ -2813,6 +2816,9 @@
<item>"eutran,11"</item>
<item>"nfc,1"</item>
<item>"crl,1"</item>
+ <item>"nrepc,15"</item>
+ <item>"nr5gc,15"</item>
+ <item>"eutran5gc,15"</item>
-->
</string-array>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 16427cd50577..d5c72da2d29f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1853,7 +1853,7 @@
<java-symbol type="array" name="config_tether_upstream_types" />
<java-symbol type="array" name="config_tether_usb_regexs" />
<java-symbol type="array" name="config_tether_wifi_regexs" />
- <java-symbol type="array" name="config_usbHostBlacklist" />
+ <java-symbol type="array" name="config_usbHostDenylist" />
<java-symbol type="array" name="config_serialPorts" />
<java-symbol type="array" name="radioAttributes" />
<java-symbol type="array" name="config_oemUsbModeOverride" />
diff --git a/core/sysprop/Android.bp b/core/sysprop/Android.bp
new file mode 100644
index 000000000000..7f20a0ba6642
--- /dev/null
+++ b/core/sysprop/Android.bp
@@ -0,0 +1,21 @@
+// 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.
+
+sysprop_library {
+ name: "com.android.sysprop.localization",
+ srcs: ["LocalizationProperties.sysprop"],
+ property_owner: "Platform",
+ api_packages: ["android.sysprop"],
+ vendor_available: false,
+}
diff --git a/core/sysprop/LocalizationProperties.sysprop b/core/sysprop/LocalizationProperties.sysprop
new file mode 100644
index 000000000000..65f544fa6179
--- /dev/null
+++ b/core/sysprop/LocalizationProperties.sysprop
@@ -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.
+
+module: "android.sysprop.LocalizationProperties"
+owner: Platform
+
+prop {
+ api_name: "locale_filter"
+ type: String
+ prop_name: "ro.localization.locale_filter"
+ scope: Internal
+ access: Readonly
+}
diff --git a/core/sysprop/api/com.android.sysprop.localization-current.txt b/core/sysprop/api/com.android.sysprop.localization-current.txt
new file mode 100644
index 000000000000..fe4f4578683c
--- /dev/null
+++ b/core/sysprop/api/com.android.sysprop.localization-current.txt
@@ -0,0 +1,9 @@
+props {
+ module: "android.sysprop.LocalizationProperties"
+ prop {
+ api_name: "locale_filter"
+ type: String
+ scope: Internal
+ prop_name: "ro.localization.locale_filter"
+ }
+}
diff --git a/core/sysprop/api/com.android.sysprop.localization-latest.txt b/core/sysprop/api/com.android.sysprop.localization-latest.txt
new file mode 100644
index 000000000000..fe4f4578683c
--- /dev/null
+++ b/core/sysprop/api/com.android.sysprop.localization-latest.txt
@@ -0,0 +1,9 @@
+props {
+ module: "android.sysprop.LocalizationProperties"
+ prop {
+ api_name: "locale_filter"
+ type: String
+ scope: Internal
+ prop_name: "ro.localization.locale_filter"
+ }
+}
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
index 1edd9623ed2d..e42b4b4ae2bf 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -20,7 +20,11 @@ android_test {
"android.test.runner",
"android.test.base",
],
- static_libs: ["androidx.test.rules", "truth-prebuilt"],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "truth-prebuilt",
+ ],
test_suites: ["general-tests"],
sdk_version: "test_current",
platform_apis: true,
diff --git a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
index 153337727e96..9246a2335050 100644
--- a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
+++ b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
@@ -18,6 +18,8 @@ package com.android.os.bugreports.tests;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.Manifest;
@@ -25,17 +27,27 @@ import android.content.Context;
import android.os.BugreportManager;
import android.os.BugreportManager.BugreportCallback;
import android.os.BugreportParams;
+import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
+import android.os.StrictMode;
import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExternalResource;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -51,9 +63,11 @@ import java.util.concurrent.TimeUnit;
@RunWith(JUnit4.class)
public class BugreportManagerTest {
@Rule public TestName name = new TestName();
+ @Rule public ExtendedStrictModeVmPolicy mTemporaryVmPolicy = new ExtendedStrictModeVmPolicy();
private static final String TAG = "BugreportManagerTest";
private static final long BUGREPORT_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(10);
+ private static final long UIAUTOMATOR_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(10);
private Handler mHandler;
private Executor mExecutor;
@@ -86,6 +100,8 @@ public class BugreportManagerTest {
@After
public void teardown() throws Exception {
dropPermissions();
+ FileUtils.closeQuietly(mBugreportFd);
+ FileUtils.closeQuietly(mScreenshotFd);
}
@@ -95,47 +111,45 @@ public class BugreportManagerTest {
// wifi bugreport does not take screenshot
mBrm.startBugreport(mBugreportFd, null /*screenshotFd = null*/, wifi(),
mExecutor, callback);
+ shareConsentDialog(ConsentReply.ALLOW);
waitTillDoneOrTimeout(callback);
assertThat(callback.isDone()).isTrue();
// Wifi bugreports should not receive any progress.
assertThat(callback.hasReceivedProgress()).isFalse();
- // TODO: Because of b/130234145, consent dialog is not shown; so we get a timeout error.
- // When the bug is fixed, accept consent via UIAutomator and verify contents
- // of mBugreportFd.
- assertThat(callback.getErrorCode()).isEqualTo(
- BugreportCallback.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
+ assertThat(mBugreportFile.length()).isGreaterThan(0L);
assertFdsAreClosed(mBugreportFd);
}
+ @LargeTest
@Test
public void normalFlow_interactive() throws Exception {
BugreportCallbackImpl callback = new BugreportCallbackImpl();
// interactive bugreport does not take screenshot
mBrm.startBugreport(mBugreportFd, null /*screenshotFd = null*/, interactive(),
mExecutor, callback);
-
+ shareConsentDialog(ConsentReply.ALLOW);
waitTillDoneOrTimeout(callback);
+
assertThat(callback.isDone()).isTrue();
// Interactive bugreports show progress updates.
assertThat(callback.hasReceivedProgress()).isTrue();
- assertThat(callback.getErrorCode()).isEqualTo(
- BugreportCallback.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
+ assertThat(mBugreportFile.length()).isGreaterThan(0L);
assertFdsAreClosed(mBugreportFd);
}
+ @LargeTest
@Test
public void normalFlow_full() throws Exception {
BugreportCallbackImpl callback = new BugreportCallbackImpl();
mBrm.startBugreport(mBugreportFd, mScreenshotFd, full(), mExecutor, callback);
-
+ shareConsentDialog(ConsentReply.ALLOW);
waitTillDoneOrTimeout(callback);
+
assertThat(callback.isDone()).isTrue();
- assertThat(callback.getErrorCode()).isEqualTo(
- BugreportCallback.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
- // bugreport and screenshot files should be empty when user consent timed out.
- assertThat(mBugreportFile.length()).isEqualTo(0);
- assertThat(mScreenshotFile.length()).isEqualTo(0);
+ // bugreport and screenshot files shouldn't be empty when user consents.
+ assertThat(mBugreportFile.length()).isGreaterThan(0L);
+ assertThat(mScreenshotFile.length()).isGreaterThan(0L);
assertFdsAreClosed(mBugreportFd, mScreenshotFd);
}
@@ -144,6 +158,8 @@ public class BugreportManagerTest {
// Start bugreport #1
BugreportCallbackImpl callback = new BugreportCallbackImpl();
mBrm.startBugreport(mBugreportFd, mScreenshotFd, wifi(), mExecutor, callback);
+ // TODO(b/162389762) Make sure the wait time is reasonable
+ shareConsentDialog(ConsentReply.ALLOW);
// Before #1 is done, try to start #2.
assertThat(callback.isDone()).isFalse();
@@ -375,4 +391,88 @@ public class BugreportManagerTest {
private static BugreportParams full() {
return new BugreportParams(BugreportParams.BUGREPORT_MODE_FULL);
}
+
+ /* Allow/deny the consent dialog to sharing bugreport data or check existence only. */
+ private enum ConsentReply {
+ ALLOW,
+ DENY,
+ TIMEOUT
+ }
+
+ /*
+ * Ensure the consent dialog is shown and take action according to <code>consentReply<code/>.
+ * It will fail if the dialog is not shown when <code>ignoreNotFound<code/> is false.
+ */
+ private void shareConsentDialog(@NonNull ConsentReply consentReply) throws Exception {
+ mTemporaryVmPolicy.permitIncorrectContextUse();
+ final UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ // Unlock before finding/clicking an object.
+ device.wakeUp();
+ device.executeShellCommand("wm dismiss-keyguard");
+
+ final BySelector consentTitleObj = By.res("android", "alertTitle");
+ if (!device.wait(Until.hasObject(consentTitleObj), UIAUTOMATOR_TIMEOUT_MS)) {
+ fail("The consent dialog is not found");
+ }
+ if (consentReply.equals(ConsentReply.TIMEOUT)) {
+ return;
+ }
+ final BySelector selector;
+ if (consentReply.equals(ConsentReply.ALLOW)) {
+ selector = By.res("android", "button1");
+ Log.d(TAG, "Allow the consent dialog");
+ } else { // ConsentReply.DENY
+ selector = By.res("android", "button2");
+ Log.d(TAG, "Deny the consent dialog");
+ }
+ final UiObject2 btnObj = device.findObject(selector);
+ assertNotNull("The button of consent dialog is not found", btnObj);
+ btnObj.click();
+
+ Log.d(TAG, "Wait for the dialog to be dismissed");
+ assertTrue(device.wait(Until.gone(consentTitleObj), UIAUTOMATOR_TIMEOUT_MS));
+ }
+
+ /**
+ * A rule to change strict mode vm policy temporarily till test method finished.
+ *
+ * To permit the non-visual context usage in tests while taking bugreports need user consent,
+ * or UiAutomator/BugreportManager.DumpstateListener would run into error.
+ * UiDevice#findObject creates UiObject2, its Gesture object and ViewConfiguration and
+ * UiObject2#click need to know bounds. Both of them access to WindowManager internally without
+ * visual context comes from InstrumentationRegistry and violate the policy.
+ * Also <code>DumpstateListener<code/> violate the policy when onScreenshotTaken is called.
+ *
+ * TODO(b/161201609) Remove this class once violations fixed.
+ */
+ static class ExtendedStrictModeVmPolicy extends ExternalResource {
+ private boolean mWasVmPolicyChanged = false;
+ private StrictMode.VmPolicy mOldVmPolicy;
+
+ @Override
+ protected void after() {
+ restoreVmPolicyIfNeeded();
+ }
+
+ public void permitIncorrectContextUse() {
+ // Allow to call multiple times without losing old policy.
+ if (mOldVmPolicy == null) {
+ mOldVmPolicy = StrictMode.getVmPolicy();
+ }
+ StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
+ .detectAll()
+ .permitIncorrectContextUse()
+ .penaltyLog()
+ .build());
+ mWasVmPolicyChanged = true;
+ }
+
+ private void restoreVmPolicyIfNeeded() {
+ if (mWasVmPolicyChanged && mOldVmPolicy != null) {
+ StrictMode.setVmPolicy(mOldVmPolicy);
+ mOldVmPolicy = null;
+ }
+ }
+ }
}
diff --git a/core/tests/coretests/apks/install/res/values/strings.xml b/core/tests/coretests/apks/install/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install/res/values/strings.xml
+++ b/core/tests/coretests/apks/install/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml b/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_bad_dex/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_decl_perm/res/values/strings.xml b/core/tests/coretests/apks/install_decl_perm/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_decl_perm/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_decl_perm/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml b/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_loc_auto/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml b/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_loc_internal/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml b/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_loc_sdcard/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml b/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_loc_unspecified/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_use_perm_good/res/values/strings.xml b/core/tests/coretests/apks/install_use_perm_good/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_use_perm_good/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_use_perm_good/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml b/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_uses_feature/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml b/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml b/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml
+++ b/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/keyset/res/values/strings.xml b/core/tests/coretests/apks/keyset/res/values/strings.xml
index ff99ffa77b2a..d811ec29ef19 100644
--- a/core/tests/coretests/apks/keyset/res/values/strings.xml
+++ b/core/tests/coretests/apks/keyset/res/values/strings.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
<string name="keyset_perm_desc">keyset_perm_description</string>
<string name="keyset_perm_label">keyset_perm_label</string>
</resources>
diff --git a/core/tests/coretests/apks/version/res/values/strings.xml b/core/tests/coretests/apks/version/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/version/res/values/strings.xml
+++ b/core/tests/coretests/apks/version/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/apks/version_nosys/res/values/strings.xml b/core/tests/coretests/apks/version_nosys/res/values/strings.xml
index 3b8b3b1af9b5..984152fb5fa7 100644
--- a/core/tests/coretests/apks/version_nosys/res/values/strings.xml
+++ b/core/tests/coretests/apks/version_nosys/res/values/strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Just need this dummy file to have something to build. -->
+<!-- Just need this placeholder file to have something to build. -->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="dummy">dummy</string>
+ <string name="placeholder">placeholder</string>
</resources>
diff --git a/core/tests/coretests/src/android/os/VintfObjectTest.java b/core/tests/coretests/src/android/os/VintfObjectTest.java
index af3660a6dab9..ae6e79a040f7 100644
--- a/core/tests/coretests/src/android/os/VintfObjectTest.java
+++ b/core/tests/coretests/src/android/os/VintfObjectTest.java
@@ -20,7 +20,7 @@ import junit.framework.TestCase;
public class VintfObjectTest extends TestCase {
/**
- * Sanity check for {@link VintfObject#report VintfObject.report()}.
+ * Quick check for {@link VintfObject#report VintfObject.report()}.
*/
public void testReport() {
String[] xmls = VintfObject.report();
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 4cdfbb8ce27f..5711f98e3b75 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -415,6 +415,7 @@ key 583 ASSIST
key usage 0x0c0067 WINDOW
key usage 0x0c006F BRIGHTNESS_UP
key usage 0x0c0070 BRIGHTNESS_DOWN
+key usage 0x0c0173 MEDIA_AUDIO_TRACK
# Joystick and game controller axes.
# Axes that are not mapped will be assigned generic axis numbers by the input subsystem.
diff --git a/data/keyboards/Vendor_2dc8_Product_6101.kl b/data/keyboards/Vendor_2dc8_Product_6101.kl
new file mode 100644
index 000000000000..ec9f5581b006
--- /dev/null
+++ b/data/keyboards/Vendor_2dc8_Product_6101.kl
@@ -0,0 +1,55 @@
+# 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.
+
+#
+# 8BitDo - SN30 Pro gamepad in Android (D-Input) mode
+#
+
+# Mapping according to https://developer.android.com/training/game-controllers/controller-input.html
+
+# Button labeled as "A" but should really produce keycode "B"
+key 304 BUTTON_B
+# Button labeled as "B" but should really produce keycode "A"
+key 305 BUTTON_A
+# Button labeled as "X" but should really produce keycode "Y"
+key 307 BUTTON_Y
+# Button labeled as "Y" but should really produce keycode "X"
+key 308 BUTTON_X
+
+key 310 BUTTON_L1
+key 312 BUTTON_L2
+key 311 BUTTON_R1
+key 313 BUTTON_R2
+
+# Button "Start" does not emit event when gamepad is in Android mode
+# Button "Home"
+key 306 BUTTON_MODE
+key 314 BUTTON_SELECT
+key 315 BUTTON_START
+
+key 317 BUTTON_THUMBL
+key 318 BUTTON_THUMBR
+
+# Left Analog Stick
+axis 0x00 X
+axis 0x01 Y
+
+# Right Analog Stick
+axis 0x02 Z
+axis 0x05 RZ
+
+# Dpad
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 1da434496297..b3103fd516dd 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
@@ -157,7 +158,7 @@ public class HardwareRenderer {
protected RenderNode mRootNode;
private boolean mOpaque = true;
private boolean mForceDark = false;
- private boolean mIsWideGamut = false;
+ private @ActivityInfo.ColorMode int mColorMode = ActivityInfo.COLOR_MODE_DEFAULT;
/**
* Creates a new instance of a HardwareRenderer. The HardwareRenderer will default
@@ -167,7 +168,7 @@ public class HardwareRenderer {
ProcessInitializer.sInstance.initDisplayInfo();
mRootNode = RenderNode.adopt(nCreateRootRenderNode());
mRootNode.setClipToBounds(false);
- mNativeProxy = nCreateProxy(!mOpaque, mIsWideGamut, mRootNode.mNativeRenderNode);
+ mNativeProxy = nCreateProxy(!mOpaque, mRootNode.mNativeRenderNode);
if (mNativeProxy == 0) {
throw new OutOfMemoryError("Unable to create hardware renderer");
}
@@ -619,17 +620,17 @@ public class HardwareRenderer {
}
/**
- * Enable/disable wide gamut rendering on this renderer. Whether or not the actual rendering
- * will be wide gamut depends on the hardware support for such rendering.
+ * Sets the desired color mode on this renderer. Whether or not the actual rendering
+ * will use the requested colorMode depends on the hardware support for such rendering.
*
- * @param wideGamut true if this renderer should render in wide gamut, false if it should
- * render in sRGB
- * TODO: Figure out color...
+ * @param colorMode The @{@link ActivityInfo.ColorMode} to request
* @hide
*/
- public void setWideGamut(boolean wideGamut) {
- mIsWideGamut = wideGamut;
- nSetWideGamut(mNativeProxy, wideGamut);
+ public void setColorMode(@ActivityInfo.ColorMode int colorMode) {
+ if (mColorMode != colorMode) {
+ mColorMode = colorMode;
+ nSetColorMode(mNativeProxy, colorMode);
+ }
}
/**
@@ -804,11 +805,6 @@ public class HardwareRenderer {
nSetPictureCaptureCallback(mNativeProxy, callback);
}
- /** @hide */
- public boolean isWideGamut() {
- return mIsWideGamut;
- }
-
/** called by native */
static void invokePictureCapturedCallback(long picturePtr, PictureCapturedCallback callback) {
Picture picture = new Picture(picturePtr);
@@ -1207,8 +1203,7 @@ public class HardwareRenderer {
private static native long nCreateRootRenderNode();
- private static native long nCreateProxy(boolean translucent, boolean isWideGamut,
- long rootRenderNode);
+ private static native long nCreateProxy(boolean translucent, long rootRenderNode);
private static native void nDeleteProxy(long nativeProxy);
@@ -1230,7 +1225,7 @@ public class HardwareRenderer {
private static native void nSetOpaque(long nativeProxy, boolean opaque);
- private static native void nSetWideGamut(long nativeProxy, boolean wideGamut);
+ private static native void nSetColorMode(long nativeProxy, int colorMode);
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
diff --git a/graphics/proto/Android.bp b/graphics/proto/Android.bp
index ddced597759f..ea79b731a365 100644
--- a/graphics/proto/Android.bp
+++ b/graphics/proto/Android.bp
@@ -1,10 +1,10 @@
java_library_static {
- name: "game-driver-protos",
+ name: "updatable-driver-protos",
host_supported: true,
proto: {
type: "lite",
},
- srcs: ["game_driver.proto"],
+ srcs: ["updatable_driver.proto"],
jarjar_rules: "jarjar-rules.txt",
- sdk_version: "28",
+ sdk_version: "30",
}
diff --git a/graphics/proto/game_driver.proto b/graphics/proto/updatable_driver.proto
index fd7ffccac24c..cbc9424854d1 100644
--- a/graphics/proto/game_driver.proto
+++ b/graphics/proto/updatable_driver.proto
@@ -16,16 +16,16 @@
syntax = "proto2";
-package android.gamedriver;
+package android.updatabledriver;
-option java_package = "android.gamedriver";
-option java_outer_classname = "GameDriverProto";
+option java_package = "android.updatabledriver";
+option java_outer_classname = "UpdatableDriverProto";
-message Blacklist {
+message Denylist {
optional int64 version_code = 1;
repeated string package_names = 2;
}
-message Blacklists {
- repeated Blacklist blacklists = 1;
+message Denylists {
+ repeated Denylist denylists = 1;
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java
index 92e575804bbe..ca3a5112bc55 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SettingsSidecarImpl.java
@@ -192,7 +192,7 @@ class SettingsSidecarImpl extends StubSidecar {
Rect featureRect = new Rect(left, top, right, bottom);
rotateRectToDisplayRotation(featureRect, displayId);
transformToWindowSpaceRect(featureRect, windowToken);
- if (!featureRect.isEmpty()) {
+ if (isNotZero(featureRect)) {
SidecarDisplayFeature feature = new SidecarDisplayFeature();
feature.setRect(featureRect);
feature.setType(type);
@@ -207,6 +207,10 @@ class SettingsSidecarImpl extends StubSidecar {
return features;
}
+ private static boolean isNotZero(Rect rect) {
+ return rect.height() > 0 || rect.width() > 0;
+ }
+
@Override
protected void onListenersChanged() {
if (mSettingsObserver == null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index 338ece5afbc2..aeda2d923490 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -68,12 +68,15 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>();
private final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>();
- public DisplayImeController(IWindowManager wmService, DisplayController displayController,
+ protected DisplayImeController(IWindowManager wmService, DisplayController displayController,
Handler mainHandler, TransactionPool transactionPool) {
mHandler = mainHandler;
mWmService = wmService;
mTransactionPool = transactionPool;
mDisplayController = displayController;
+ }
+
+ protected void startMonitorDisplays() {
mDisplayController.addDisplayWindowListener(this);
}
@@ -490,4 +493,29 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
return IInputMethodManager.Stub.asInterface(
ServiceManager.getService(Context.INPUT_METHOD_SERVICE));
}
+
+ /** Builds {@link DisplayImeController} instance. */
+ public static class Builder {
+ private IWindowManager mWmService;
+ private DisplayController mDisplayController;
+ private Handler mHandler;
+ private TransactionPool mTransactionPool;
+
+ public Builder(IWindowManager wmService, DisplayController displayController,
+ Handler handler, TransactionPool transactionPool) {
+ mWmService = wmService;
+ mDisplayController = displayController;
+ mHandler = handler;
+ mTransactionPool = transactionPool;
+ }
+
+ /** Builds and initializes {@link DisplayImeController} instance. */
+ public DisplayImeController build() {
+ DisplayImeController displayImeController = new DisplayImeController(mWmService,
+ mDisplayController, mHandler, mTransactionPool);
+ // Separates startMonitorDisplays from constructor to prevent circular init issue.
+ displayImeController.startMonitorDisplays();
+ return displayImeController;
+ }
+ }
}
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 3893041b05d9..8ab7da5257ab 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -101,7 +101,7 @@ cc_library {
},
},
sanitize: {
- blacklist: "libandroidfw_blacklist.txt",
+ blocklist: "libandroidfw_blocklist.txt",
},
}
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index e351a46d633a..e10a7f3f5c61 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1717,6 +1717,10 @@ struct ResTable_overlayable_policy_header
// The overlay must be signed with the same signature as the actor declared for the target
// resource
ACTOR_SIGNATURE = 0x00000080,
+
+ // The overlay must be signed with the same signature as the reference package declared
+ // in the SystemConfig
+ CONFIG_SIGNATURE = 0x00000100,
};
using PolicyBitmask = uint32_t;
diff --git a/libs/androidfw/libandroidfw_blacklist.txt b/libs/androidfw/libandroidfw_blocklist.txt
index dd17e4d5b1e8..dd17e4d5b1e8 100644
--- a/libs/androidfw/libandroidfw_blacklist.txt
+++ b/libs/androidfw/libandroidfw_blocklist.txt
diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp
index 72747e8fa543..33264d5d5c86 100644
--- a/libs/hwui/AutoBackendTextureRelease.cpp
+++ b/libs/hwui/AutoBackendTextureRelease.cpp
@@ -25,7 +25,8 @@ using namespace android::uirenderer::renderthread;
namespace android {
namespace uirenderer {
-AutoBackendTextureRelease::AutoBackendTextureRelease(GrContext* context, AHardwareBuffer* buffer) {
+AutoBackendTextureRelease::AutoBackendTextureRelease(GrDirectContext* context,
+ AHardwareBuffer* buffer) {
AHardwareBuffer_Desc desc;
AHardwareBuffer_describe(buffer, &desc);
bool createProtectedImage = 0 != (desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT);
@@ -67,8 +68,9 @@ static void releaseProc(SkImage::ReleaseContext releaseContext) {
textureRelease->unref(false);
}
-void AutoBackendTextureRelease::makeImage(AHardwareBuffer* buffer, android_dataspace dataspace,
- GrContext* context) {
+void AutoBackendTextureRelease::makeImage(AHardwareBuffer* buffer,
+ android_dataspace dataspace,
+ GrDirectContext* context) {
AHardwareBuffer_Desc desc;
AHardwareBuffer_describe(buffer, &desc);
SkColorType colorType = GrAHardwareBufferUtils::GetSkColorTypeFromBufferFormat(desc.format);
@@ -81,7 +83,7 @@ void AutoBackendTextureRelease::makeImage(AHardwareBuffer* buffer, android_datas
}
}
-void AutoBackendTextureRelease::newBufferContent(GrContext* context) {
+void AutoBackendTextureRelease::newBufferContent(GrDirectContext* context) {
if (mBackendTexture.isValid()) {
mUpdateProc(mImageCtx, context);
}
diff --git a/libs/hwui/AutoBackendTextureRelease.h b/libs/hwui/AutoBackendTextureRelease.h
index acdd63cb7921..06f51fcd1105 100644
--- a/libs/hwui/AutoBackendTextureRelease.h
+++ b/libs/hwui/AutoBackendTextureRelease.h
@@ -31,7 +31,8 @@ namespace uirenderer {
*/
class AutoBackendTextureRelease final {
public:
- AutoBackendTextureRelease(GrContext* context, AHardwareBuffer* buffer);
+ AutoBackendTextureRelease(GrDirectContext* context,
+ AHardwareBuffer* buffer);
const GrBackendTexture& getTexture() const { return mBackendTexture; }
@@ -42,9 +43,11 @@ public:
inline sk_sp<SkImage> getImage() const { return mImage; }
- void makeImage(AHardwareBuffer* buffer, android_dataspace dataspace, GrContext* context);
+ void makeImage(AHardwareBuffer* buffer,
+ android_dataspace dataspace,
+ GrDirectContext* context);
- void newBufferContent(GrContext* context);
+ void newBufferContent(GrDirectContext* context);
private:
// The only way to invoke dtor is with unref, when mUsageCount is 0.
diff --git a/libs/hwui/ColorMode.h b/libs/hwui/ColorMode.h
new file mode 100644
index 000000000000..6d387f9ef43d
--- /dev/null
+++ b/libs/hwui/ColorMode.h
@@ -0,0 +1,34 @@
+/*
+ * 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
+
+namespace android::uirenderer {
+
+// Must match the constants in ActivityInfo.java
+enum class ColorMode {
+ // SRGB means HWUI will produce buffer in SRGB color space.
+ Default = 0,
+ // WideColorGamut selects the most optimal colorspace & format for the device's display
+ // Most commonly DisplayP3 + RGBA_8888 currently.
+ WideColorGamut = 1,
+ // HDR Rec2020 + F16
+ Hdr = 2,
+ // HDR Rec2020 + 1010102
+ Hdr10 = 3,
+};
+
+} // namespace android::uirenderer
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 67d8c07e61de..6589dbd50cf7 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -189,7 +189,7 @@ void DeferredLayerUpdater::detachSurfaceTexture() {
sk_sp<SkImage> DeferredLayerUpdater::ImageSlot::createIfNeeded(AHardwareBuffer* buffer,
android_dataspace dataspace,
bool forceCreate,
- GrContext* context) {
+ GrDirectContext* context) {
if (!mTextureRelease || !mTextureRelease->getImage().get() || dataspace != mDataspace ||
forceCreate || mBuffer != buffer) {
if (buffer != mBuffer) {
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 05f3774d6951..6731e9c428d6 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -106,7 +106,7 @@ private:
~ImageSlot() { clear(); }
sk_sp<SkImage> createIfNeeded(AHardwareBuffer* buffer, android_dataspace dataspace,
- bool forceCreate, GrContext* context);
+ bool forceCreate, GrDirectContext* context);
private:
void clear();
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index c2d2ff874816..87244427a719 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -21,7 +21,7 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>
-#include <GrContext.h>
+#include <GrDirectContext.h>
#include <SkCanvas.h>
#include <SkImage.h>
#include <utils/GLUtils.h>
@@ -285,7 +285,7 @@ private:
return (image.get() != nullptr);
}
- sk_sp<GrContext> mGrContext;
+ sk_sp<GrDirectContext> mGrContext;
renderthread::VulkanManager mVulkanManager;
std::mutex mVkLock;
};
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 0dea354b7200..b71bb07dbc86 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -118,7 +118,7 @@ CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTran
}
int imgWidth = image->width();
int imgHeight = image->height();
- sk_sp<GrContext> grContext = sk_ref_sp(mRenderThread.getGrContext());
+ sk_sp<GrDirectContext> grContext = sk_ref_sp(mRenderThread.getGrContext());
if (bitmap->colorType() == kRGBA_F16_SkColorType &&
!grContext->colorTypeSupportedAsSurface(bitmap->colorType())) {
diff --git a/libs/hwui/apex/jni_runtime.cpp b/libs/hwui/apex/jni_runtime.cpp
index b933813550d4..12e2e8135278 100644
--- a/libs/hwui/apex/jni_runtime.cpp
+++ b/libs/hwui/apex/jni_runtime.cpp
@@ -16,14 +16,14 @@
#include "android/graphics/jni_runtime.h"
-#include <android/log.h>
-#include <nativehelper/JNIHelp.h>
-#include <sys/cdefs.h>
-
#include <EGL/egl.h>
#include <GraphicsJNI.h>
#include <Properties.h>
#include <SkGraphics.h>
+#include <android/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <sys/cdefs.h>
+#include <vulkan/vulkan.h>
#undef LOG_TAG
#define LOG_TAG "AndroidGraphicsJNI"
@@ -172,6 +172,11 @@ using android::uirenderer::RenderPipelineType;
void zygote_preload_graphics() {
if (Properties::peekRenderPipelineType() == RenderPipelineType::SkiaGL) {
+ // Preload GL driver if HWUI renders with GL backend.
eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ } else {
+ // Preload Vulkan driver if HWUI renders with Vulkan backend.
+ uint32_t apiVersion;
+ vkEnumerateInstanceVersion(&apiVersion);
}
-} \ No newline at end of file
+}
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 42743db3061c..7d6875f59d17 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -143,11 +143,10 @@ static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, job
}
static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
- jboolean translucent, jboolean isWideGamut, jlong rootRenderNodePtr) {
+ jboolean translucent, jlong rootRenderNodePtr) {
RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr);
ContextFactoryImpl factory(rootRenderNode);
RenderProxy* proxy = new RenderProxy(translucent, rootRenderNode, &factory);
- proxy->setWideGamut(isWideGamut);
return (jlong) proxy;
}
@@ -218,10 +217,10 @@ static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz,
proxy->setOpaque(opaque);
}
-static void android_view_ThreadedRenderer_setWideGamut(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jboolean wideGamut) {
+static void android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject clazz,
+ jlong proxyPtr, jint colorMode) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
- proxy->setWideGamut(wideGamut);
+ proxy->setColorMode(static_cast<ColorMode>(colorMode));
}
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
@@ -659,7 +658,7 @@ static const JNINativeMethod gMethods[] = {
(void*)android_view_ThreadedRenderer_setProcessStatsBuffer},
{"nGetRenderThreadTid", "(J)I", (void*)android_view_ThreadedRenderer_getRenderThreadTid},
{"nCreateRootRenderNode", "()J", (void*)android_view_ThreadedRenderer_createRootRenderNode},
- {"nCreateProxy", "(ZZJ)J", (void*)android_view_ThreadedRenderer_createProxy},
+ {"nCreateProxy", "(ZJ)J", (void*)android_view_ThreadedRenderer_createProxy},
{"nDeleteProxy", "(J)V", (void*)android_view_ThreadedRenderer_deleteProxy},
{"nLoadSystemProperties", "(J)Z",
(void*)android_view_ThreadedRenderer_loadSystemProperties},
@@ -671,7 +670,7 @@ static const JNINativeMethod gMethods[] = {
{"nSetLightAlpha", "(JFF)V", (void*)android_view_ThreadedRenderer_setLightAlpha},
{"nSetLightGeometry", "(JFFFF)V", (void*)android_view_ThreadedRenderer_setLightGeometry},
{"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque},
- {"nSetWideGamut", "(JZ)V", (void*)android_view_ThreadedRenderer_setWideGamut},
+ {"nSetColorMode", "(JI)V", (void*)android_view_ThreadedRenderer_setColorMode},
{"nSyncAndDrawFrame", "(J[JI)I", (void*)android_view_ThreadedRenderer_syncAndDrawFrame},
{"nDestroy", "(JJ)V", (void*)android_view_ThreadedRenderer_destroy},
{"nRegisterAnimatingRenderNode", "(JJ)V",
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index 14a297f785fc..dd0fc695c246 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -15,7 +15,7 @@
*/
#include "GLFunctorDrawable.h"
-#include <GrContext.h>
+#include <GrDirectContext.h>
#include <private/hwui/DrawGlInfo.h>
#include "FunctorDrawable.h"
#include "GrBackendSurface.h"
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index f839213e9007..f95f347cffaf 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -29,7 +29,7 @@ namespace skiapipeline {
void LayerDrawable::onDraw(SkCanvas* canvas) {
Layer* layer = mLayerUpdater->backingLayer();
if (layer) {
- DrawLayer(canvas->getGrContext(), canvas, layer, nullptr, nullptr, true);
+ DrawLayer(canvas->recordingContext(), canvas, layer, nullptr, nullptr, true);
}
}
@@ -67,8 +67,12 @@ static bool shouldFilterRect(const SkMatrix& matrix, const SkRect& srcRect, cons
isIntegerAligned(dstDevRect.y()));
}
-bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
- const SkRect* srcRect, const SkRect* dstRect,
+// TODO: Context arg probably doesn't belong here – do debug check at callsite instead.
+bool LayerDrawable::DrawLayer(GrRecordingContext* context,
+ SkCanvas* canvas,
+ Layer* layer,
+ const SkRect* srcRect,
+ const SkRect* dstRect,
bool useLayerTransform) {
if (context == nullptr) {
SkDEBUGF(("Attempting to draw LayerDrawable into an unsupported surface"));
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.h b/libs/hwui/pipeline/skia/LayerDrawable.h
index 7cd515ae9fcb..ffbb480023ac 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.h
+++ b/libs/hwui/pipeline/skia/LayerDrawable.h
@@ -32,8 +32,12 @@ class LayerDrawable : public SkDrawable {
public:
explicit LayerDrawable(DeferredLayerUpdater* layerUpdater) : mLayerUpdater(layerUpdater) {}
- static bool DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer, const SkRect* srcRect,
- const SkRect* dstRect, bool useLayerTransform);
+ static bool DrawLayer(GrRecordingContext* context,
+ SkCanvas* canvas,
+ Layer* layer,
+ const SkRect* srcRect,
+ const SkRect* dstRect,
+ bool useLayerTransform);
protected:
virtual SkRect onGetBounds() override {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 24a6228242a5..389fe7eed7c7 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -87,6 +87,8 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
// Note: The default preference of pixel format is RGBA_8888, when other
// pixel format is available, we should branch out and do more check.
fboInfo.fFormat = GL_RGBA8;
+ } else if (colorType == kRGBA_1010102_SkColorType) {
+ fboInfo.fFormat = GL_RGB10_A2;
} else {
LOG_ALWAYS_FATAL("Unsupported color type.");
}
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 89a1c713ef62..6dd36981e8aa 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -35,6 +35,7 @@
#include "VectorDrawable.h"
#include "thread/CommonPool.h"
#include "tools/SkSharingProc.h"
+#include "utils/Color.h"
#include "utils/String8.h"
#include "utils/TraceUtils.h"
@@ -587,14 +588,23 @@ void SkiaPipeline::dumpResourceCacheUsage() const {
void SkiaPipeline::setSurfaceColorProperties(ColorMode colorMode) {
mColorMode = colorMode;
- if (colorMode == ColorMode::SRGB) {
- mSurfaceColorType = SkColorType::kN32_SkColorType;
- mSurfaceColorSpace = SkColorSpace::MakeSRGB();
- } else if (colorMode == ColorMode::WideColorGamut) {
- mSurfaceColorType = DeviceInfo::get()->getWideColorType();
- mSurfaceColorSpace = DeviceInfo::get()->getWideColorSpace();
- } else {
- LOG_ALWAYS_FATAL("Unreachable: unsupported color mode.");
+ switch (colorMode) {
+ case ColorMode::Default:
+ mSurfaceColorType = SkColorType::kN32_SkColorType;
+ mSurfaceColorSpace = SkColorSpace::MakeSRGB();
+ break;
+ case ColorMode::WideColorGamut:
+ mSurfaceColorType = DeviceInfo::get()->getWideColorType();
+ mSurfaceColorSpace = DeviceInfo::get()->getWideColorSpace();
+ break;
+ case ColorMode::Hdr:
+ mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType;
+ mSurfaceColorSpace = SkColorSpace::MakeRGB(GetPQSkTransferFunction(), SkNamedGamut::kRec2020);
+ break;
+ case ColorMode::Hdr10:
+ mSurfaceColorType = SkColorType::kRGBA_1010102_SkColorType;
+ mSurfaceColorSpace = SkColorSpace::MakeRGB(GetPQSkTransferFunction(), SkNamedGamut::kRec2020);
+ break;
}
}
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index 8341164edc19..100bfb6b159a 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -50,7 +50,7 @@ public:
bool createOrUpdateLayer(RenderNode* node, const DamageAccumulator& damageAccumulator,
ErrorHandler* errorHandler) override;
- void setSurfaceColorProperties(renderthread::ColorMode colorMode) override;
+ void setSurfaceColorProperties(ColorMode colorMode) override;
SkColorType getSurfaceColorType() const override { return mSurfaceColorType; }
sk_sp<SkColorSpace> getSurfaceColorSpace() override { return mSurfaceColorSpace; }
@@ -76,7 +76,7 @@ protected:
renderthread::RenderThread& mRenderThread;
- renderthread::ColorMode mColorMode = renderthread::ColorMode::SRGB;
+ ColorMode mColorMode = ColorMode::Default;
SkColorType mSurfaceColorType;
sk_sp<SkColorSpace> mSurfaceColorSpace;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index a362bd220936..13d544c68e95 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -174,7 +174,10 @@ void CanvasContext::setSurface(ANativeWindow* window, bool enableTimeout) {
} else {
mNativeSurface = nullptr;
}
+ setupPipelineSurface();
+}
+void CanvasContext::setupPipelineSurface() {
bool hasSurface = mRenderPipeline->setSurface(
mNativeSurface ? mNativeSurface->getNativeWindow() : nullptr, mSwapBehavior);
@@ -184,7 +187,7 @@ void CanvasContext::setSurface(ANativeWindow* window, bool enableTimeout) {
mFrameNumber = -1;
- if (window != nullptr && hasSurface) {
+ if (mNativeSurface != nullptr && hasSurface) {
mHaveNewSurface = true;
mSwapHistory.clear();
// Enable frame stats after the surface has been bound to the appropriate graphics API.
@@ -239,9 +242,9 @@ void CanvasContext::setOpaque(bool opaque) {
mOpaque = opaque;
}
-void CanvasContext::setWideGamut(bool wideGamut) {
- ColorMode colorMode = wideGamut ? ColorMode::WideColorGamut : ColorMode::SRGB;
- mRenderPipeline->setSurfaceColorProperties(colorMode);
+void CanvasContext::setColorMode(ColorMode mode) {
+ mRenderPipeline->setSurfaceColorProperties(mode);
+ setupPipelineSurface();
}
bool CanvasContext::makeCurrent() {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 0306eeccc5d4..cba710f01063 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -30,6 +30,7 @@
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
#include "utils/RingBuffer.h"
+#include "ColorMode.h"
#include <SkBitmap.h>
#include <SkRect.h>
@@ -119,7 +120,7 @@ public:
void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
void setLightGeometry(const Vector3& lightCenter, float lightRadius);
void setOpaque(bool opaque);
- void setWideGamut(bool wideGamut);
+ void setColorMode(ColorMode mode);
bool makeCurrent();
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target);
void draw();
@@ -211,6 +212,7 @@ private:
bool isSwapChainStuffed();
bool surfaceRequiresRedraw();
void setPresentTime();
+ void setupPipelineSurface();
SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index c7013531c07f..2a8aa8c3e5b7 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -76,6 +76,7 @@ static struct {
bool glColorSpace = false;
bool scRGB = false;
bool displayP3 = false;
+ bool hdr = false;
bool contextPriority = false;
bool surfacelessContext = false;
bool nativeFenceSync = false;
@@ -86,7 +87,8 @@ static struct {
EglManager::EglManager()
: mEglDisplay(EGL_NO_DISPLAY)
, mEglConfig(nullptr)
- , mEglConfigWideGamut(nullptr)
+ , mEglConfigF16(nullptr)
+ , mEglConfig1010102(nullptr)
, mEglContext(EGL_NO_CONTEXT)
, mPBufferSurface(EGL_NO_SURFACE)
, mCurrentSurface(EGL_NO_SURFACE)
@@ -143,8 +145,7 @@ void EglManager::initialize() {
} else {
LOG_ALWAYS_FATAL("Unsupported wide color space.");
}
- mHasWideColorGamutSupport = EglExtensions.glColorSpace && hasWideColorSpaceExtension &&
- mEglConfigWideGamut != EGL_NO_CONFIG_KHR;
+ mHasWideColorGamutSupport = EglExtensions.glColorSpace && hasWideColorSpaceExtension;
}
EGLConfig EglManager::load8BitsConfig(EGLDisplay display, EglManager::SwapBehavior swapBehavior) {
@@ -177,6 +178,35 @@ EGLConfig EglManager::load8BitsConfig(EGLDisplay display, EglManager::SwapBehavi
return config;
}
+EGLConfig EglManager::load1010102Config(EGLDisplay display, SwapBehavior swapBehavior) {
+ EGLint eglSwapBehavior =
+ (swapBehavior == SwapBehavior::Preserved) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+ // If we reached this point, we have a valid swap behavior
+ EGLint attribs[] = {EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE,
+ 10,
+ EGL_GREEN_SIZE,
+ 10,
+ EGL_BLUE_SIZE,
+ 10,
+ EGL_ALPHA_SIZE,
+ 2,
+ EGL_DEPTH_SIZE,
+ 0,
+ EGL_STENCIL_SIZE,
+ STENCIL_BUFFER_SIZE,
+ EGL_SURFACE_TYPE,
+ EGL_WINDOW_BIT | eglSwapBehavior,
+ EGL_NONE};
+ EGLConfig config = EGL_NO_CONFIG_KHR;
+ EGLint numConfigs = 1;
+ if (!eglChooseConfig(display, attribs, &config, numConfigs, &numConfigs) || numConfigs != 1) {
+ return EGL_NO_CONFIG_KHR;
+ }
+ return config;
+}
+
EGLConfig EglManager::loadFP16Config(EGLDisplay display, SwapBehavior swapBehavior) {
EGLint eglSwapBehavior =
(swapBehavior == SwapBehavior::Preserved) ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
@@ -230,6 +260,7 @@ void EglManager::initExtensions() {
EglExtensions.pixelFormatFloat = extensions.has("EGL_EXT_pixel_format_float");
EglExtensions.scRGB = extensions.has("EGL_EXT_gl_colorspace_scrgb");
EglExtensions.displayP3 = extensions.has("EGL_EXT_gl_colorspace_display_p3_passthrough");
+ EglExtensions.hdr = extensions.has("EGL_EXT_gl_colorspace_bt2020_pq");
EglExtensions.contextPriority = extensions.has("EGL_IMG_context_priority");
EglExtensions.surfacelessContext = extensions.has("EGL_KHR_surfaceless_context");
EglExtensions.fenceSync = extensions.has("EGL_KHR_fence_sync");
@@ -260,18 +291,20 @@ void EglManager::loadConfigs() {
LOG_ALWAYS_FATAL("Failed to choose config, error = %s", eglErrorString());
}
}
- SkColorType wideColorType = DeviceInfo::get()->getWideColorType();
// When we reach this point, we have a valid swap behavior
- if (wideColorType == SkColorType::kRGBA_F16_SkColorType && EglExtensions.pixelFormatFloat) {
- mEglConfigWideGamut = loadFP16Config(mEglDisplay, mSwapBehavior);
- if (mEglConfigWideGamut == EGL_NO_CONFIG_KHR) {
+ if (EglExtensions.pixelFormatFloat) {
+ mEglConfigF16 = loadFP16Config(mEglDisplay, mSwapBehavior);
+ if (mEglConfigF16 == EGL_NO_CONFIG_KHR) {
ALOGE("Device claims wide gamut support, cannot find matching config, error = %s",
eglErrorString());
EglExtensions.pixelFormatFloat = false;
}
- } else if (wideColorType == SkColorType::kN32_SkColorType) {
- mEglConfigWideGamut = load8BitsConfig(mEglDisplay, mSwapBehavior);
+ }
+ mEglConfig1010102 = load1010102Config(mEglDisplay, mSwapBehavior);
+ if (mEglConfig1010102 == EGL_NO_CONFIG_KHR) {
+ ALOGW("Failed to initialize 101010-2 format, error = %s",
+ eglErrorString());
}
}
@@ -311,8 +344,9 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
sk_sp<SkColorSpace> colorSpace) {
LOG_ALWAYS_FATAL_IF(!hasEglContext(), "Not initialized");
- bool wideColorGamut = colorMode == ColorMode::WideColorGamut && mHasWideColorGamutSupport &&
- EglExtensions.noConfigContext;
+ if (!mHasWideColorGamutSupport || !EglExtensions.noConfigContext) {
+ colorMode = ColorMode::Default;
+ }
// The color space we want to use depends on whether linear blending is turned
// on and whether the app has requested wide color gamut rendering. When wide
@@ -338,26 +372,47 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window,
// list is considered empty if the first entry is EGL_NONE
EGLint attribs[] = {EGL_NONE, EGL_NONE, EGL_NONE};
+ EGLConfig config = mEglConfig;
+ if (DeviceInfo::get()->getWideColorType() == kRGBA_F16_SkColorType) {
+ if (mEglConfigF16 == EGL_NO_CONFIG_KHR) {
+ colorMode = ColorMode::Default;
+ } else {
+ config = mEglConfigF16;
+ }
+ }
if (EglExtensions.glColorSpace) {
attribs[0] = EGL_GL_COLORSPACE_KHR;
- if (wideColorGamut) {
- skcms_Matrix3x3 colorGamut;
- LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&colorGamut),
- "Could not get gamut matrix from color space");
- if (memcmp(&colorGamut, &SkNamedGamut::kDisplayP3, sizeof(colorGamut)) == 0) {
- attribs[1] = EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT;
- } else if (memcmp(&colorGamut, &SkNamedGamut::kSRGB, sizeof(colorGamut)) == 0) {
- attribs[1] = EGL_GL_COLORSPACE_SCRGB_EXT;
- } else {
- LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
+ switch (colorMode) {
+ case ColorMode::Default:
+ attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
+ break;
+ case ColorMode::WideColorGamut: {
+ skcms_Matrix3x3 colorGamut;
+ LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&colorGamut),
+ "Could not get gamut matrix from color space");
+ if (memcmp(&colorGamut, &SkNamedGamut::kDisplayP3, sizeof(colorGamut)) == 0) {
+ attribs[1] = EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT;
+ } else if (memcmp(&colorGamut, &SkNamedGamut::kSRGB, sizeof(colorGamut)) == 0) {
+ attribs[1] = EGL_GL_COLORSPACE_SCRGB_EXT;
+ } else if (memcmp(&colorGamut, &SkNamedGamut::kRec2020, sizeof(colorGamut)) == 0) {
+ attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
+ } else {
+ LOG_ALWAYS_FATAL("Unreachable: unsupported wide color space.");
+ }
+ break;
}
- } else {
- attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
+ case ColorMode::Hdr:
+ config = mEglConfigF16;
+ attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
+ break;
+ case ColorMode::Hdr10:
+ config = mEglConfig1010102;
+ attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
+ break;
}
}
- EGLSurface surface = eglCreateWindowSurface(
- mEglDisplay, wideColorGamut ? mEglConfigWideGamut : mEglConfig, window, attribs);
+ EGLSurface surface = eglCreateWindowSurface(mEglDisplay, config, window, attribs);
if (surface == EGL_NO_SURFACE) {
return Error<EGLint>{eglGetError()};
}
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index f67fb31db951..69f3ed014c53 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -88,6 +88,7 @@ private:
static EGLConfig load8BitsConfig(EGLDisplay display, SwapBehavior swapBehavior);
static EGLConfig loadFP16Config(EGLDisplay display, SwapBehavior swapBehavior);
+ static EGLConfig load1010102Config(EGLDisplay display, SwapBehavior swapBehavior);
void initExtensions();
void createPBufferSurface();
@@ -97,7 +98,8 @@ private:
EGLDisplay mEglDisplay;
EGLConfig mEglConfig;
- EGLConfig mEglConfigWideGamut;
+ EGLConfig mEglConfigF16;
+ EGLConfig mEglConfig1010102;
EGLContext mEglContext;
EGLSurface mPBufferSurface;
EGLSurface mCurrentSurface;
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index c3c22869a42f..a04738d6a6f0 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -22,6 +22,7 @@
#include "Lighting.h"
#include "SwapBehavior.h"
#include "hwui/Bitmap.h"
+#include "ColorMode.h"
#include <SkRect.h>
#include <utils/RefBase.h>
@@ -42,16 +43,6 @@ namespace renderthread {
enum class MakeCurrentResult { AlreadyCurrent, Failed, Succeeded };
-enum class ColorMode {
- // SRGB means HWUI will produce buffer in SRGB color space.
- SRGB,
- // WideColorGamut means HWUI would support rendering scRGB non-linear into
- // a signed buffer with enough range to support the wide color gamut of the
- // display.
- WideColorGamut,
- // Hdr
-};
-
class Frame;
class IRenderPipeline {
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index b764f74bf116..aad0cca80cdc 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -109,8 +109,8 @@ void RenderProxy::setOpaque(bool opaque) {
mRenderThread.queue().post([=]() { mContext->setOpaque(opaque); });
}
-void RenderProxy::setWideGamut(bool wideGamut) {
- mRenderThread.queue().post([=]() { mContext->setWideGamut(wideGamut); });
+void RenderProxy::setColorMode(ColorMode mode) {
+ mRenderThread.queue().post([=]() { mContext->setColorMode(mode); });
}
int64_t* RenderProxy::frameInfo() {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 16eabadc064c..33dabc9895b1 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -24,6 +24,7 @@
#include "../FrameMetricsObserver.h"
#include "../IContextFactory.h"
+#include "ColorMode.h"
#include "DrawFrameTask.h"
#include "SwapBehavior.h"
#include "hwui/Bitmap.h"
@@ -77,7 +78,7 @@ public:
void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
void setLightGeometry(const Vector3& lightCenter, float lightRadius);
void setOpaque(bool opaque);
- void setWideGamut(bool wideGamut);
+ void setColorMode(ColorMode mode);
int64_t* frameInfo();
int syncAndDrawFrame();
void destroy();
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 206b58f62ea7..565fb61c8994 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -190,7 +190,7 @@ void RenderThread::requireGlContext() {
auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
auto size = glesVersion ? strlen(glesVersion) : -1;
cacheManager().configureContext(&options, glesVersion, size);
- sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
+ sk_sp<GrDirectContext> grContext(GrDirectContext::MakeGL(std::move(glInterface), options));
LOG_ALWAYS_FATAL_IF(!grContext.get());
setGrContext(grContext);
}
@@ -204,7 +204,7 @@ void RenderThread::requireVkContext() {
initGrContextOptions(options);
auto vkDriverVersion = mVkManager->getDriverVersion();
cacheManager().configureContext(&options, &vkDriverVersion, sizeof(vkDriverVersion));
- sk_sp<GrContext> grContext = mVkManager->createContext(options);
+ sk_sp<GrDirectContext> grContext = mVkManager->createContext(options);
LOG_ALWAYS_FATAL_IF(!grContext.get());
setGrContext(grContext);
}
@@ -263,7 +263,7 @@ Readback& RenderThread::readback() {
return *mReadback;
}
-void RenderThread::setGrContext(sk_sp<GrContext> context) {
+void RenderThread::setGrContext(sk_sp<GrDirectContext> context) {
mCacheManager->reset(context);
if (mGrContext) {
mRenderState->onContextDestroyed();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 2c295bcd8105..b8ce55650516 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -17,7 +17,7 @@
#ifndef RENDERTHREAD_H_
#define RENDERTHREAD_H_
-#include <GrContext.h>
+#include <GrDirectContext.h>
#include <SkBitmap.h>
#include <apex/choreographer.h>
#include <cutils/compiler.h>
@@ -106,8 +106,8 @@ public:
ProfileDataContainer& globalProfileData() { return mGlobalProfileData; }
Readback& readback();
- GrContext* getGrContext() const { return mGrContext.get(); }
- void setGrContext(sk_sp<GrContext> cxt);
+ GrDirectContext* getGrContext() const { return mGrContext.get(); }
+ void setGrContext(sk_sp<GrDirectContext> cxt);
CacheManager& cacheManager() { return *mCacheManager; }
VulkanManager& vulkanManager() { return *mVkManager; }
@@ -186,7 +186,7 @@ private:
ProfileDataContainer mGlobalProfileData;
Readback* mReadback = nullptr;
- sk_sp<GrContext> mGrContext;
+ sk_sp<GrDirectContext> mGrContext;
CacheManager* mCacheManager;
VulkanManager* mVkManager;
};
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 3cb16074dd5e..249936eb485e 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -20,7 +20,7 @@
#include <EGL/eglext.h>
#include <GrBackendSemaphore.h>
#include <GrBackendSurface.h>
-#include <GrContext.h>
+#include <GrDirectContext.h>
#include <GrTypes.h>
#include <android/sync.h>
#include <ui/FatVector.h>
@@ -369,7 +369,7 @@ void VulkanManager::initialize() {
}
}
-sk_sp<GrContext> VulkanManager::createContext(const GrContextOptions& options) {
+sk_sp<GrDirectContext> VulkanManager::createContext(const GrContextOptions& options) {
auto getProc = [](const char* proc_name, VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return vkGetDeviceProcAddr(device, proc_name);
@@ -388,7 +388,7 @@ sk_sp<GrContext> VulkanManager::createContext(const GrContextOptions& options) {
backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
backendContext.fGetProc = std::move(getProc);
- return GrContext::MakeVulkan(backendContext, options);
+ return GrDirectContext::MakeVulkan(backendContext, options);
}
VkFunctorInitParams VulkanManager::getVkFunctorInitParams() const {
@@ -562,9 +562,11 @@ void VulkanManager::destroySurface(VulkanSurface* surface) {
delete surface;
}
-VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode,
+VulkanSurface* VulkanManager::createSurface(ANativeWindow* window,
+ ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
- SkColorType surfaceColorType, GrContext* grContext,
+ SkColorType surfaceColorType,
+ GrDirectContext* grContext,
uint32_t extraBuffers) {
LOG_ALWAYS_FATAL_IF(!hasVkContext(), "Not initialized");
if (!window) {
@@ -575,7 +577,7 @@ VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode col
*this, extraBuffers);
}
-status_t VulkanManager::fenceWait(int fence, GrContext* grContext) {
+status_t VulkanManager::fenceWait(int fence, GrDirectContext* grContext) {
if (!hasVkContext()) {
ALOGE("VulkanManager::fenceWait: VkDevice not initialized");
return INVALID_OPERATION;
@@ -623,7 +625,7 @@ status_t VulkanManager::fenceWait(int fence, GrContext* grContext) {
return OK;
}
-status_t VulkanManager::createReleaseFence(int* nativeFence, GrContext* grContext) {
+status_t VulkanManager::createReleaseFence(int* nativeFence, GrDirectContext* grContext) {
*nativeFence = -1;
if (!hasVkContext()) {
ALOGE("VulkanManager::createReleaseFence: VkDevice not initialized");
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 8b19f13fdfb9..3f2df8d75d89 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -57,9 +57,11 @@ public:
bool hasVkContext() { return mDevice != VK_NULL_HANDLE; }
// Create and destroy functions for wrapping an ANativeWindow in a VulkanSurface
- VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode,
+ VulkanSurface* createSurface(ANativeWindow* window,
+ ColorMode colorMode,
sk_sp<SkColorSpace> surfaceColorSpace,
- SkColorType surfaceColorType, GrContext* grContext,
+ SkColorType surfaceColorType,
+ GrDirectContext* grContext,
uint32_t extraBuffers);
void destroySurface(VulkanSurface* surface);
@@ -70,18 +72,18 @@ public:
void destroy();
// Inserts a wait on fence command into the Vulkan command buffer.
- status_t fenceWait(int fence, GrContext* grContext);
+ status_t fenceWait(int fence, GrDirectContext* grContext);
// Creates a fence that is signaled when all the pending Vulkan commands are finished on the
// GPU.
- status_t createReleaseFence(int* nativeFence, GrContext* grContext);
+ status_t createReleaseFence(int* nativeFence, GrDirectContext* grContext);
// Returned pointers are owned by VulkanManager.
// An instance of VkFunctorInitParams returned from getVkFunctorInitParams refers to
// the internal state of VulkanManager: VulkanManager must be alive to use the returned value.
VkFunctorInitParams getVkFunctorInitParams() const;
- sk_sp<GrContext> createContext(const GrContextOptions& options);
+ sk_sp<GrDirectContext> createContext(const GrContextOptions& options);
uint32_t getDriverVersion() const { return mDriverVersion; }
diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp
index a4d7b825520d..edd3e4e4f4d4 100644
--- a/libs/hwui/tests/unit/CacheManagerTests.cpp
+++ b/libs/hwui/tests/unit/CacheManagerTests.cpp
@@ -26,7 +26,7 @@ using namespace android;
using namespace android::uirenderer;
using namespace android::uirenderer::renderthread;
-static size_t getCacheUsage(GrContext* grContext) {
+static size_t getCacheUsage(GrDirectContext* grContext) {
size_t cacheUsage;
grContext->getResourceCacheUsage(nullptr, &cacheUsage);
return cacheUsage;
@@ -35,7 +35,7 @@ static size_t getCacheUsage(GrContext* grContext) {
RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) {
int32_t width = DeviceInfo::get()->getWidth();
int32_t height = DeviceInfo::get()->getHeight();
- GrContext* grContext = renderThread.getGrContext();
+ GrDirectContext* grContext = renderThread.getGrContext();
ASSERT_TRUE(grContext != nullptr);
// create pairs of offscreen render targets and images until we exceed the
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index ca1bf690cfd0..eff34a83af1b 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -344,5 +344,27 @@ SkColor LabToSRGB(const Lab& lab, SkAlpha alpha) {
static_cast<uint8_t>(rgb.b * 255));
}
+// Note that SkColorSpace doesn't have the notion of an unspecified SDR white
+// level.
+static constexpr float kDefaultSDRWhiteLevel = 150.f;
+
+skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level) {
+ if (sdr_white_level <= 0.f) {
+ sdr_white_level = kDefaultSDRWhiteLevel;
+ }
+ // The generic PQ transfer function produces normalized luminance values i.e.
+ // the range 0-1 represents 0-10000 nits for the reference display, but we
+ // want to map 1.0 to |sdr_white_level| nits so we need to scale accordingly.
+ const double w = 10000. / sdr_white_level;
+ // Distribute scaling factor W by scaling A and B with X ^ (1/F):
+ // ((A + Bx^C) / (D + Ex^C))^F * W = ((A + Bx^C) / (D + Ex^C) * W^(1/F))^F
+ // See https://crbug.com/1058580#c32 for discussion.
+ skcms_TransferFunction fn = SkNamedTransferFn::kPQ;
+ const double ws = pow(w, 1. / fn.f);
+ fn.a = ws * fn.a;
+ fn.b = ws * fn.b;
+ return fn;
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h
index 71ed68371a9a..1654072fd264 100644
--- a/libs/hwui/utils/Color.h
+++ b/libs/hwui/utils/Color.h
@@ -126,6 +126,7 @@ struct Lab {
Lab sRGBToLab(SkColor color);
SkColor LabToSRGB(const Lab& lab, SkAlpha alpha);
+skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level = 0.f);
} /* namespace uirenderer */
} /* namespace android */
diff --git a/location/java/android/location/GnssAntennaInfo.java b/location/java/android/location/GnssAntennaInfo.java
index b2f9a0f41b7e..23977f18f749 100644
--- a/location/java/android/location/GnssAntennaInfo.java
+++ b/location/java/android/location/GnssAntennaInfo.java
@@ -53,7 +53,7 @@ public final class GnssAntennaInfo implements Parcelable {
* Class containing information about the antenna phase center offset (PCO). PCO is defined with
* respect to the origin of the Android sensor coordinate system, e.g., center of primary screen
* for mobiles - see sensor or form factor documents for details. Uncertainties are reported
- * to 1-sigma.
+ * to 1-sigma.
*/
public static final class PhaseCenterOffset implements Parcelable {
private final double mOffsetXMm;
@@ -95,31 +95,55 @@ public final class GnssAntennaInfo implements Parcelable {
}
};
+ /**
+ * Returns the x-axis offset of the phase center from the origin of the Android sensor
+ * coordinate system, in millimeters.
+ */
@FloatRange()
public double getXOffsetMm() {
return mOffsetXMm;
}
+ /**
+ * Returns the 1-sigma uncertainty of the x-axis offset of the phase center from the origin
+ * of the Android sensor coordinate system, in millimeters.
+ */
@FloatRange()
public double getXOffsetUncertaintyMm() {
return mOffsetXUncertaintyMm;
}
+ /**
+ * Returns the y-axis offset of the phase center from the origin of the Android sensor
+ * coordinate system, in millimeters.
+ */
@FloatRange()
public double getYOffsetMm() {
return mOffsetYMm;
}
+ /**
+ * Returns the 1-sigma uncertainty of the y-axis offset of the phase center from the origin
+ * of the Android sensor coordinate system, in millimeters.
+ */
@FloatRange()
public double getYOffsetUncertaintyMm() {
return mOffsetYUncertaintyMm;
}
+ /**
+ * Returns the z-axis offset of the phase center from the origin of the Android sensor
+ * coordinate system, in millimeters.
+ */
@FloatRange()
public double getZOffsetMm() {
return mOffsetZMm;
}
+ /**
+ * Returns the 1-sigma uncertainty of the z-axis offset of the phase center from the origin
+ * of the Android sensor coordinate system, in millimeters.
+ */
@FloatRange()
public double getZOffsetUncertaintyMm() {
return mOffsetZUncertaintyMm;
@@ -165,7 +189,7 @@ public final class GnssAntennaInfo implements Parcelable {
* at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles,
* i.e., deltaPhi = 180 / (number of columns - 1).
*/
- public static final class SphericalCorrections implements Parcelable{
+ public static final class SphericalCorrections implements Parcelable {
private final double[][] mCorrections;
private final double[][] mCorrectionUncertainties;
private final double mDeltaTheta;
@@ -296,10 +320,10 @@ public final class GnssAntennaInfo implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mNumRows);
dest.writeInt(mNumColumns);
- for (double[] row: mCorrections) {
+ for (double[] row : mCorrections) {
dest.writeDoubleArray(row);
}
- for (double[] row: mCorrectionUncertainties) {
+ for (double[] row : mCorrectionUncertainties) {
dest.writeDoubleArray(row);
}
}
@@ -340,6 +364,7 @@ public final class GnssAntennaInfo implements Parcelable {
/**
* Set antenna carrier frequency (MHz).
+ *
* @param carrierFrequencyMHz antenna carrier frequency (MHz)
* @return Builder builder object
*/
@@ -351,6 +376,7 @@ public final class GnssAntennaInfo implements Parcelable {
/**
* Set antenna phase center offset.
+ *
* @param phaseCenterOffset phase center offset object
* @return Builder builder object
*/
@@ -362,6 +388,7 @@ public final class GnssAntennaInfo implements Parcelable {
/**
* Set phase center variation corrections.
+ *
* @param phaseCenterVariationCorrections phase center variation corrections object
* @return Builder builder object
*/
@@ -374,6 +401,7 @@ public final class GnssAntennaInfo implements Parcelable {
/**
* Set signal gain corrections.
+ *
* @param signalGainCorrections signal gain corrections object
* @return Builder builder object
*/
@@ -386,6 +414,7 @@ public final class GnssAntennaInfo implements Parcelable {
/**
* Build GnssAntennaInfo object.
+ *
* @return instance of GnssAntennaInfo
*/
@NonNull
@@ -400,47 +429,65 @@ public final class GnssAntennaInfo implements Parcelable {
return mCarrierFrequencyMHz;
}
+ /**
+ * Returns a {@link PhaseCenterOffset} object encapsulating the phase center offset and
+ * corresponding uncertainties in millimeters.
+ *
+ * @return {@link PhaseCenterOffset}
+ */
@NonNull
public PhaseCenterOffset getPhaseCenterOffset() {
return mPhaseCenterOffset;
}
+ /**
+ * Returns a {@link SphericalCorrections} object encapsulating the phase center variation
+ * corrections and corresponding uncertainties in millimeters.
+ *
+ * @return phase center variation corrections as {@link SphericalCorrections}
+ */
@Nullable
public SphericalCorrections getPhaseCenterVariationCorrections() {
return mPhaseCenterVariationCorrections;
}
+ /**
+ * Returns a {@link SphericalCorrections} object encapsulating the signal gain
+ * corrections and corresponding uncertainties in dBi.
+ *
+ * @return signal gain corrections as {@link SphericalCorrections}
+ */
@Nullable
public SphericalCorrections getSignalGainCorrections() {
return mSignalGainCorrections;
}
- public static final @android.annotation.NonNull
- Creator<GnssAntennaInfo> CREATOR = new Creator<GnssAntennaInfo>() {
- @Override
- public GnssAntennaInfo createFromParcel(Parcel in) {
- double carrierFrequencyMHz = in.readDouble();
-
- ClassLoader classLoader = getClass().getClassLoader();
- PhaseCenterOffset phaseCenterOffset =
- in.readParcelable(classLoader);
- SphericalCorrections phaseCenterVariationCorrections =
- in.readParcelable(classLoader);
- SphericalCorrections signalGainCorrections =
- in.readParcelable(classLoader);
-
- return new GnssAntennaInfo(
- carrierFrequencyMHz,
- phaseCenterOffset,
- phaseCenterVariationCorrections,
- signalGainCorrections);
- }
-
- @Override
- public GnssAntennaInfo[] newArray(int size) {
- return new GnssAntennaInfo[size];
- }
- };
+ public static final @android.annotation.NonNull Creator<GnssAntennaInfo> CREATOR =
+ new Creator<GnssAntennaInfo>() {
+ @Override
+ public GnssAntennaInfo createFromParcel(Parcel in) {
+ double carrierFrequencyMHz = in.readDouble();
+
+ ClassLoader classLoader = getClass().getClassLoader();
+ PhaseCenterOffset phaseCenterOffset =
+ in.readParcelable(classLoader);
+ SphericalCorrections phaseCenterVariationCorrections =
+ in.readParcelable(classLoader);
+ SphericalCorrections signalGainCorrections =
+ in.readParcelable(classLoader);
+
+ return new GnssAntennaInfo(
+ carrierFrequencyMHz,
+ phaseCenterOffset,
+ phaseCenterVariationCorrections,
+ signalGainCorrections);
+ }
+
+ @Override
+ public GnssAntennaInfo[] newArray(int size) {
+ return new GnssAntennaInfo[size];
+ }
+ };
@Override
public int describeContents() {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 3ac71b2cff1d..c6fb3ef8f694 100755
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -564,6 +564,7 @@ public class AudioManager {
* request is from a hardware key press. (e.g. {@link MediaController}).
* @hide
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public static final int FLAG_FROM_KEY = 1 << 12;
// The iterator of TreeMap#entrySet() returns the entries in ascending key order.
@@ -3801,7 +3802,7 @@ public class AudioManager {
final IAudioService service = getService();
try {
service.unregisterAudioPolicyAsync(policy.cb());
- policy.setRegistration(null);
+ policy.reset();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3823,7 +3824,7 @@ public class AudioManager {
try {
policy.invalidateCaptorsAndInjectors();
service.unregisterAudioPolicy(policy.cb());
- policy.setRegistration(null);
+ policy.reset();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -6200,6 +6201,24 @@ public class AudioManager {
}
}
+
+ /**
+ * Retrieves the Hardware A/V synchronization ID corresponding to the given audio session ID.
+ * For more details on Hardware A/V synchronization please refer to
+ * <a href="https://source.android.com/devices/tv/multimedia-tunneling/">
+ * media tunneling documentation</a>.
+ * @param sessionId the audio session ID for which the HW A/V sync ID is retrieved.
+ * @return the HW A/V sync ID for this audio session (an integer different from 0).
+ * @throws UnsupportedOperationException if HW A/V synchronization is not supported.
+ */
+ public int getAudioHwSyncForSession(int sessionId) {
+ int hwSyncId = AudioSystem.getAudioHwSyncForSession(sessionId);
+ if (hwSyncId == AudioSystem.AUDIO_HW_SYNC_INVALID) {
+ throw new UnsupportedOperationException("HW A/V synchronization is not supported.");
+ }
+ return hwSyncId;
+ }
+
//---------------------------------------------------------
// Inner classes
//--------------------
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 4d26b8d3f7af..c9cdbb0ed277 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -487,6 +487,11 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
}
}
+ /** @hide */
+ public AudioAttributes getAudioAttributes() {
+ return mAudioAttributes;
+ }
+
/**
* Builder class for {@link AudioRecord} objects.
* Use this class to configure and create an <code>AudioRecord</code> instance. By setting the
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 4a6724a09c1e..57e8e438d592 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -70,16 +70,17 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
+import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
/**
- * This is a class for reading and writing Exif tags in a JPEG file or a RAW image file.
+ * This is a class for reading and writing Exif tags in various image file formats.
* <p>
- * Supported formats are: JPEG, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW, RAF and HEIF.
+ * Supported for reading: JPEG, PNG, WebP, HEIF, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW, RAF.
* <p>
- * Attribute mutation is supported for JPEG image files.
+ * Supported for writing: JPEG, PNG, WebP.
* <p>
* Note: It is recommended to use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
* <a href="{@docRoot}reference/androidx/exifinterface/media/ExifInterface.html">ExifInterface
@@ -585,6 +586,15 @@ public class ExifInterface {
private static final int WEBP_FILE_SIZE_BYTE_LENGTH = 4;
private static final byte[] WEBP_CHUNK_TYPE_EXIF = new byte[]{(byte) 0x45, (byte) 0x58,
(byte) 0x49, (byte) 0x46};
+ private static final byte[] WEBP_VP8_SIGNATURE = new byte[]{(byte) 0x9d, (byte) 0x01,
+ (byte) 0x2a};
+ private static final byte WEBP_VP8L_SIGNATURE = (byte) 0x2f;
+ private static final byte[] WEBP_CHUNK_TYPE_VP8X = "VP8X".getBytes(Charset.defaultCharset());
+ private static final byte[] WEBP_CHUNK_TYPE_VP8L = "VP8L".getBytes(Charset.defaultCharset());
+ private static final byte[] WEBP_CHUNK_TYPE_VP8 = "VP8 ".getBytes(Charset.defaultCharset());
+ private static final byte[] WEBP_CHUNK_TYPE_ANIM = "ANIM".getBytes(Charset.defaultCharset());
+ private static final byte[] WEBP_CHUNK_TYPE_ANMF = "ANMF".getBytes(Charset.defaultCharset());
+ private static final int WEBP_CHUNK_TYPE_VP8X_DEFAULT_LENGTH = 10;
private static final int WEBP_CHUNK_TYPE_BYTE_LENGTH = 4;
private static final int WEBP_CHUNK_SIZE_BYTE_LENGTH = 4;
@@ -1609,7 +1619,7 @@ public class ExifInterface {
}
/**
- * Returns whether ExifInterface currently supports parsing data from the specified mime type
+ * Returns whether ExifInterface currently supports reading data from the specified mime type
* or not.
*
* @param mimeType the string value of mime type
@@ -1633,6 +1643,8 @@ public class ExifInterface {
case "image/x-fuji-raf":
case "image/heic":
case "image/heif":
+ case "image/png":
+ case "image/webp":
return true;
default:
return false;
@@ -2046,18 +2058,21 @@ public class ExifInterface {
* {@link #setAttribute(String,String)} to set all attributes to write and
* make a single call rather than multiple calls for each attribute.
* <p>
- * This method is only supported for JPEG and PNG files.
+ * This method is supported for JPEG, PNG and WebP files.
* <p class="note">
* Note: after calling this method, any attempts to obtain range information
* from {@link #getAttributeRange(String)} or {@link #getThumbnailRange()}
* will throw {@link IllegalStateException}, since the offsets may have
* changed in the newly written file.
+ * <p>
+ * For WebP format, the Exif data will be stored as an Extended File Format, and it may not be
+ * supported for older readers.
* </p>
*/
public void saveAttributes() throws IOException {
- if (!mIsSupportedFile || (mMimeType != IMAGE_TYPE_JPEG && mMimeType != IMAGE_TYPE_PNG)) {
- throw new IOException("ExifInterface only supports saving attributes on JPEG or PNG "
- + "formats.");
+ if (!isSupportedFormatForSavingAttributes()) {
+ throw new IOException("ExifInterface only supports saving attributes on JPEG, PNG, "
+ + "or WebP formats.");
}
if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) {
throw new IOException(
@@ -2081,16 +2096,15 @@ public class ExifInterface {
try {
// Move the original file to temporary file.
if (mFilename != null) {
- tempFile = new File(mFilename + ".tmp");
+ String parent = originalFile.getParent();
+ String name = originalFile.getName();
+ String tempPrefix = UUID.randomUUID().toString() + "_";
+ tempFile = new File(parent, tempPrefix + name);
if (!originalFile.renameTo(tempFile)) {
throw new IOException("Couldn't rename to " + tempFile.getAbsolutePath());
}
} else if (mSeekableFileDescriptor != null) {
- if (mMimeType == IMAGE_TYPE_JPEG) {
- tempFile = File.createTempFile("temp", "jpg");
- } else if (mMimeType == IMAGE_TYPE_PNG) {
- tempFile = File.createTempFile("temp", "png");
- }
+ tempFile = File.createTempFile("temp", "tmp");
Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET);
in = new FileInputStream(mSeekableFileDescriptor);
out = new FileOutputStream(tempFile);
@@ -2120,6 +2134,8 @@ public class ExifInterface {
saveJpegAttributes(bufferedIn, bufferedOut);
} else if (mMimeType == IMAGE_TYPE_PNG) {
savePngAttributes(bufferedIn, bufferedOut);
+ } else if (mMimeType == IMAGE_TYPE_WEBP) {
+ saveWebpAttributes(bufferedIn, bufferedOut);
}
}
} catch (Exception e) {
@@ -2601,7 +2617,6 @@ public class ExifInterface {
ByteOrderedDataInputStream signatureInputStream = null;
try {
signatureInputStream = new ByteOrderedDataInputStream(signatureCheckBytes);
- signatureInputStream.setByteOrder(ByteOrder.BIG_ENDIAN);
long chunkSize = signatureInputStream.readInt();
byte[] chunkType = new byte[4];
@@ -3392,6 +3407,9 @@ public class ExifInterface {
bytesRead += in.skipBytes(WEBP_SIGNATURE_2.length);
try {
while (true) {
+ // TODO: Check the first Chunk Type, and if it is VP8X, check if the chunks are
+ // ordered properly.
+
// Each chunk is made up of three parts:
// 1) Chunk FourCC: 4-byte concatenating four ASCII characters.
// 2) Chunk Size: 4-byte unsigned integer indicating the size of the chunk.
@@ -3417,6 +3435,9 @@ public class ExifInterface {
// Save offset values for handling thumbnail and attribute offsets.
mExifOffset = bytesRead;
readExifSegment(payload, IFD_TYPE_PRIMARY);
+
+ // Save offset values for handleThumbnailFromJfif() function
+ mExifOffset = bytesRead;
break;
} else {
// Add a single padding byte at end if chunk size is odd
@@ -3610,6 +3631,263 @@ public class ExifInterface {
copy(dataInputStream, dataOutputStream);
}
+ // A WebP file has a header and a series of chunks.
+ // The header is composed of:
+ // "RIFF" + File Size + "WEBP"
+ //
+ // The structure of the chunks can be divided largely into two categories:
+ // 1) Contains only image data,
+ // 2) Contains image data and extra data.
+ // In the first category, there is only one chunk: type "VP8" (compression with loss) or "VP8L"
+ // (lossless compression).
+ // In the second category, the first chunk will be of type "VP8X", which contains flags
+ // indicating which extra data exist in later chunks. The proceeding chunks must conform to
+ // the following order based on type (if they exist):
+ // Color Profile ("ICCP") + Animation Control Data ("ANIM") + Image Data ("VP8"/"VP8L")
+ // + Exif metadata ("EXIF") + XMP metadata ("XMP")
+ //
+ // And in order to have EXIF data, a WebP file must be of the second structure and thus follow
+ // the following rules:
+ // 1) "VP8X" chunk as the first chunk,
+ // 2) flag for EXIF inside "VP8X" chunk set to 1, and
+ // 3) contain the "EXIF" chunk in the correct order amongst other chunks.
+ //
+ // Based on these rules, this API will support three different cases depending on the contents
+ // of the original file:
+ // 1) "EXIF" chunk already exists
+ // -> replace it with the new "EXIF" chunk
+ // 2) "EXIF" chunk does not exist and the first chunk is "VP8" or "VP8L"
+ // -> add "VP8X" before the "VP8"/"VP8L" chunk (with EXIF flag set to 1), and add new
+ // "EXIF" chunk after the "VP8"/"VP8L" chunk.
+ // 3) "EXIF" chunk does not exist and the first chunk is "VP8X"
+ // -> set EXIF flag in "VP8X" chunk to 1, and add new "EXIF" chunk at the proper location.
+ //
+ // See https://developers.google.com/speed/webp/docs/riff_container for more details.
+ private void saveWebpAttributes(InputStream inputStream, OutputStream outputStream)
+ throws IOException {
+ if (DEBUG) {
+ Log.d(TAG, "saveWebpAttributes starting with (inputStream: " + inputStream
+ + ", outputStream: " + outputStream + ")");
+ }
+ ByteOrderedDataInputStream totalInputStream =
+ new ByteOrderedDataInputStream(inputStream, ByteOrder.LITTLE_ENDIAN);
+ ByteOrderedDataOutputStream totalOutputStream =
+ new ByteOrderedDataOutputStream(outputStream, ByteOrder.LITTLE_ENDIAN);
+
+ // WebP signature
+ copy(totalInputStream, totalOutputStream, WEBP_SIGNATURE_1.length);
+ // File length will be written after all the chunks have been written
+ totalInputStream.skipBytes(WEBP_FILE_SIZE_BYTE_LENGTH + WEBP_SIGNATURE_2.length);
+
+ // Create a separate byte array to calculate file length
+ ByteArrayOutputStream nonHeaderByteArrayOutputStream = null;
+ try {
+ nonHeaderByteArrayOutputStream = new ByteArrayOutputStream();
+ ByteOrderedDataOutputStream nonHeaderOutputStream =
+ new ByteOrderedDataOutputStream(nonHeaderByteArrayOutputStream,
+ ByteOrder.LITTLE_ENDIAN);
+
+ if (mExifOffset != 0) {
+ // EXIF chunk exists in the original file
+ // Tested by webp_with_exif.webp
+ int bytesRead = WEBP_SIGNATURE_1.length + WEBP_FILE_SIZE_BYTE_LENGTH
+ + WEBP_SIGNATURE_2.length;
+ copy(totalInputStream, nonHeaderOutputStream,
+ mExifOffset - bytesRead - WEBP_CHUNK_TYPE_BYTE_LENGTH
+ - WEBP_CHUNK_SIZE_BYTE_LENGTH);
+
+ // Skip input stream to the end of the EXIF chunk
+ totalInputStream.skipBytes(WEBP_CHUNK_TYPE_BYTE_LENGTH);
+ int exifChunkLength = totalInputStream.readInt();
+ totalInputStream.skipBytes(exifChunkLength);
+
+ // Write new EXIF chunk to output stream
+ int exifSize = writeExifSegment(nonHeaderOutputStream);
+ } else {
+ // EXIF chunk does not exist in the original file
+ byte[] firstChunkType = new byte[WEBP_CHUNK_TYPE_BYTE_LENGTH];
+ if (totalInputStream.read(firstChunkType) != firstChunkType.length) {
+ throw new IOException("Encountered invalid length while parsing WebP chunk "
+ + "type");
+ }
+
+ if (Arrays.equals(firstChunkType, WEBP_CHUNK_TYPE_VP8X)) {
+ // Original file already includes other extra data
+ int size = totalInputStream.readInt();
+ // WebP files have a single padding byte at the end if the chunk size is odd.
+ byte[] data = new byte[(size % 2) == 1 ? size + 1 : size];
+ totalInputStream.read(data);
+
+ // Set the EXIF flag to 1
+ data[0] = (byte) (data[0] | (1 << 3));
+
+ // Retrieve Animation flag--in order to check where EXIF data should start
+ boolean containsAnimation = ((data[0] >> 1) & 1) == 1;
+
+ // Write the original VP8X chunk
+ nonHeaderOutputStream.write(WEBP_CHUNK_TYPE_VP8X);
+ nonHeaderOutputStream.writeInt(size);
+ nonHeaderOutputStream.write(data);
+
+ // Animation control data is composed of 1 ANIM chunk and multiple ANMF
+ // chunks and since the image data (VP8/VP8L) chunks are included in the ANMF
+ // chunks, EXIF data should come after the last ANMF chunk.
+ // Also, because there is no value indicating the amount of ANMF chunks, we need
+ // to keep iterating through chunks until we either reach the end of the file or
+ // the XMP chunk (if it exists).
+ // Tested by webp_with_anim_without_exif.webp
+ if (containsAnimation) {
+ copyChunksUpToGivenChunkType(totalInputStream, nonHeaderOutputStream,
+ WEBP_CHUNK_TYPE_ANIM, null);
+
+ while (true) {
+ byte[] type = new byte[WEBP_CHUNK_TYPE_BYTE_LENGTH];
+ int read = inputStream.read(type);
+ if (!Arrays.equals(type, WEBP_CHUNK_TYPE_ANMF)) {
+ // Either we have reached EOF or the start of a non-ANMF chunk
+ writeExifSegment(nonHeaderOutputStream);
+ break;
+ }
+ copyWebPChunk(totalInputStream, nonHeaderOutputStream, type);
+ }
+ } else {
+ // Skip until we find the VP8 or VP8L chunk
+ copyChunksUpToGivenChunkType(totalInputStream, nonHeaderOutputStream,
+ WEBP_CHUNK_TYPE_VP8, WEBP_CHUNK_TYPE_VP8L);
+ writeExifSegment(nonHeaderOutputStream);
+ }
+ } else if (Arrays.equals(firstChunkType, WEBP_CHUNK_TYPE_VP8)
+ || Arrays.equals(firstChunkType, WEBP_CHUNK_TYPE_VP8L)) {
+ int size = totalInputStream.readInt();
+ int bytesToRead = size;
+ // WebP files have a single padding byte at the end if the chunk size is odd.
+ if (size % 2 == 1) {
+ bytesToRead += 1;
+ }
+
+ // Retrieve image width/height
+ int widthAndHeight = 0;
+ int width = 0;
+ int height = 0;
+ int alpha = 0;
+ // Save VP8 frame data for later
+ byte[] vp8Frame = new byte[3];
+
+ if (Arrays.equals(firstChunkType, WEBP_CHUNK_TYPE_VP8)) {
+ totalInputStream.read(vp8Frame);
+
+ // Check signature
+ byte[] vp8Signature = new byte[3];
+ if (totalInputStream.read(vp8Signature) != vp8Signature.length
+ || !Arrays.equals(WEBP_VP8_SIGNATURE, vp8Signature)) {
+ throw new IOException("Encountered error while checking VP8 "
+ + "signature");
+ }
+
+ // Retrieve image width/height
+ widthAndHeight = totalInputStream.readInt();
+ width = (widthAndHeight << 18) >> 18;
+ height = (widthAndHeight << 2) >> 18;
+ bytesToRead -= (vp8Frame.length + vp8Signature.length + 4);
+ } else if (Arrays.equals(firstChunkType, WEBP_CHUNK_TYPE_VP8L)) {
+ // Check signature
+ byte vp8lSignature = totalInputStream.readByte();
+ if (vp8lSignature != WEBP_VP8L_SIGNATURE) {
+ throw new IOException("Encountered error while checking VP8L "
+ + "signature");
+ }
+
+ // Retrieve image width/height
+ widthAndHeight = totalInputStream.readInt();
+ // VP8L stores width - 1 and height - 1 values. See "2 RIFF Header" of
+ // "WebP Lossless Bitstream Specification"
+ width = ((widthAndHeight << 18) >> 18) + 1;
+ height = ((widthAndHeight << 4) >> 18) + 1;
+ // Retrieve alpha bit
+ alpha = widthAndHeight & (1 << 3);
+ bytesToRead -= (1 /* VP8L signature */ + 4);
+ }
+
+ // Create VP8X with Exif flag set to 1
+ nonHeaderOutputStream.write(WEBP_CHUNK_TYPE_VP8X);
+ nonHeaderOutputStream.writeInt(WEBP_CHUNK_TYPE_VP8X_DEFAULT_LENGTH);
+ byte[] data = new byte[WEBP_CHUNK_TYPE_VP8X_DEFAULT_LENGTH];
+ // EXIF flag
+ data[0] = (byte) (data[0] | (1 << 3));
+ // ALPHA flag
+ data[0] = (byte) (data[0] | (alpha << 4));
+ // VP8X stores Width - 1 and Height - 1 values
+ width -= 1;
+ height -= 1;
+ data[4] = (byte) width;
+ data[5] = (byte) (width >> 8);
+ data[6] = (byte) (width >> 16);
+ data[7] = (byte) height;
+ data[8] = (byte) (height >> 8);
+ data[9] = (byte) (height >> 16);
+ nonHeaderOutputStream.write(data);
+
+ // Write VP8 or VP8L data
+ nonHeaderOutputStream.write(firstChunkType);
+ nonHeaderOutputStream.writeInt(size);
+ if (Arrays.equals(firstChunkType, WEBP_CHUNK_TYPE_VP8)) {
+ nonHeaderOutputStream.write(vp8Frame);
+ nonHeaderOutputStream.write(WEBP_VP8_SIGNATURE);
+ nonHeaderOutputStream.writeInt(widthAndHeight);
+ } else if (Arrays.equals(firstChunkType, WEBP_CHUNK_TYPE_VP8L)) {
+ nonHeaderOutputStream.write(WEBP_VP8L_SIGNATURE);
+ nonHeaderOutputStream.writeInt(widthAndHeight);
+ }
+ copy(totalInputStream, nonHeaderOutputStream, bytesToRead);
+
+ // Write EXIF chunk
+ writeExifSegment(nonHeaderOutputStream);
+ }
+ }
+
+ // Copy the rest of the file
+ copy(totalInputStream, nonHeaderOutputStream);
+
+ // Write file length + second signature
+ totalOutputStream.writeInt(nonHeaderByteArrayOutputStream.size()
+ + WEBP_SIGNATURE_2.length);
+ totalOutputStream.write(WEBP_SIGNATURE_2);
+ nonHeaderByteArrayOutputStream.writeTo(totalOutputStream);
+ } catch (Exception e) {
+ throw new IOException("Failed to save WebP file", e);
+ } finally {
+ closeQuietly(nonHeaderByteArrayOutputStream);
+ }
+ }
+
+ private void copyChunksUpToGivenChunkType(ByteOrderedDataInputStream inputStream,
+ ByteOrderedDataOutputStream outputStream, byte[] firstGivenType,
+ byte[] secondGivenType) throws IOException {
+ while (true) {
+ byte[] type = new byte[WEBP_CHUNK_TYPE_BYTE_LENGTH];
+ if (inputStream.read(type) != type.length) {
+ throw new IOException("Encountered invalid length while copying WebP chunks up to"
+ + "chunk type " + new String(firstGivenType, ASCII)
+ + ((secondGivenType == null) ? "" : " or " + new String(secondGivenType,
+ ASCII)));
+ }
+ copyWebPChunk(inputStream, outputStream, type);
+ if (Arrays.equals(type, firstGivenType)
+ || (secondGivenType != null && Arrays.equals(type, secondGivenType))) {
+ break;
+ }
+ }
+ }
+
+ private void copyWebPChunk(ByteOrderedDataInputStream inputStream,
+ ByteOrderedDataOutputStream outputStream, byte[] type) throws IOException {
+ int size = inputStream.readInt();
+ outputStream.write(type);
+ outputStream.writeInt(size);
+ // WebP files have a single padding byte at the end if the chunk size is odd.
+ copy(inputStream, outputStream, (size % 2) == 1 ? size + 1 : size);
+ }
+
// Reads the given EXIF byte area and save its tag data into attributes.
private void readExifSegment(byte[] exifBytes, int imageType) throws IOException {
ByteOrderedDataInputStream dataInputStream =
@@ -4360,14 +4638,22 @@ public class ExifInterface {
ifdOffsets[IFD_TYPE_INTEROPERABILITY], mExifByteOrder));
}
- if (mMimeType == IMAGE_TYPE_JPEG) {
- // Write JPEG specific data (APP1 size, APP1 identifier)
- dataOutputStream.writeUnsignedShort(totalSize);
- dataOutputStream.write(IDENTIFIER_EXIF_APP1);
- } else if (mMimeType == IMAGE_TYPE_PNG) {
- // Write PNG specific data (chunk size, chunk type)
- dataOutputStream.writeInt(totalSize);
- dataOutputStream.write(PNG_CHUNK_TYPE_EXIF);
+ switch (mMimeType) {
+ case IMAGE_TYPE_JPEG:
+ // Write JPEG specific data (APP1 size, APP1 identifier)
+ dataOutputStream.writeUnsignedShort(totalSize);
+ dataOutputStream.write(IDENTIFIER_EXIF_APP1);
+ break;
+ case IMAGE_TYPE_PNG:
+ // Write PNG specific data (chunk size, chunk type)
+ dataOutputStream.writeInt(totalSize);
+ dataOutputStream.write(PNG_CHUNK_TYPE_EXIF);
+ break;
+ case IMAGE_TYPE_WEBP:
+ // Write WebP specific data (chunk type, chunk size)
+ dataOutputStream.write(WEBP_CHUNK_TYPE_EXIF);
+ dataOutputStream.writeInt(totalSize);
+ break;
}
// Write TIFF Headers. See JEITA CP-3451C Section 4.5.2. Table 1.
@@ -4436,6 +4722,11 @@ public class ExifInterface {
dataOutputStream.write(getThumbnailBytes());
}
+ // For WebP files, add a single padding byte at end if chunk size is odd
+ if (mMimeType == IMAGE_TYPE_WEBP && totalSize % 2 == 1) {
+ dataOutputStream.writeByte(0);
+ }
+
// Reset the byte order to big endian in order to write remaining parts of the JPEG file.
dataOutputStream.setByteOrder(ByteOrder.BIG_ENDIAN);
@@ -4537,12 +4828,17 @@ public class ExifInterface {
private int mPosition;
public ByteOrderedDataInputStream(InputStream in) throws IOException {
+ this(in, ByteOrder.BIG_ENDIAN);
+ }
+
+ ByteOrderedDataInputStream(InputStream in, ByteOrder byteOrder) throws IOException {
mInputStream = in;
mDataInputStream = new DataInputStream(in);
mLength = mDataInputStream.available();
mPosition = 0;
// TODO (b/142218289): Need to handle case where input stream does not support mark
mDataInputStream.mark(mLength);
+ mByteOrder = byteOrder;
}
public ByteOrderedDataInputStream(byte[] bytes) throws IOException {
@@ -4867,4 +5163,12 @@ public class ExifInterface {
}
}
}
+
+ private boolean isSupportedFormatForSavingAttributes() {
+ if (mIsSupportedFile && (mMimeType == IMAGE_TYPE_JPEG || mMimeType == IMAGE_TYPE_PNG
+ || mMimeType == IMAGE_TYPE_WEBP)) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 87c3bb9ffabe..5dc6f755d066 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -198,7 +198,10 @@ public class ImageReader implements AutoCloseable {
* {@link HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE}, or combined</td>
* </tr>
* </table>
- * Using other combinations may result in {@link IllegalArgumentException}.
+ * Using other combinations may result in {@link IllegalArgumentException}. Additionally,
+ * specifying {@link HardwareBuffer#USAGE_CPU_WRITE_RARELY} or
+ * {@link HardwareBuffer#USAGE_CPU_WRITE_OFTEN} and writing to the ImageReader's buffers
+ * might break assumptions made by some producers, and should be used with caution.
* </p>
* <p>
* If the {@link ImageReader} is used as an output target for a {@link
@@ -255,6 +258,7 @@ public class ImageReader implements AutoCloseable {
mWidth = width;
mHeight = height;
mFormat = format;
+ mUsage = usage;
mMaxImages = maxImages;
if (width < 1 || height < 1) {
@@ -768,6 +772,7 @@ public class ImageReader implements AutoCloseable {
private final int mWidth;
private final int mHeight;
private final int mFormat;
+ private final long mUsage;
private final int mMaxImages;
private final int mNumPlanes;
private final Surface mSurface;
@@ -909,7 +914,8 @@ public class ImageReader implements AutoCloseable {
throwISEIfImageIsInvalid();
if (mPlanes == null) {
- mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mFormat);
+ mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mFormat,
+ ImageReader.this.mUsage);
}
// Shallow copy is fine.
return mPlanes.clone();
@@ -1038,7 +1044,7 @@ public class ImageReader implements AutoCloseable {
private AtomicBoolean mIsDetached = new AtomicBoolean(false);
private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes,
- int readerFormat);
+ int readerFormat, long readerUsage);
private synchronized native int nativeGetWidth();
private synchronized native int nativeGetHeight();
private synchronized native int nativeGetFormat(int readerFormat);
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index d3e9c7e91056..8a17465c53b3 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -553,6 +553,12 @@ public class AudioPolicy {
}
}
+ /** @hide */
+ public void reset() {
+ setRegistration(null);
+ mConfig.reset();
+ }
+
public void setRegistration(String regId) {
synchronized (mLock) {
mRegistrationId = regId;
@@ -566,6 +572,11 @@ public class AudioPolicy {
sendMsg(MSG_POLICY_STATUS_CHANGE);
}
+ /**@hide*/
+ public String getRegistration() {
+ return mRegistrationId;
+ }
+
private boolean policyReadyToUse() {
synchronized (mLock) {
if (mStatus != POLICY_STATUS_REGISTERED) {
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 91b9bb3f64c0..561a8847feed 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -162,7 +162,7 @@ public class AudioPolicyConfig implements Parcelable {
public String toLogFriendlyString () {
String textDump = new String("android.media.audiopolicy.AudioPolicyConfig:\n");
- textDump += mMixes.size() + " AudioMix: "+ mRegistrationId + "\n";
+ textDump += mMixes.size() + " AudioMix, reg:" + mRegistrationId + "\n";
for(AudioMix mix : mMixes) {
// write mix route flags
textDump += "* route flags=0x" + Integer.toHexString(mix.getRouteFlags()) + "\n";
@@ -220,6 +220,10 @@ public class AudioPolicyConfig implements Parcelable {
return textDump;
}
+ protected void reset() {
+ mMixCounter = 0;
+ }
+
protected void setRegistration(String regId) {
final boolean currentRegNull = (mRegistrationId == null) || mRegistrationId.isEmpty();
final boolean newRegNull = (regId == null) || regId.isEmpty();
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 0a02156ccf76..bd2a0eaa75c9 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -675,7 +675,8 @@ static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
}
-static void Image_getLockedImage(JNIEnv* env, jobject thiz, LockedImage *image) {
+static void Image_getLockedImage(JNIEnv* env, jobject thiz, LockedImage *image,
+ uint64_t ndkReaderUsage) {
ALOGV("%s", __FUNCTION__);
BufferItem* buffer = Image_getBufferItem(env, thiz);
if (buffer == NULL) {
@@ -684,8 +685,16 @@ static void Image_getLockedImage(JNIEnv* env, jobject thiz, LockedImage *image)
return;
}
- status_t res = lockImageFromBuffer(buffer,
- GRALLOC_USAGE_SW_READ_OFTEN, buffer->mFence->dup(), image);
+ uint32_t lockUsage;
+ if ((ndkReaderUsage & (AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY
+ | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN)) != 0) {
+ lockUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
+ } else {
+ lockUsage = GRALLOC_USAGE_SW_READ_OFTEN;
+ }
+
+ status_t res = lockImageFromBuffer(buffer, lockUsage, buffer->mFence->dup(), image);
+
if (res != OK) {
jniThrowExceptionFmt(env, "java/lang/RuntimeException",
"lock buffer failed for format 0x%x",
@@ -721,7 +730,7 @@ static bool Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,
}
static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,
- int numPlanes, int readerFormat)
+ int numPlanes, int readerFormat, uint64_t ndkReaderUsage)
{
ALOGV("%s: create SurfacePlane array with size %d", __FUNCTION__, numPlanes);
int rowStride = 0;
@@ -754,7 +763,7 @@ static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,
}
LockedImage lockedImg = LockedImage();
- Image_getLockedImage(env, thiz, &lockedImg);
+ Image_getLockedImage(env, thiz, &lockedImg, ndkReaderUsage);
if (env->ExceptionCheck()) {
return NULL;
}
@@ -839,7 +848,7 @@ static const JNINativeMethod gImageReaderMethods[] = {
};
static const JNINativeMethod gImageMethods[] = {
- {"nativeCreatePlanes", "(II)[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
+ {"nativeCreatePlanes", "(IIJ)[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
(void*)Image_createSurfacePlanes },
{"nativeGetWidth", "()I", (void*)Image_getWidth },
{"nativeGetHeight", "()I", (void*)Image_getHeight },
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 033a32f550b7..55aac09b0f65 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -590,7 +590,7 @@ android_media_MediaPlayer_getSyncParams(JNIEnv *env, jobject thiz)
ALOGV("getSyncSettings: %d %d %f %f",
scp.sync.mSource, scp.sync.mAudioAdjustMode, scp.sync.mTolerance, scp.frameRate);
- // sanity check params
+ // check params
if (scp.sync.mSource >= AVSYNC_SOURCE_MAX
|| scp.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
|| scp.sync.mTolerance < 0.f
diff --git a/media/jni/android_media_MediaSync.cpp b/media/jni/android_media_MediaSync.cpp
index f75200868a0d..d1ce30a3e827 100644
--- a/media/jni/android_media_MediaSync.cpp
+++ b/media/jni/android_media_MediaSync.cpp
@@ -451,7 +451,7 @@ static jobject android_media_MediaSync_getSyncParams(JNIEnv *env, jobject thiz)
ALOGV("getSyncParams: %d %d %f %f",
scs.sync.mSource, scs.sync.mAudioAdjustMode, scs.sync.mTolerance, scs.frameRate);
- // sanity check params
+ // check params
if (scs.sync.mSource >= AVSYNC_SOURCE_MAX
|| scs.sync.mAudioAdjustMode >= AVSYNC_AUDIO_ADJUST_MODE_MAX
|| scs.sync.mTolerance < 0.f
diff --git a/media/jni/audioeffect/Visualizer.cpp b/media/jni/audioeffect/Visualizer.cpp
index f4d65d0a397f..a74ae5307a36 100644
--- a/media/jni/audioeffect/Visualizer.cpp
+++ b/media/jni/audioeffect/Visualizer.cpp
@@ -34,21 +34,9 @@ namespace android {
// ---------------------------------------------------------------------------
-Visualizer::Visualizer (const String16& opPackageName,
- int32_t priority,
- effect_callback_t cbf,
- void* user,
- audio_session_t sessionId)
- : AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId),
- mCaptureRate(CAPTURE_RATE_DEF),
- mCaptureSize(CAPTURE_SIZE_DEF),
- mSampleRate(44100000),
- mScalingMode(VISUALIZER_SCALING_MODE_NORMALIZED),
- mMeasurementMode(MEASUREMENT_MODE_NONE),
- mCaptureCallBack(NULL),
- mCaptureCbkUser(NULL)
+Visualizer::Visualizer (const String16& opPackageName)
+ : AudioEffect(opPackageName)
{
- initCaptureSize();
}
Visualizer::~Visualizer()
@@ -58,6 +46,23 @@ Visualizer::~Visualizer()
setCaptureCallBack(NULL, NULL, 0, 0);
}
+status_t Visualizer::set(int32_t priority,
+ effect_callback_t cbf,
+ void* user,
+ audio_session_t sessionId,
+ audio_io_handle_t io,
+ const AudioDeviceTypeAddr& device,
+ bool probe)
+{
+ status_t status = AudioEffect::set(
+ SL_IID_VISUALIZATION, nullptr, priority, cbf, user, sessionId, io, device, probe);
+ if (status == NO_ERROR || status == ALREADY_EXISTS) {
+ initCaptureSize();
+ }
+ return status;
+}
+
+
void Visualizer::release()
{
ALOGV("Visualizer::release()");
diff --git a/media/jni/audioeffect/Visualizer.h b/media/jni/audioeffect/Visualizer.h
index d4672a95c6d8..8b6a62f25638 100644
--- a/media/jni/audioeffect/Visualizer.h
+++ b/media/jni/audioeffect/Visualizer.h
@@ -65,14 +65,22 @@ public:
/* Constructor.
* See AudioEffect constructor for details on parameters.
*/
- Visualizer(const String16& opPackageName,
- int32_t priority = 0,
- effect_callback_t cbf = NULL,
- void* user = NULL,
- audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX);
+ explicit Visualizer(const String16& opPackageName);
~Visualizer();
+ /**
+ * Initialize an uninitialized Visualizer.
+ * See AudioEffect 'set' function for details on parameters.
+ */
+ status_t set(int32_t priority = 0,
+ effect_callback_t cbf = NULL,
+ void* user = NULL,
+ audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
+ audio_io_handle_t io = AUDIO_IO_HANDLE_NONE,
+ const AudioDeviceTypeAddr& device = {},
+ bool probe = false);
+
// Declared 'final' because we call this in ~Visualizer().
status_t setEnabled(bool enabled) final;
@@ -163,15 +171,15 @@ private:
uint32_t initCaptureSize();
Mutex mCaptureLock;
- uint32_t mCaptureRate;
- uint32_t mCaptureSize;
- uint32_t mSampleRate;
- uint32_t mScalingMode;
- uint32_t mMeasurementMode;
- capture_cbk_t mCaptureCallBack;
- void *mCaptureCbkUser;
+ uint32_t mCaptureRate = CAPTURE_RATE_DEF;
+ uint32_t mCaptureSize = CAPTURE_SIZE_DEF;
+ uint32_t mSampleRate = 44100000;
+ uint32_t mScalingMode = VISUALIZER_SCALING_MODE_NORMALIZED;
+ uint32_t mMeasurementMode = MEASUREMENT_MODE_NONE;
+ capture_cbk_t mCaptureCallBack = nullptr;
+ void *mCaptureCbkUser = nullptr;
sp<CaptureThread> mCaptureThread;
- uint32_t mCaptureFlags;
+ uint32_t mCaptureFlags = 0;
};
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index dbe7b4b619c9..96961ac21a2d 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -337,22 +337,21 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
}
// create the native AudioEffect object
- lpAudioEffect = new AudioEffect(typeStr,
- String16(opPackageNameStr.c_str()),
- uuidStr,
- priority,
- effectCallback,
- &lpJniStorage->mCallbackData,
- (audio_session_t) sessionId,
- AUDIO_IO_HANDLE_NONE,
- device,
- probe);
+ lpAudioEffect = new AudioEffect(String16(opPackageNameStr.c_str()));
if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
goto setup_failure;
}
-
+ lpAudioEffect->set(typeStr,
+ uuidStr,
+ priority,
+ effectCallback,
+ &lpJniStorage->mCallbackData,
+ (audio_session_t) sessionId,
+ AUDIO_IO_HANDLE_NONE,
+ device,
+ probe);
lStatus = AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->initCheck());
if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) {
ALOGE("AudioEffect initCheck failed %d", lStatus);
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index f9a77f474c50..4c5970a30a05 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -382,15 +382,15 @@ android_media_visualizer_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
}
// create the native Visualizer object
- lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()),
- 0,
- android_media_visualizer_effect_callback,
- lpJniStorage,
- (audio_session_t) sessionId);
+ lpVisualizer = new Visualizer(String16(opPackageNameStr.c_str()));
if (lpVisualizer == 0) {
ALOGE("Error creating Visualizer");
goto setup_failure;
}
+ lpVisualizer->set(0,
+ android_media_visualizer_effect_callback,
+ lpJniStorage,
+ (audio_session_t) sessionId);
lStatus = translateError(lpVisualizer->initCheck());
if (lStatus != VISUALIZER_SUCCESS && lStatus != VISUALIZER_ERROR_ALREADY_EXISTS) {
diff --git a/media/mca/filterfw/java/android/filterfw/core/FilterFunction.java b/media/mca/filterfw/java/android/filterfw/core/FilterFunction.java
index ce81a18eeaa8..ab9ae8ab2ac8 100644
--- a/media/mca/filterfw/java/android/filterfw/core/FilterFunction.java
+++ b/media/mca/filterfw/java/android/filterfw/core/FilterFunction.java
@@ -43,7 +43,7 @@ public class FilterFunction {
public Frame execute(KeyValueMap inputMap) {
int filterOutCount = mFilter.getNumberOfOutputs();
- // Sanity checks
+ // Validation checks
if (filterOutCount > 1) {
throw new RuntimeException("Calling execute on filter " + mFilter + " with multiple "
+ "outputs! Use executeMulti() instead!");
diff --git a/media/mca/filterfw/jni/jni_native_program.cpp b/media/mca/filterfw/jni/jni_native_program.cpp
index 14246078225e..cd4f7187c250 100644
--- a/media/mca/filterfw/jni/jni_native_program.cpp
+++ b/media/mca/filterfw/jni/jni_native_program.cpp
@@ -134,7 +134,7 @@ jboolean Java_android_filterfw_core_NativeProgram_callNativeProcess(JNIEnv* env,
jobject output) {
NativeProgram* program = ConvertFromJava<NativeProgram>(env, thiz);
- // Sanity checks
+ // Validation checks
if (!program || !inputs) {
return JNI_FALSE;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
index 0ae640dd7910..e74bda8a6b35 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
@@ -16,16 +16,6 @@
package com.android.mediaframeworktest.helpers;
-import com.android.ex.camera2.blocking.BlockingCameraManager;
-import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
-import com.android.ex.camera2.blocking.BlockingSessionCallback;
-import com.android.ex.camera2.blocking.BlockingStateCallback;
-import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
-
-import junit.framework.Assert;
-
-import org.mockito.Mockito;
-
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
@@ -64,6 +54,16 @@ import android.view.WindowManager;
import androidx.test.InstrumentationRegistry;
+import com.android.ex.camera2.blocking.BlockingCameraManager;
+import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
+import com.android.ex.camera2.blocking.BlockingSessionCallback;
+import com.android.ex.camera2.blocking.BlockingStateCallback;
+import com.android.ex.camera2.exceptions.TimeoutRuntimeException;
+
+import junit.framework.Assert;
+
+import org.mockito.Mockito;
+
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
@@ -77,8 +77,8 @@ import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
-import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
@@ -225,7 +225,7 @@ public class CameraTestUtils extends Assert {
}
/**
- * Dummy listener that release the image immediately once it is available.
+ * Mock listener that release the image immediately once it is available.
*
* <p>
* It can be used for the case where we don't care the image data at all.
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/Preconditions.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/Preconditions.java
index 96b0424595e3..a77b2898c5e0 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/Preconditions.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/Preconditions.java
@@ -22,7 +22,7 @@ import java.util.Objects;
/**
* Helper set of methods to perform precondition checks before starting method execution.
*
- * <p>Typically used to sanity check arguments or the current object state.</p>
+ * <p>Typically used to check arguments or the current object state.</p>
*/
/**
* (non-Javadoc)
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
index b3f443b30a70..9a64b58a080d 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
@@ -16,7 +16,7 @@
package com.android.mediaframeworktest.helpers;
-import junit.framework.Assert;
+import static com.android.mediaframeworktest.helpers.AssertHelpers.assertArrayContainsAnyOf;
import android.graphics.ImageFormat;
import android.graphics.Rect;
@@ -31,6 +31,8 @@ import android.util.Range;
import android.util.Rational;
import android.util.Size;
+import junit.framework.Assert;
+
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
@@ -40,8 +42,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import static com.android.mediaframeworktest.helpers.AssertHelpers.assertArrayContainsAnyOf;
-
/**
* Helpers to get common static info out of the camera.
*
@@ -435,7 +435,7 @@ public class StaticMetadata {
}
/**
- * Get max AE regions and do sanity check.
+ * Get max AE regions and do validation check.
*
* @return AE max regions supported by the camera device
*/
@@ -448,7 +448,7 @@ public class StaticMetadata {
}
/**
- * Get max AWB regions and do sanity check.
+ * Get max AWB regions and do validation check.
*
* @return AWB max regions supported by the camera device
*/
@@ -461,7 +461,7 @@ public class StaticMetadata {
}
/**
- * Get max AF regions and do sanity check.
+ * Get max AF regions and do validation check.
*
* @return AF max regions supported by the camera device
*/
@@ -545,7 +545,7 @@ public class StaticMetadata {
}
/**
- * Get available thumbnail sizes and do the sanity check.
+ * Get available thumbnail sizes and do the validation check.
*
* @return The array of available thumbnail sizes
*/
@@ -573,7 +573,7 @@ public class StaticMetadata {
}
/**
- * Get available focal lengths and do the sanity check.
+ * Get available focal lengths and do the validation check.
*
* @return The array of available focal lengths
*/
@@ -594,7 +594,7 @@ public class StaticMetadata {
}
/**
- * Get available apertures and do the sanity check.
+ * Get available apertures and do the validation check.
*
* @return The non-null array of available apertures
*/
@@ -909,7 +909,7 @@ public class StaticMetadata {
}
/**
- * Get hyperfocalDistance and do the sanity check.
+ * Get hyperfocalDistance and do the validation check.
* <p>
* Note that, this tag is optional, will return -1 if this tag is not
* available.
@@ -1068,7 +1068,7 @@ public class StaticMetadata {
}
/**
- * get android.control.availableModes and do the sanity check.
+ * get android.control.availableModes and do the validation check.
*
* @return available control modes.
*/
@@ -1124,7 +1124,7 @@ public class StaticMetadata {
}
/**
- * Get aeAvailableModes and do the sanity check.
+ * Get aeAvailableModes and do the validation check.
*
* <p>Depending on the check level this class has, for WAR or COLLECT levels,
* If the aeMode list is invalid, return an empty mode array. The the caller doesn't
@@ -1196,7 +1196,7 @@ public class StaticMetadata {
}
/**
- * Get available AWB modes and do the sanity check.
+ * Get available AWB modes and do the validation check.
*
* @return array that contains available AWB modes, empty array if awbAvailableModes is
* unavailable.
@@ -1222,7 +1222,7 @@ public class StaticMetadata {
}
/**
- * Get available AF modes and do the sanity check.
+ * Get available AF modes and do the validation check.
*
* @return array that contains available AF modes, empty array if afAvailableModes is
* unavailable.
@@ -1580,7 +1580,7 @@ public class StaticMetadata {
}
/**
- * Get value of key android.control.aeCompensationStep and do the sanity check.
+ * Get value of key android.control.aeCompensationStep and do the validation check.
*
* @return default value if the value is null.
*/
@@ -1605,7 +1605,7 @@ public class StaticMetadata {
}
/**
- * Get value of key android.control.aeCompensationRange and do the sanity check.
+ * Get value of key android.control.aeCompensationRange and do the validation check.
*
* @return default value if the value is null or malformed.
*/
@@ -1635,7 +1635,7 @@ public class StaticMetadata {
}
/**
- * Get availableVideoStabilizationModes and do the sanity check.
+ * Get availableVideoStabilizationModes and do the validation check.
*
* @return available video stabilization modes, empty array if it is unavailable.
*/
@@ -1666,7 +1666,7 @@ public class StaticMetadata {
}
/**
- * Get availableOpticalStabilization and do the sanity check.
+ * Get availableOpticalStabilization and do the validation check.
*
* @return available optical stabilization modes, empty array if it is unavailable.
*/
@@ -1780,7 +1780,7 @@ public class StaticMetadata {
}
/**
- * Get max pipeline depth and do the sanity check.
+ * Get max pipeline depth and do the validation check.
*
* @return max pipeline depth, default value if it is not available.
*/
@@ -1846,7 +1846,7 @@ public class StaticMetadata {
/**
- * Get available capabilities and do the sanity check.
+ * Get available capabilities and do the validation check.
*
* @return reported available capabilities list, empty list if the value is unavailable.
*/
@@ -2070,7 +2070,7 @@ public class StaticMetadata {
}
/**
- * Get max number of output raw streams and do the basic sanity check.
+ * Get max number of output raw streams and do the basic validation check.
*
* @return reported max number of raw output stream
*/
@@ -2083,7 +2083,7 @@ public class StaticMetadata {
}
/**
- * Get max number of output processed streams and do the basic sanity check.
+ * Get max number of output processed streams and do the basic validation check.
*
* @return reported max number of processed output stream
*/
@@ -2096,7 +2096,7 @@ public class StaticMetadata {
}
/**
- * Get max number of output stalling processed streams and do the basic sanity check.
+ * Get max number of output stalling processed streams and do the basic validation check.
*
* @return reported max number of stalling processed output stream
*/
@@ -2109,7 +2109,7 @@ public class StaticMetadata {
}
/**
- * Get lens facing and do the sanity check
+ * Get lens facing and do the validation check
* @return lens facing, return default value (BACK) if value is unavailable.
*/
public int getLensFacingChecked() {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java
index 31b79677f9ff..47caf0a0bc9b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2CaptureRequestTest.java
@@ -309,7 +309,7 @@ public class Camera2CaptureRequestTest extends Camera2SurfaceViewTestCase {
private void changeExposure(CaptureRequest.Builder requestBuilder,
long expTime, int sensitivity) {
// Check if the max analog sensitivity is available and no larger than max sensitivity.
- // The max analog sensitivity is not actually used here. This is only an extra sanity check.
+ // The max analog sensitivity is not actually used here. This is only an extra check.
mStaticInfo.getMaxAnalogSensitivityChecked();
expTime = mStaticInfo.getExposureClampToRange(expTime);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
index 6a4db5791d5c..dc8da4868df3 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2RecordingTest.java
@@ -985,7 +985,7 @@ public class Camera2RecordingTest extends Camera2SurfaceViewTestCase {
}
/**
- * Validate video snapshot capture image object sanity and test.
+ * Validate video snapshot capture image object soundness and test.
*
* <p> Check for size, format and jpeg decoding</p>
*
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java
index f7373f7b68db..cbdcc36eea3a 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2StillCaptureTest.java
@@ -570,7 +570,7 @@ public class Camera2StillCaptureTest extends Camera2SurfaceViewTestCase {
}
/**
- * Validate JPEG capture image object sanity and test.
+ * Validate JPEG capture image object soundness and test.
* <p>
* In addition to image object sanity, this function also does the decoding
* test, which is slower.
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 66637ef93598..54618a5da3a3 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -24189,6 +24189,7 @@ package android.media {
method @NonNull public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
method @NonNull public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations();
method public int getAllowedCapturePolicy();
+ method public int getAudioHwSyncForSession(int);
method public android.media.AudioDeviceInfo[] getDevices(int);
method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException;
method public int getMode();
@@ -43605,6 +43606,7 @@ package android.system {
package android.telecom {
public final class Call {
+ method public void addConferenceParticipants(@NonNull java.util.List<android.net.Uri>);
method public void answer(int);
method public void conference(android.telecom.Call);
method public void deflect(android.net.Uri);
@@ -43713,6 +43715,7 @@ package android.telecom {
method public static boolean hasProperty(int, int);
method public boolean hasProperty(int);
method public static String propertiesToString(int);
+ field public static final int CAPABILITY_ADD_PARTICIPANT = 33554432; // 0x2000000
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 4194304; // 0x400000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
field public static final int CAPABILITY_CAN_PULL_CALL = 8388608; // 0x800000
@@ -43742,6 +43745,7 @@ package android.telecom {
field public static final int PROPERTY_GENERIC_CONFERENCE = 2; // 0x2
field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 128; // 0x80
field public static final int PROPERTY_HIGH_DEF_AUDIO = 16; // 0x10
+ field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 8192; // 0x2000
field public static final int PROPERTY_IS_EXTERNAL_CALL = 64; // 0x40
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800
field public static final int PROPERTY_RTT = 1024; // 0x400
@@ -43819,6 +43823,7 @@ package android.telecom {
public abstract class Conference extends android.telecom.Conferenceable {
ctor public Conference(android.telecom.PhoneAccountHandle);
method public final boolean addConnection(android.telecom.Connection);
+ method @NonNull public static android.telecom.Conference createFailedConference(@NonNull android.telecom.DisconnectCause, @NonNull android.telecom.PhoneAccountHandle);
method public final void destroy();
method public final android.telecom.CallAudioState getCallAudioState();
method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
@@ -43834,6 +43839,9 @@ package android.telecom {
method public final android.telecom.StatusHints getStatusHints();
method public android.telecom.Connection.VideoProvider getVideoProvider();
method public int getVideoState();
+ method public final boolean isRingbackRequested();
+ method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>);
+ method public void onAnswer(int);
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onConnectionAdded(android.telecom.Connection);
method public void onDisconnect();
@@ -43842,6 +43850,7 @@ package android.telecom {
method public void onMerge(android.telecom.Connection);
method public void onMerge();
method public void onPlayDtmfTone(char);
+ method public void onReject();
method public void onSeparate(android.telecom.Connection);
method public void onStopDtmfTone();
method public void onSwap();
@@ -43862,6 +43871,8 @@ package android.telecom {
method public final void setDisconnected(android.telecom.DisconnectCause);
method public final void setExtras(@Nullable android.os.Bundle);
method public final void setOnHold();
+ method public final void setRingbackRequested(boolean);
+ method public final void setRinging();
method public final void setStatusHints(android.telecom.StatusHints);
method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider);
method public final void setVideoState(android.telecom.Connection, int);
@@ -43898,6 +43909,7 @@ package android.telecom {
method public final boolean isRingbackRequested();
method public final void notifyConferenceMergeFailed();
method public void onAbort();
+ method public void onAddConferenceParticipants(@NonNull java.util.List<android.net.Uri>);
method public void onAnswer(int);
method public void onAnswer();
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
@@ -43977,6 +43989,7 @@ package android.telecom {
field public static final int AUDIO_CODEC_GSM_HR = 10; // 0xa
field public static final int AUDIO_CODEC_NONE = 0; // 0x0
field public static final int AUDIO_CODEC_QCELP13K = 3; // 0x3
+ field public static final int CAPABILITY_ADD_PARTICIPANT = 67108864; // 0x4000000
field public static final int CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO = 8388608; // 0x800000
field public static final int CAPABILITY_CAN_PAUSE_VIDEO = 1048576; // 0x100000
field public static final int CAPABILITY_CAN_PULL_CALL = 16777216; // 0x1000000
@@ -44020,6 +44033,7 @@ package android.telecom {
field public static final int PROPERTY_ASSISTED_DIALING = 512; // 0x200
field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
field public static final int PROPERTY_HIGH_DEF_AUDIO = 4; // 0x4
+ field public static final int PROPERTY_IS_ADHOC_CONFERENCE = 4096; // 0x1000
field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10
field public static final int PROPERTY_IS_RTT = 256; // 0x100
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1024; // 0x400
@@ -44115,9 +44129,13 @@ package android.telecom {
method public void onConference(android.telecom.Connection, android.telecom.Connection);
method public void onConnectionServiceFocusGained();
method public void onConnectionServiceFocusLost();
+ method @Nullable public android.telecom.Conference onCreateIncomingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
+ method public void onCreateIncomingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateIncomingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
+ method @Nullable public android.telecom.Conference onCreateOutgoingConference(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
+ method public void onCreateOutgoingConferenceFailed(@Nullable android.telecom.PhoneAccountHandle, @Nullable android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
method public android.telecom.Connection onCreateOutgoingHandoverConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
@@ -44428,6 +44446,7 @@ package android.telecom {
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ANSWER_PHONE_CALLS, android.Manifest.permission.MODIFY_PHONE_STATE}) public void acceptRingingCall(int);
method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
+ method public void addNewIncomingConference(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void cancelMissedCallsNotification();
method public android.content.Intent createManageBlockedNumbersIntent();
method @Deprecated @RequiresPermission(android.Manifest.permission.ANSWER_PHONE_CALLS) public boolean endCall();
@@ -44455,6 +44474,7 @@ package android.telecom {
method public void registerPhoneAccount(android.telecom.PhoneAccount);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void showInCallScreen(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void silenceRinger();
+ method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void startConference(@NonNull java.util.List<android.net.Uri>, @NonNull android.os.Bundle);
method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle);
field public static final String ACTION_CHANGE_DEFAULT_DIALER = "android.telecom.action.CHANGE_DEFAULT_DIALER";
field public static final String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
@@ -44994,6 +45014,8 @@ package android.telephony {
field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
field public static final String KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL = "support_3gpp_call_forwarding_while_roaming_bool";
+ field public static final String KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL = "support_add_conference_participants_bool";
+ field public static final String KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL = "support_adhoc_conference_calls_bool";
field public static final String KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL = "support_clir_network_default_bool";
field public static final String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
field public static final String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool";
@@ -45993,6 +46015,7 @@ package android.telephony {
method @Nullable public android.net.LinkProperties getLinkProperties();
method public int getNetworkType();
method public int getState();
+ method public int getTransportType();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseDataConnectionState> CREATOR;
}
@@ -46066,12 +46089,13 @@ package android.telephony {
public final class SmsManager {
method public String createAppSpecificSmsToken(android.app.PendingIntent);
method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
+ method @NonNull public android.telephony.SmsManager createForSubscriptionId(int);
method public java.util.ArrayList<java.lang.String> divideMessage(String);
method public void downloadMultimediaMessage(android.content.Context, String, android.net.Uri, android.os.Bundle, android.app.PendingIntent);
method @NonNull public android.os.Bundle getCarrierConfigValues();
- method public static android.telephony.SmsManager getDefault();
+ method @Deprecated public static android.telephony.SmsManager getDefault();
method public static int getDefaultSmsSubscriptionId();
- method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
+ method @Deprecated public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback);
method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress();
method public int getSubscriptionId();
diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt
index c1dbfb7a9be7..3c0b955119a6 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/non-updatable-api/module-lib-current.txt
@@ -31,12 +31,25 @@ package android.graphics {
}
+package android.media {
+
+ public class AudioManager {
+ field public static final int FLAG_FROM_KEY = 4096; // 0x1000
+ }
+
+}
+
package android.os {
public class Binder implements android.os.IBinder {
method public final void markVintfStability();
}
+ public interface Parcelable {
+ field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
+ field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
+ }
+
public class StatsServiceManager {
method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsCompanionServiceRegisterer();
method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsManagerServiceRegisterer();
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index 222e563d4f96..385ae278975c 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -9706,6 +9706,7 @@ package android.telephony {
method @Deprecated public int getDataConnectionApnTypeBitMask();
method @Deprecated public int getDataConnectionFailCause();
method @Deprecated public int getDataConnectionState();
+ method public int getId();
}
public final class PreciseDisconnectCause {
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
index c7af8c8778ce..d0776aef78b6 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/chunking/cdc/Hkdf.java
@@ -40,18 +40,18 @@ public final class Hkdf {
*
* <p>IMPORTANT: The use or edit of this method requires a security review.
*
- * @param masterKey Master key from which to derive sub-keys.
+ * @param mainKey Main key from which to derive sub-keys.
* @param salt A randomly generated 256-bit byte string.
* @param data Arbitrary information that is bound to the derived key (i.e., used in its
* creation).
- * @return Raw derived key bytes = HKDF-SHA256(masterKey, salt, data).
+ * @return Raw derived key bytes = HKDF-SHA256(mainKey, salt, data).
* @throws InvalidKeyException If the salt can not be used as a valid key.
*/
- static byte[] hkdf(byte[] masterKey, byte[] salt, byte[] data) throws InvalidKeyException {
- Objects.requireNonNull(masterKey, "HKDF requires master key to be set.");
+ static byte[] hkdf(byte[] mainKey, byte[] salt, byte[] data) throws InvalidKeyException {
+ Objects.requireNonNull(mainKey, "HKDF requires main key to be set.");
Objects.requireNonNull(salt, "HKDF requires a salt.");
Objects.requireNonNull(data, "No data provided to HKDF.");
- return hkdfSha256Expand(hkdfSha256Extract(masterKey, salt), data);
+ return hkdfSha256Expand(hkdfSha256Extract(mainKey, salt), data);
}
private Hkdf() {}
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index cf967c02bec5..039f2c039ded 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -24,12 +24,35 @@
<bool name="config_enableFullscreenUserSwitcher">true</bool>
- <!-- configure which system ui bars should be displayed -->
+ <!-- Configure which system bars should be displayed. -->
<bool name="config_enableTopNavigationBar">true</bool>
<bool name="config_enableLeftNavigationBar">false</bool>
<bool name="config_enableRightNavigationBar">false</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>
+
<!-- Disable normal notification rendering; we handle that ourselves -->
<bool name="config_renderNotifications">false</bool>
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 7b6dceb5fcd7..995a3ecde6c1 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -134,9 +134,13 @@ public abstract class CarSystemUIModule {
}
@Singleton
- @Binds
- abstract DisplayImeController bindDisplayImeController(
- DisplaySystemBarsController displaySystemBarsController);
+ @Provides
+ static DisplayImeController provideDisplayImeController(Context context,
+ IWindowManager wmService, DisplayController displayController,
+ @Main Handler mainHandler, TransactionPool transactionPool) {
+ return new DisplaySystemBarsController.Builder(context, wmService, displayController,
+ mainHandler, transactionPool).build();
+ }
@Binds
abstract HeadsUpManager bindHeadsUpManagerPhone(HeadsUpManagerPhone headsUpManagerPhone);
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
index 35b2080dddf9..9584850fde7c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
@@ -16,12 +16,8 @@
package com.android.systemui.car.navigationbar;
-import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
-import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
-import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.ITYPE_TOP_GESTURES;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
@@ -30,13 +26,11 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARE
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.PixelFormat;
import android.inputmethodservice.InputMethodService;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.Display;
-import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsetsController;
@@ -47,7 +41,6 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.RegisterStatusBarResult;
import com.android.internal.view.AppearanceRegion;
-import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarDeviceProvisionedListener;
@@ -76,7 +69,6 @@ import dagger.Lazy;
/** Navigation bars customized for the automotive use case. */
public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks {
-
private final Resources mResources;
private final CarNavigationBarController mCarNavigationBarController;
private final SysuiDarkIconDispatcher mStatusBarIconController;
@@ -93,6 +85,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
private final Lazy<StatusBarIconController> mIconControllerLazy;
private final int mDisplayId;
+ private final SystemBarConfigs mSystemBarConfigs;
private StatusBarSignalPolicy mSignalPolicy;
private ActivityManagerWrapper mActivityManagerWrapper;
@@ -141,7 +134,8 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
IStatusBarService barService,
Lazy<KeyguardStateController> keyguardStateControllerLazy,
Lazy<PhoneStatusBarPolicy> iconPolicyLazy,
- Lazy<StatusBarIconController> iconControllerLazy
+ Lazy<StatusBarIconController> iconControllerLazy,
+ SystemBarConfigs systemBarConfigs
) {
super(context);
mResources = resources;
@@ -158,6 +152,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
mKeyguardStateControllerLazy = keyguardStateControllerLazy;
mIconPolicyLazy = iconPolicyLazy;
mIconControllerLazy = iconControllerLazy;
+ mSystemBarConfigs = systemBarConfigs;
mDisplayId = context.getDisplayId();
}
@@ -344,103 +339,63 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
private void buildNavBarContent() {
mTopNavigationBarView = mCarNavigationBarController.getTopBar(isDeviceSetupForUser());
if (mTopNavigationBarView != null) {
+ mSystemBarConfigs.insetSystemBar(SystemBarConfigs.TOP, mTopNavigationBarView);
mTopNavigationBarWindow.addView(mTopNavigationBarView);
}
mBottomNavigationBarView = mCarNavigationBarController.getBottomBar(isDeviceSetupForUser());
if (mBottomNavigationBarView != null) {
+ mSystemBarConfigs.insetSystemBar(SystemBarConfigs.BOTTOM, mBottomNavigationBarView);
mBottomNavigationBarWindow.addView(mBottomNavigationBarView);
}
mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(isDeviceSetupForUser());
if (mLeftNavigationBarView != null) {
+ mSystemBarConfigs.insetSystemBar(SystemBarConfigs.LEFT, mLeftNavigationBarView);
mLeftNavigationBarWindow.addView(mLeftNavigationBarView);
}
mRightNavigationBarView = mCarNavigationBarController.getRightBar(isDeviceSetupForUser());
if (mRightNavigationBarView != null) {
+ mSystemBarConfigs.insetSystemBar(SystemBarConfigs.RIGHT, mRightNavigationBarView);
mRightNavigationBarWindow.addView(mRightNavigationBarView);
}
}
private void attachNavBarWindows() {
- if (mTopNavigationBarWindow != null) {
- int height = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- height,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- PixelFormat.TRANSLUCENT);
- lp.setTitle("TopCarNavigationBar");
- lp.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_TOP_GESTURES};
- lp.setFitInsetsTypes(0);
- lp.windowAnimations = 0;
- lp.gravity = Gravity.TOP;
- mWindowManager.addView(mTopNavigationBarWindow, lp);
- }
-
- if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) {
- mBottomNavBarVisible = true;
- int height = mResources.getDimensionPixelSize(
- com.android.internal.R.dimen.navigation_bar_height);
-
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- height,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- PixelFormat.TRANSLUCENT);
- lp.setTitle("BottomCarNavigationBar");
- lp.providesInsetsTypes = new int[]{ITYPE_NAVIGATION_BAR, ITYPE_BOTTOM_GESTURES};
- lp.windowAnimations = 0;
- lp.gravity = Gravity.BOTTOM;
- mWindowManager.addView(mBottomNavigationBarWindow, lp);
- }
-
- if (mLeftNavigationBarWindow != null) {
- int width = mResources.getDimensionPixelSize(
- R.dimen.car_left_navigation_bar_width);
- WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
- width, ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- PixelFormat.TRANSLUCENT);
- leftlp.setTitle("LeftCarNavigationBar");
- leftlp.providesInsetsTypes = new int[]{ITYPE_CLIMATE_BAR};
- leftlp.setFitInsetsTypes(0);
- leftlp.windowAnimations = 0;
- leftlp.gravity = Gravity.LEFT;
- mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
- }
+ mSystemBarConfigs.getSystemBarSidesByZOrder().forEach(this::attachNavBarBySide);
+ }
- if (mRightNavigationBarWindow != null) {
- int width = mResources.getDimensionPixelSize(
- R.dimen.car_right_navigation_bar_width);
- WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
- width, ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- PixelFormat.TRANSLUCENT);
- rightlp.setTitle("RightCarNavigationBar");
- rightlp.providesInsetsTypes = new int[]{ITYPE_EXTRA_NAVIGATION_BAR};
- rightlp.setFitInsetsTypes(0);
- rightlp.windowAnimations = 0;
- rightlp.gravity = Gravity.RIGHT;
- mWindowManager.addView(mRightNavigationBarWindow, rightlp);
+ private void attachNavBarBySide(int side) {
+ switch(side) {
+ case SystemBarConfigs.TOP:
+ if (mTopNavigationBarWindow != null) {
+ mWindowManager.addView(mTopNavigationBarWindow,
+ mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.TOP));
+ }
+ break;
+ case SystemBarConfigs.BOTTOM:
+ if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) {
+ mBottomNavBarVisible = true;
+
+ mWindowManager.addView(mBottomNavigationBarWindow,
+ mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.BOTTOM));
+ }
+ break;
+ case SystemBarConfigs.LEFT:
+ if (mLeftNavigationBarWindow != null) {
+ mWindowManager.addView(mLeftNavigationBarWindow,
+ mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.LEFT));
+ }
+ break;
+ case SystemBarConfigs.RIGHT:
+ if (mRightNavigationBarWindow != null) {
+ mWindowManager.addView(mRightNavigationBarWindow,
+ mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.RIGHT));
+ }
+ break;
+ default:
+ return;
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
index ca780ae645c9..fe26040c5eae 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
@@ -22,7 +22,6 @@ import android.view.ViewGroup;
import androidx.annotation.Nullable;
-import com.android.systemui.R;
import com.android.systemui.car.hvac.HvacController;
import javax.inject.Inject;
@@ -61,7 +60,8 @@ public class CarNavigationBarController {
NavigationBarViewFactory navigationBarViewFactory,
ButtonSelectionStateController buttonSelectionStateController,
Lazy<HvacController> hvacControllerLazy,
- ButtonRoleHolderController buttonRoleHolderController) {
+ ButtonRoleHolderController buttonRoleHolderController,
+ SystemBarConfigs systemBarConfigs) {
mContext = context;
mNavigationBarViewFactory = navigationBarViewFactory;
mButtonSelectionStateController = buttonSelectionStateController;
@@ -69,10 +69,10 @@ public class CarNavigationBarController {
mButtonRoleHolderController = buttonRoleHolderController;
// Read configuration.
- mShowTop = mContext.getResources().getBoolean(R.bool.config_enableTopNavigationBar);
- mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar);
- mShowLeft = mContext.getResources().getBoolean(R.bool.config_enableLeftNavigationBar);
- mShowRight = mContext.getResources().getBoolean(R.bool.config_enableRightNavigationBar);
+ mShowTop = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.TOP);
+ mShowBottom = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.BOTTOM);
+ mShowLeft = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.LEFT);
+ mShowRight = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.RIGHT);
}
/**
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java
index 0ced4021ce38..ab401bbf06bb 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java
@@ -16,14 +16,10 @@
package com.android.systemui.car.navigationbar;
-import static android.view.WindowInsets.Type.systemBars;
-
import android.content.Context;
-import android.graphics.Insets;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
-import android.view.WindowInsets;
import android.widget.LinearLayout;
import com.android.systemui.Dependency;
@@ -80,30 +76,6 @@ public class CarNavigationBarView extends LinearLayout {
setFocusable(false);
}
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
- applyMargins(windowInsets.getInsets(systemBars()));
- return windowInsets;
- }
-
- private void applyMargins(Insets insets) {
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- if (child.getLayoutParams() instanceof LayoutParams) {
- LayoutParams lp = (LayoutParams) child.getLayoutParams();
- if (lp.rightMargin != insets.right || lp.leftMargin != insets.left
- || lp.topMargin != insets.top || lp.bottomMargin != insets.bottom) {
- lp.rightMargin = insets.right;
- lp.leftMargin = insets.left;
- lp.topMargin = insets.top;
- lp.bottomMargin = insets.bottom;
- child.requestLayout();
- }
- }
- }
- }
-
// Used to forward touch events even if the touch was initiated from a child component
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java
new file mode 100644
index 000000000000..3527bf93682f
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java
@@ -0,0 +1,380 @@
+/*
+ * 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.car.navigationbar;
+
+import android.annotation.IntDef;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.InsetsState;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Main;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Reads configs for system bars for each side (TOP, BOTTOM, LEFT, and RIGHT) and returns the
+ * corresponding {@link android.view.WindowManager.LayoutParams} per the configuration.
+ */
+@Singleton
+public class SystemBarConfigs {
+
+ private static final String TAG = SystemBarConfigs.class.getSimpleName();
+ // The z-order from which system bars will start to appear on top of HUN's.
+ private static final int HUN_ZORDER = 10;
+
+ @IntDef(value = {TOP, BOTTOM, LEFT, RIGHT})
+ @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+ private @interface SystemBarSide {
+ }
+
+ public static final int TOP = 0;
+ public static final int BOTTOM = 1;
+ public static final int LEFT = 2;
+ public static final int RIGHT = 3;
+
+ /*
+ NOTE: The elements' order in the map below must be preserved as-is since the correct
+ corresponding values are obtained by the index.
+ */
+ private static final int[] BAR_TYPE_MAP = {
+ InsetsState.ITYPE_STATUS_BAR,
+ InsetsState.ITYPE_NAVIGATION_BAR,
+ InsetsState.ITYPE_CLIMATE_BAR,
+ InsetsState.ITYPE_EXTRA_NAVIGATION_BAR
+ };
+
+ private static final Map<@SystemBarSide Integer, Integer> BAR_GRAVITY_MAP = new ArrayMap<>();
+ private static final Map<@SystemBarSide Integer, String> BAR_TITLE_MAP = new ArrayMap<>();
+ private static final Map<@SystemBarSide Integer, Integer> BAR_GESTURE_MAP = new ArrayMap<>();
+
+ private final Resources mResources;
+ private final Map<@SystemBarSide Integer, SystemBarConfig> mSystemBarConfigMap =
+ new ArrayMap<>();
+ private final List<@SystemBarSide Integer> mSystemBarSidesByZOrder = new ArrayList<>();
+
+ private boolean mTopNavBarEnabled;
+ private boolean mBottomNavBarEnabled;
+ private boolean mLeftNavBarEnabled;
+ private boolean mRightNavBarEnabled;
+
+ @Inject
+ public SystemBarConfigs(@Main Resources resources) {
+ mResources = resources;
+
+ populateMaps();
+ readConfigs();
+ checkEnabledBarsHaveUniqueBarTypes();
+ setInsetPaddingsForOverlappingCorners();
+ sortSystemBarSidesByZOrder();
+ }
+
+ protected WindowManager.LayoutParams getLayoutParamsBySide(@SystemBarSide int side) {
+ return mSystemBarConfigMap.get(side) != null
+ ? mSystemBarConfigMap.get(side).getLayoutParams() : null;
+ }
+
+ protected boolean getEnabledStatusBySide(@SystemBarSide int side) {
+ switch (side) {
+ case TOP:
+ return mTopNavBarEnabled;
+ case BOTTOM:
+ return mBottomNavBarEnabled;
+ case LEFT:
+ return mLeftNavBarEnabled;
+ case RIGHT:
+ return mRightNavBarEnabled;
+ default:
+ return false;
+ }
+ }
+
+ protected void insetSystemBar(@SystemBarSide int side, CarNavigationBarView view) {
+ int[] paddings = mSystemBarConfigMap.get(side).getPaddings();
+ view.setPadding(paddings[2], paddings[0], paddings[3], paddings[1]);
+ }
+
+ protected List<Integer> getSystemBarSidesByZOrder() {
+ return mSystemBarSidesByZOrder;
+ }
+
+ @VisibleForTesting
+ protected static int getHunZOrder() {
+ return HUN_ZORDER;
+ }
+
+ private static void populateMaps() {
+ BAR_GRAVITY_MAP.put(TOP, Gravity.TOP);
+ BAR_GRAVITY_MAP.put(BOTTOM, Gravity.BOTTOM);
+ BAR_GRAVITY_MAP.put(LEFT, Gravity.LEFT);
+ BAR_GRAVITY_MAP.put(RIGHT, Gravity.RIGHT);
+
+ BAR_TITLE_MAP.put(TOP, "TopCarSystemBar");
+ BAR_TITLE_MAP.put(BOTTOM, "BottomCarSystemBar");
+ BAR_TITLE_MAP.put(LEFT, "LeftCarSystemBar");
+ BAR_TITLE_MAP.put(RIGHT, "RightCarSystemBar");
+
+ BAR_GESTURE_MAP.put(TOP, InsetsState.ITYPE_TOP_GESTURES);
+ BAR_GESTURE_MAP.put(BOTTOM, InsetsState.ITYPE_BOTTOM_GESTURES);
+ BAR_GESTURE_MAP.put(LEFT, InsetsState.ITYPE_LEFT_GESTURES);
+ BAR_GESTURE_MAP.put(RIGHT, InsetsState.ITYPE_RIGHT_GESTURES);
+ }
+
+ private void readConfigs() {
+ mTopNavBarEnabled = mResources.getBoolean(R.bool.config_enableTopNavigationBar);
+ mBottomNavBarEnabled = mResources.getBoolean(R.bool.config_enableBottomNavigationBar);
+ mLeftNavBarEnabled = mResources.getBoolean(R.bool.config_enableLeftNavigationBar);
+ mRightNavBarEnabled = mResources.getBoolean(R.bool.config_enableRightNavigationBar);
+
+ if (mTopNavBarEnabled) {
+ SystemBarConfig topBarConfig =
+ new SystemBarConfigBuilder()
+ .setSide(TOP)
+ .setGirth(mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height))
+ .setBarType(mResources.getInteger(R.integer.config_topSystemBarType))
+ .setZOrder(mResources.getInteger(R.integer.config_topSystemBarZOrder))
+ .build();
+ mSystemBarConfigMap.put(TOP, topBarConfig);
+ }
+
+ if (mBottomNavBarEnabled) {
+ SystemBarConfig bottomBarConfig =
+ new SystemBarConfigBuilder()
+ .setSide(BOTTOM)
+ .setGirth(mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height))
+ .setBarType(mResources.getInteger(R.integer.config_bottomSystemBarType))
+ .setZOrder(
+ mResources.getInteger(R.integer.config_bottomSystemBarZOrder))
+ .build();
+ mSystemBarConfigMap.put(BOTTOM, bottomBarConfig);
+ }
+
+ if (mLeftNavBarEnabled) {
+ SystemBarConfig leftBarConfig =
+ new SystemBarConfigBuilder()
+ .setSide(LEFT)
+ .setGirth(mResources.getDimensionPixelSize(
+ R.dimen.car_left_navigation_bar_width))
+ .setBarType(mResources.getInteger(R.integer.config_leftSystemBarType))
+ .setZOrder(mResources.getInteger(R.integer.config_leftSystemBarZOrder))
+ .build();
+ mSystemBarConfigMap.put(LEFT, leftBarConfig);
+ }
+
+ if (mRightNavBarEnabled) {
+ SystemBarConfig rightBarConfig =
+ new SystemBarConfigBuilder()
+ .setSide(RIGHT)
+ .setGirth(mResources.getDimensionPixelSize(
+ R.dimen.car_right_navigation_bar_width))
+ .setBarType(mResources.getInteger(R.integer.config_rightSystemBarType))
+ .setZOrder(mResources.getInteger(R.integer.config_rightSystemBarZOrder))
+ .build();
+ mSystemBarConfigMap.put(RIGHT, rightBarConfig);
+ }
+ }
+
+ private void checkEnabledBarsHaveUniqueBarTypes() throws RuntimeException {
+ Set<Integer> barTypesUsed = new ArraySet<>();
+ int enabledNavBarCount = mSystemBarConfigMap.size();
+
+ for (SystemBarConfig systemBarConfig : mSystemBarConfigMap.values()) {
+ barTypesUsed.add(systemBarConfig.getBarType());
+ }
+
+ // The number of bar types used cannot be fewer than that of enabled system bars.
+ if (barTypesUsed.size() < enabledNavBarCount) {
+ throw new RuntimeException("Each enabled system bar must have a unique bar type. Check "
+ + "the configuration in config.xml");
+ }
+ }
+
+ private void setInsetPaddingsForOverlappingCorners() {
+ setInsetPaddingForOverlappingCorner(TOP, LEFT);
+ setInsetPaddingForOverlappingCorner(TOP, RIGHT);
+ setInsetPaddingForOverlappingCorner(BOTTOM, LEFT);
+ setInsetPaddingForOverlappingCorner(BOTTOM, RIGHT);
+ }
+
+ private void setInsetPaddingForOverlappingCorner(@SystemBarSide int horizontalSide,
+ @SystemBarSide int verticalSide) {
+
+ if (isVerticalBar(horizontalSide) || isHorizontalBar(verticalSide)) {
+ Log.w(TAG, "configureBarPaddings: Returning immediately since the horizontal and "
+ + "vertical sides were not provided correctly.");
+ return;
+ }
+
+ SystemBarConfig horizontalBarConfig = mSystemBarConfigMap.get(horizontalSide);
+ SystemBarConfig verticalBarConfig = mSystemBarConfigMap.get(verticalSide);
+
+ if (verticalBarConfig != null && horizontalBarConfig != null) {
+ int horizontalBarZOrder = horizontalBarConfig.getZOrder();
+ int horizontalBarGirth = horizontalBarConfig.getGirth();
+ int verticalBarZOrder = verticalBarConfig.getZOrder();
+ int verticalBarGirth = verticalBarConfig.getGirth();
+
+ if (horizontalBarZOrder > verticalBarZOrder) {
+ verticalBarConfig.setPaddingBySide(horizontalSide, horizontalBarGirth);
+ } else if (horizontalBarZOrder < verticalBarZOrder) {
+ horizontalBarConfig.setPaddingBySide(verticalSide, verticalBarGirth);
+ } else {
+ throw new RuntimeException(
+ BAR_TITLE_MAP.get(horizontalSide) + " " + BAR_TITLE_MAP.get(verticalSide)
+ + " have the same Z-Order, and so their placing order cannot be "
+ + "determined. Determine which bar should be placed on top of the "
+ + "other bar and change the Z-order in config.xml accordingly."
+ );
+ }
+ }
+ }
+
+ private void sortSystemBarSidesByZOrder() {
+ List<SystemBarConfig> systemBarsByZOrder = new ArrayList<>(mSystemBarConfigMap.values());
+
+ systemBarsByZOrder.sort(new Comparator<SystemBarConfig>() {
+ @Override
+ public int compare(SystemBarConfig o1, SystemBarConfig o2) {
+ return o1.getZOrder() - o2.getZOrder();
+ }
+ });
+
+ systemBarsByZOrder.forEach(systemBarConfig -> {
+ mSystemBarSidesByZOrder.add(systemBarConfig.getSide());
+ });
+ }
+
+ private static boolean isHorizontalBar(@SystemBarSide int side) {
+ return side == TOP || side == BOTTOM;
+ }
+
+ private static boolean isVerticalBar(@SystemBarSide int side) {
+ return side == LEFT || side == RIGHT;
+ }
+
+ private static final class SystemBarConfig {
+ private final int mSide;
+ private final int mBarType;
+ private final int mGirth;
+ private final int mZOrder;
+
+ private int[] mPaddings = new int[]{0, 0, 0, 0};
+
+ private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder) {
+ mSide = side;
+ mBarType = barType;
+ mGirth = girth;
+ mZOrder = zOrder;
+ }
+
+ private int getSide() {
+ return mSide;
+ }
+
+ private int getBarType() {
+ return mBarType;
+ }
+
+ private int getGirth() {
+ return mGirth;
+ }
+
+ private int getZOrder() {
+ return mZOrder;
+ }
+
+ private int[] getPaddings() {
+ return mPaddings;
+ }
+
+ private WindowManager.LayoutParams getLayoutParams() {
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ isHorizontalBar(mSide) ? ViewGroup.LayoutParams.MATCH_PARENT : mGirth,
+ isHorizontalBar(mSide) ? mGirth : ViewGroup.LayoutParams.MATCH_PARENT,
+ mapZOrderToBarType(mZOrder),
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+ PixelFormat.TRANSLUCENT);
+ lp.setTitle(BAR_TITLE_MAP.get(mSide));
+ lp.providesInsetsTypes = new int[]{BAR_TYPE_MAP[mBarType], BAR_GESTURE_MAP.get(mSide)};
+ lp.setFitInsetsTypes(0);
+ lp.windowAnimations = 0;
+ lp.gravity = BAR_GRAVITY_MAP.get(mSide);
+ return lp;
+ }
+
+ private int mapZOrderToBarType(int zOrder) {
+ return zOrder >= HUN_ZORDER ? WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL
+ : WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
+ }
+
+ private void setPaddingBySide(@SystemBarSide int side, int padding) {
+ mPaddings[side] = padding;
+ }
+ }
+
+ private static final class SystemBarConfigBuilder {
+ private int mSide;
+ private int mBarType;
+ private int mGirth;
+ private int mZOrder;
+
+ private SystemBarConfigBuilder setSide(@SystemBarSide int side) {
+ mSide = side;
+ return this;
+ }
+
+ private SystemBarConfigBuilder setBarType(int type) {
+ mBarType = type;
+ return this;
+ }
+
+ private SystemBarConfigBuilder setGirth(int girth) {
+ mGirth = girth;
+ return this;
+ }
+
+ private SystemBarConfigBuilder setZOrder(int zOrder) {
+ mZOrder = zOrder;
+ return this;
+ }
+
+ private SystemBarConfig build() {
+ return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder);
+ }
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
index d0a2aebdb80a..5bd8797c5349 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserGridRecyclerView.java
@@ -33,6 +33,7 @@ import android.car.user.CarUserManager;
import android.car.user.UserCreationResult;
import android.car.user.UserSwitchResult;
import android.car.userlib.UserHelper;
+import android.car.util.concurrent.AsyncFuture;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -60,7 +61,6 @@ import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.UserIcons;
import com.android.systemui.R;
@@ -449,7 +449,7 @@ public class UserGridRecyclerView extends RecyclerView {
*/
@Nullable
public UserInfo createNewOrFindExistingGuest(Context context) {
- AndroidFuture<UserCreationResult> future = mCarUserManager.createGuest(mGuestName);
+ AsyncFuture<UserCreationResult> future = mCarUserManager.createGuest(mGuestName);
// CreateGuest will return null if a guest already exists.
UserInfo newGuest = getUserInfo(future);
if (newGuest != null) {
@@ -482,7 +482,7 @@ public class UserGridRecyclerView extends RecyclerView {
}
@Nullable
- private UserInfo getUserInfo(AndroidFuture<UserCreationResult> future) {
+ private UserInfo getUserInfo(AsyncFuture<UserCreationResult> future) {
UserCreationResult userCreationResult;
try {
userCreationResult = future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
@@ -504,7 +504,7 @@ public class UserGridRecyclerView extends RecyclerView {
}
private boolean switchUser(@UserIdInt int userId) {
- AndroidFuture<UserSwitchResult> userSwitchResultFuture =
+ AsyncFuture<UserSwitchResult> userSwitchResultFuture =
mCarUserManager.switchUser(userId);
UserSwitchResult userSwitchResult;
try {
@@ -531,7 +531,7 @@ public class UserGridRecyclerView extends RecyclerView {
@Override
protected UserInfo doInBackground(String... userNames) {
- AndroidFuture<UserCreationResult> future = mCarUserManager.createUser(userNames[0],
+ AsyncFuture<UserCreationResult> future = mCarUserManager.createUser(userNames[0],
/* flags= */ 0);
try {
UserInfo user = getUserInfo(future);
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java
index aea691443290..7db2823dc3b9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediator.java
@@ -16,12 +16,12 @@
package com.android.systemui.car.userswitcher;
-import android.app.ActivityManager;
import android.car.Car;
import android.car.user.CarUserManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.car.window.OverlayViewMediator;
@@ -36,13 +36,16 @@ public class UserSwitchTransitionViewMediator implements OverlayViewMediator,
private static final String TAG = "UserSwitchTransitionViewMediator";
private final CarServiceProvider mCarServiceProvider;
+ private final CarDeviceProvisionedController mCarDeviceProvisionedController;
private final UserSwitchTransitionViewController mUserSwitchTransitionViewController;
@Inject
public UserSwitchTransitionViewMediator(
CarServiceProvider carServiceProvider,
+ CarDeviceProvisionedController carDeviceProvisionedController,
UserSwitchTransitionViewController userSwitchTransitionViewController) {
mCarServiceProvider = carServiceProvider;
+ mCarDeviceProvisionedController = carDeviceProvisionedController;
mUserSwitchTransitionViewController = userSwitchTransitionViewController;
}
@@ -74,7 +77,7 @@ public class UserSwitchTransitionViewMediator implements OverlayViewMediator,
@VisibleForTesting
void handleUserLifecycleEvent(CarUserManager.UserLifecycleEvent event) {
if (event.getEventType() == CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING
- && ActivityManager.getCurrentUser() == event.getUserId()) {
+ && mCarDeviceProvisionedController.getCurrentUser() == event.getUserId()) {
mUserSwitchTransitionViewController.handleShow(event.getUserId());
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
index 5c80202ba592..e493c97a9b46 100644
--- a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
@@ -36,25 +36,20 @@ import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.TransactionPool;
-import javax.inject.Inject;
-import javax.inject.Singleton;
-
/**
* Controller that maps between displays and {@link IDisplayWindowInsetsController} in order to
* give system bar control to SystemUI.
* {@link R.bool#config_remoteInsetsControllerControlsSystemBars} determines whether this controller
* takes control or not.
*/
-@Singleton
public class DisplaySystemBarsController extends DisplayImeController {
private static final String TAG = "DisplaySystemBarsController";
- private SparseArray<PerDisplay> mPerDisplaySparseArray;
private final Context mContext;
+ private SparseArray<PerDisplay> mPerDisplaySparseArray;
- @Inject
- public DisplaySystemBarsController(
+ private DisplaySystemBarsController(
Context context,
IWindowManager wmService,
DisplayController displayController,
@@ -172,4 +167,33 @@ public class DisplaySystemBarsController extends DisplayImeController {
}
}
}
+
+ /** Builds {@link DisplaySystemBarsController} instance. */
+ public static class Builder {
+ private Context mContext;
+ private IWindowManager mWmService;
+ private DisplayController mDisplayController;
+ private Handler mHandler;
+ private TransactionPool mTransactionPool;
+
+ public Builder(Context context, IWindowManager wmService,
+ DisplayController displayController, Handler handler,
+ TransactionPool transactionPool) {
+ mContext = context;
+ mWmService = wmService;
+ mDisplayController = displayController;
+ mHandler = handler;
+ mTransactionPool = transactionPool;
+ }
+
+ /** Builds and initializes {@link DisplaySystemBarsController} instance. */
+ public DisplaySystemBarsController build() {
+ DisplaySystemBarsController displaySystemBarsController =
+ new DisplaySystemBarsController(
+ mContext, mWmService, mDisplayController, mHandler, mTransactionPool);
+ // Separates startMonitorDisplays from constructor to prevent circular init issue.
+ displaySystemBarsController.startMonitorDisplays();
+ return displaySystemBarsController;
+ }
+ }
}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
index dec8b8ecdfb4..0b164a2e1a51 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
@@ -73,7 +73,8 @@ public class CarNavigationBarControllerTest extends SysuiTestCase {
private CarNavigationBarController createNavigationBarController() {
return new CarNavigationBarController(mContext, mNavigationBarViewFactory,
mButtonSelectionStateController, () -> mHvacController,
- mButtonRoleHolderController);
+ mButtonRoleHolderController,
+ new SystemBarConfigs(mTestableResources.getResources()));
}
@Test
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarTest.java
index d9edfa960858..2b5af71dccaa 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarTest.java
@@ -142,7 +142,7 @@ public class CarNavigationBarTest extends SysuiTestCase {
mWindowManager, mDeviceProvisionedController, new CommandQueue(mContext),
mAutoHideController, mButtonSelectionStateListener, mHandler, mUiBgExecutor,
mBarService, () -> mKeyguardStateController, () -> mIconPolicy,
- () -> mIconController);
+ () -> mIconController, new SystemBarConfigs(mTestableResources.getResources()));
}
@Test
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java
new file mode 100644
index 000000000000..8b1589913d1d
--- /dev/null
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.car.navigationbar;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.content.res.Resources;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.WindowManager;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.car.CarSystemUiTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@CarSystemUiTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class SystemBarConfigsTest extends SysuiTestCase {
+
+ private SystemBarConfigs mSystemBarConfigs;
+ @Mock
+ private Resources mResources;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ setDefaultValidConfig();
+ }
+
+ @Test
+ public void onInit_allSystemBarsEnabled_eachHasUniqueBarTypes_doesNotThrowException() {
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void onInit_allSystemBarsEnabled_twoBarsHaveDuplicateType_throwsRuntimeException() {
+ when(mResources.getInteger(R.integer.config_topSystemBarType)).thenReturn(0);
+ when(mResources.getInteger(R.integer.config_bottomSystemBarType)).thenReturn(0);
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
+ @Test
+ public void onInit_allSystemBarsEnabled_systemBarSidesSortedByZOrder() {
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ List<Integer> actualOrder = mSystemBarConfigs.getSystemBarSidesByZOrder();
+ List<Integer> expectedOrder = new ArrayList<>();
+ expectedOrder.add(SystemBarConfigs.LEFT);
+ expectedOrder.add(SystemBarConfigs.RIGHT);
+ expectedOrder.add(SystemBarConfigs.TOP);
+ expectedOrder.add(SystemBarConfigs.BOTTOM);
+
+ assertTrue(actualOrder.equals(expectedOrder));
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void onInit_intersectingBarsHaveSameZOrder_throwsRuntimeException() {
+ when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(33);
+ when(mResources.getInteger(R.integer.config_leftSystemBarZOrder)).thenReturn(33);
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
+ @Test
+ public void getTopSystemBarLayoutParams_topBarEnabled_returnsTopSystemBarLayoutParams() {
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ WindowManager.LayoutParams lp = mSystemBarConfigs.getLayoutParamsBySide(
+ SystemBarConfigs.TOP);
+
+ assertNotNull(lp);
+ }
+
+ @Test
+ public void getTopSystemBarLayoutParams_topBarNotEnabled_returnsNull() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(false);
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ WindowManager.LayoutParams lp = mSystemBarConfigs.getLayoutParamsBySide(
+ SystemBarConfigs.TOP);
+
+ assertNull(lp);
+ }
+
+ @Test
+ public void topSystemBarHasHigherZOrderThanHuns_topSystemBarIsNavigationBarPanelType() {
+ when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(
+ SystemBarConfigs.getHunZOrder() + 1);
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ WindowManager.LayoutParams lp = mSystemBarConfigs.getLayoutParamsBySide(
+ SystemBarConfigs.TOP);
+
+ assertEquals(lp.type, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL);
+ }
+
+ @Test
+ public void topSystemBarHasLowerZOrderThanHuns_topSystemBarIsStatusBarAdditionalType() {
+ when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(
+ SystemBarConfigs.getHunZOrder() - 1);
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ WindowManager.LayoutParams lp = mSystemBarConfigs.getLayoutParamsBySide(
+ SystemBarConfigs.TOP);
+
+ assertEquals(lp.type, WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL);
+ }
+
+ // Set valid config where all system bars are enabled.
+ private void setDefaultValidConfig() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.config_enableBottomNavigationBar)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.config_enableLeftNavigationBar)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.config_enableRightNavigationBar)).thenReturn(true);
+
+ when(mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height)).thenReturn(100);
+ when(mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height)).thenReturn(100);
+ when(mResources.getDimensionPixelSize(R.dimen.car_left_navigation_bar_width)).thenReturn(
+ 100);
+ when(mResources.getDimensionPixelSize(R.dimen.car_right_navigation_bar_width)).thenReturn(
+ 100);
+
+ when(mResources.getInteger(R.integer.config_topSystemBarType)).thenReturn(0);
+ when(mResources.getInteger(R.integer.config_bottomSystemBarType)).thenReturn(1);
+ when(mResources.getInteger(R.integer.config_leftSystemBarType)).thenReturn(2);
+ when(mResources.getInteger(R.integer.config_rightSystemBarType)).thenReturn(3);
+
+ when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(5);
+ when(mResources.getInteger(R.integer.config_bottomSystemBarZOrder)).thenReturn(10);
+ when(mResources.getInteger(R.integer.config_leftSystemBarZOrder)).thenReturn(2);
+ when(mResources.getInteger(R.integer.config_rightSystemBarZOrder)).thenReturn(3);
+ }
+}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java
index 20576e9ec11f..67f222b9e29a 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java
@@ -220,7 +220,7 @@ public class SideLoadedAppListenerTest extends SysuiTestCase {
verify(mSideLoadedAppStateController, never()).onUnsafeTaskCreatedOnDisplay(any());
verify(mSideLoadedAppStateController).onSafeTaskDisplayedOnDisplay(display1);
- verify(mSideLoadedAppStateController, never()).onUnsafeTaskDisplayedOnDisplay(display2);
+ verify(mSideLoadedAppStateController).onUnsafeTaskDisplayedOnDisplay(display2);
verify(mSideLoadedAppStateController).onSafeTaskDisplayedOnDisplay(display3);
verify(mSideLoadedAppStateController, never()).onUnsafeTaskDisplayedOnDisplay(display1);
verify(mSideLoadedAppStateController).onUnsafeTaskDisplayedOnDisplay(display2);
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediatorTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediatorTest.java
index de6feb64391f..7aeffce7042d 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediatorTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/userswitcher/UserSwitchTransitionViewMediatorTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.car.userswitcher;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -24,6 +25,8 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.car.CarSystemUiTest;
@@ -37,13 +40,15 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
-public class UserSwitchTransitionViewMediatorTest {
+public class UserSwitchTransitionViewMediatorTest extends SysuiTestCase {
private static final int TEST_USER = 100;
private UserSwitchTransitionViewMediator mUserSwitchTransitionViewMediator;
@Mock
private CarServiceProvider mCarServiceProvider;
@Mock
+ private CarDeviceProvisionedController mCarDeviceProvisionedController;
+ @Mock
private UserSwitchTransitionViewController mUserSwitchTransitionViewController;
@Mock
private CarUserManager.UserLifecycleEvent mUserLifecycleEvent;
@@ -53,21 +58,35 @@ public class UserSwitchTransitionViewMediatorTest {
MockitoAnnotations.initMocks(this);
mUserSwitchTransitionViewMediator = new UserSwitchTransitionViewMediator(
- mCarServiceProvider, mUserSwitchTransitionViewController);
-
+ mCarServiceProvider, mCarDeviceProvisionedController,
+ mUserSwitchTransitionViewController);
+ when(mCarDeviceProvisionedController.getCurrentUser()).thenReturn(TEST_USER);
}
@Test
- public void onUserLifecycleEvent_userStarting_callsHandleShow() {
+ public void onUserLifecycleEvent_userStarting_isCurrentUser_callsHandleShow() {
when(mUserLifecycleEvent.getEventType()).thenReturn(
CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING);
when(mUserLifecycleEvent.getUserId()).thenReturn(TEST_USER);
+
mUserSwitchTransitionViewMediator.handleUserLifecycleEvent(mUserLifecycleEvent);
verify(mUserSwitchTransitionViewController).handleShow(TEST_USER);
}
@Test
+ public void onUserLifecycleEvent_userStarting_isNotCurrentUser_doesNotCallHandleShow() {
+ when(mUserLifecycleEvent.getEventType()).thenReturn(
+ CarUserManager.USER_LIFECYCLE_EVENT_TYPE_STARTING);
+ when(mUserLifecycleEvent.getUserId()).thenReturn(TEST_USER);
+ when(mCarDeviceProvisionedController.getCurrentUser()).thenReturn(TEST_USER + 1);
+
+ mUserSwitchTransitionViewMediator.handleUserLifecycleEvent(mUserLifecycleEvent);
+
+ verify(mUserSwitchTransitionViewController, never()).handleShow(TEST_USER);
+ }
+
+ @Test
public void onUserLifecycleEvent_userSwitching_callsHandleHide() {
when(mUserLifecycleEvent.getEventType()).thenReturn(
CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING);
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java
index 391f75e35382..b65578dbe02c 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java
@@ -64,13 +64,13 @@ public class DisplaySystemBarsControllerTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = new DisplaySystemBarsController(
+ mController = new DisplaySystemBarsController.Builder(
mContext,
mIWindowManager,
mDisplayController,
mHandler,
mTransactionPool
- );
+ ).build();
}
@Test
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index bcaee367b03c..f108e06951ef 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -259,18 +259,19 @@ public class DeviceDiscoveryService extends Service {
private void onDeviceFound(@Nullable DeviceFilterPair device) {
if (device == null) return;
- if (mDevicesFound.contains(device)) {
- return;
- }
-
- if (DEBUG) Log.i(LOG_TAG, "Found device " + device);
-
Handler.getMain().sendMessage(obtainMessage(
DeviceDiscoveryService::onDeviceFoundMainThread, this, device));
}
@MainThread
void onDeviceFoundMainThread(@NonNull DeviceFilterPair device) {
+ if (mDevicesFound.contains(device)) {
+ Log.i(LOG_TAG, "Skipping device " + device + " - already among found devices");
+ return;
+ }
+
+ Log.i(LOG_TAG, "Found device " + device);
+
if (mDevicesFound.isEmpty()) {
onReadyToShowUI();
}
@@ -428,10 +429,10 @@ public class DeviceDiscoveryService extends Service {
@Override
public String toString() {
- return "DeviceFilterPair{" +
- "device=" + device +
- ", filter=" + filter +
- '}';
+ return "DeviceFilterPair{"
+ + "device=" + device + " " + getDisplayName()
+ + ", filter=" + filter
+ + '}';
}
}
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 1b5062efa23e..01d7682416fa 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -42,10 +42,10 @@
<string name="connected_via_app" msgid="3532267661404276584">"Падключана праз праграму \"<xliff:g id="NAME">%1$s</xliff:g>\""</string>
<string name="available_via_passpoint" msgid="1716000261192603682">"Даступна праз %1$s"</string>
<string name="tap_to_sign_up" msgid="5356397741063740395">"Націсніце, каб зарэгістравацца"</string>
- <string name="wifi_connected_no_internet" msgid="5087420713443350646">"Не падключана да інтэрнэту"</string>
+ <string name="wifi_connected_no_internet" msgid="5087420713443350646">"Няма падключэння да інтэрнэту"</string>
<string name="private_dns_broken" msgid="1984159464346556931">"Не ўдалося атрымаць доступ да прыватнага DNS-сервера"</string>
<string name="wifi_limited_connection" msgid="1184778285475204682">"Абмежаваныя магчымасці падключэння"</string>
- <string name="wifi_status_no_internet" msgid="3799933875988829048">"Не падключана да інтэрнэту"</string>
+ <string name="wifi_status_no_internet" msgid="3799933875988829048">"Няма падключэння да інтэрнэту"</string>
<string name="wifi_status_sign_in_required" msgid="2236267500459526855">"Трэба выканаць уваход"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5885145407184194503">"Пункт доступу часова заняты"</string>
<string name="connected_via_carrier" msgid="1968057009076191514">"Падключана праз %1$s"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 8e8368f9bc62..03161d051342 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -659,9 +659,6 @@
<!-- Setting Checkbox title for enabling Bluetooth Gabeldorsche. [CHAR LIMIT=40] -->
<string name="bluetooth_enable_gabeldorsche">Enable Gabeldorsche</string>
- <!-- Setting Checkbox title for enabling Enhanced Connectivity [CHAR LIMIT=80] -->
- <string name="enhanced_connectivity">Enhanced Connectivity</string>
-
<!-- UI debug setting: Select Bluetooth AVRCP Version -->
<string name="bluetooth_select_avrcp_version_string">Bluetooth AVRCP Version</string>
<!-- UI debug setting: Select Bluetooth AVRCP Version -->
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 18c2957b1adc..4eea8ad92e61 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -112,7 +112,6 @@ public class SecureSettings {
Settings.Secure.FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
Settings.Secure.VR_DISPLAY_MODE,
Settings.Secure.NOTIFICATION_BADGING,
- Settings.Secure.NOTIFICATION_FEEDBACK_ENABLED,
Settings.Secure.NOTIFICATION_DISMISS_RTL,
Settings.Secure.QS_AUTO_ADDED_TILES,
Settings.Secure.SCREENSAVER_ENABLED,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index dd94d2eb8fe0..a02d67fd7bca 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -149,5 +149,6 @@ public class GlobalSettingsValidators {
VALIDATORS.put(Global.CUSTOM_BUGREPORT_HANDLER_APP, ANY_STRING_VALIDATOR);
VALIDATORS.put(Global.CUSTOM_BUGREPORT_HANDLER_USER, ANY_INTEGER_VALIDATOR);
VALIDATORS.put(Global.DEVELOPMENT_SETTINGS_ENABLED, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(Global.NOTIFICATION_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 91f3f4af0566..c68ddbdcb5ad 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -189,7 +189,6 @@ public class SecureSettingsValidators {
VALIDATORS.put(Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.SHOW_NOTIFICATION_SNOOZE, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.NOTIFICATION_HISTORY_ENABLED, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Secure.NOTIFICATION_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.ZEN_DURATION, ANY_INTEGER_VALIDATOR);
VALIDATORS.put(Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.SHOW_ZEN_SETTINGS_SUGGESTION, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index ef3bdbc95809..fa06e14acccb 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -761,8 +761,8 @@ class SettingsProtoDumpUtil {
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
GlobalSettingsProto.Gpu.ANGLE_GL_DRIVER_SELECTION_VALUES);
dumpSetting(s, p,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST,
- GlobalSettingsProto.Gpu.ANGLE_WHITELIST);
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST,
+ GlobalSettingsProto.Gpu.ANGLE_ALLOWLIST);
dumpSetting(s, p,
Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX,
GlobalSettingsProto.Gpu.SHOW_ANGLE_IN_USE_DIALOG);
@@ -785,14 +785,14 @@ class SettingsProtoDumpUtil {
Settings.Global.GAME_DRIVER_OPT_OUT_APPS,
GlobalSettingsProto.Gpu.GAME_DRIVER_OPT_OUT_APPS);
dumpSetting(s, p,
- Settings.Global.GAME_DRIVER_BLACKLIST,
- GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLIST);
+ Settings.Global.GAME_DRIVER_DENYLIST,
+ GlobalSettingsProto.Gpu.GAME_DRIVER_DENYLIST);
dumpSetting(s, p,
- Settings.Global.GAME_DRIVER_WHITELIST,
- GlobalSettingsProto.Gpu.GAME_DRIVER_WHITELIST);
+ Settings.Global.GAME_DRIVER_ALLOWLIST,
+ GlobalSettingsProto.Gpu.GAME_DRIVER_ALLOWLIST);
dumpSetting(s, p,
- Settings.Global.GAME_DRIVER_BLACKLISTS,
- GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLISTS);
+ Settings.Global.GAME_DRIVER_DENYLISTS,
+ GlobalSettingsProto.Gpu.GAME_DRIVER_DENYLISTS);
dumpSetting(s, p,
Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES,
GlobalSettingsProto.Gpu.GAME_DRIVER_SPHAL_LIBRARIES);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java b/packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java
index 6e5b8890438d..66aa7baa3b51 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java
@@ -35,19 +35,17 @@ import java.util.List;
public class WriteFallbackSettingsFilesJobService extends JobService {
@Override
public boolean onStartJob(final JobParameters params) {
- switch (params.getJobId()) {
- case WRITE_FALLBACK_SETTINGS_FILES_JOB_ID:
- final List<String> settingsFiles = new ArrayList<>();
- settingsFiles.add(params.getExtras().getString(TABLE_GLOBAL, ""));
- settingsFiles.add(params.getExtras().getString(TABLE_SYSTEM, ""));
- settingsFiles.add(params.getExtras().getString(TABLE_SECURE, ""));
- settingsFiles.add(params.getExtras().getString(TABLE_SSAID, ""));
- settingsFiles.add(params.getExtras().getString(TABLE_CONFIG, ""));
- SettingsProvider.writeFallBackSettingsFiles(settingsFiles);
- return true;
- default:
- return false;
+ if (params.getJobId() != WRITE_FALLBACK_SETTINGS_FILES_JOB_ID) {
+ return false;
}
+ final List<String> settingsFiles = new ArrayList<>();
+ settingsFiles.add(params.getExtras().getString(TABLE_GLOBAL, ""));
+ settingsFiles.add(params.getExtras().getString(TABLE_SYSTEM, ""));
+ settingsFiles.add(params.getExtras().getString(TABLE_SECURE, ""));
+ settingsFiles.add(params.getExtras().getString(TABLE_SSAID, ""));
+ settingsFiles.add(params.getExtras().getString(TABLE_CONFIG, ""));
+ SettingsProvider.writeFallBackSettingsFiles(settingsFiles);
+ return false;
}
@Override
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 6914f0a1e33a..4bb8f45f331f 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -270,7 +270,6 @@ public class SettingsBackupTest {
Settings.Global.SMART_REPLIES_IN_NOTIFICATIONS_FLAGS,
Settings.Global.SMART_SUGGESTIONS_IN_NOTIFICATIONS_FLAGS,
Settings.Global.ENABLE_ADB_INCREMENTAL_INSTALL_DEFAULT,
- Settings.Global.ENHANCED_CONNECTIVITY_ENABLED,
Settings.Global.ENHANCED_4G_MODE_ENABLED,
Settings.Global.EPHEMERAL_COOKIE_MAX_SIZE_BYTES,
Settings.Global.ERROR_LOGCAT_PREFIX,
@@ -297,6 +296,7 @@ public class SettingsBackupTest {
Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED,
Settings.Global.HDMI_CONTROL_AUTO_WAKEUP_ENABLED,
Settings.Global.HDMI_CONTROL_ENABLED,
+ Settings.Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
Settings.Global.HDMI_CONTROL_VOLUME_CONTROL_ENABLED,
Settings.Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED,
Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED,
@@ -389,6 +389,7 @@ public class SettingsBackupTest {
Settings.Global.NITZ_UPDATE_DIFF,
Settings.Global.NITZ_UPDATE_SPACING,
Settings.Global.NOTIFICATION_SNOOZE_OPTIONS,
+ Settings.Global.NOTIFICATION_FEEDBACK_ENABLED,
Settings.Global.NR_NSA_TRACKING_SCREEN_OFF_MODE,
Settings.Global.NSD_ON,
Settings.Global.NTP_SERVER,
@@ -502,14 +503,14 @@ public class SettingsBackupTest {
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE,
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS,
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES,
- Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST,
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST,
Settings.Global.GAME_DRIVER_ALL_APPS,
Settings.Global.GAME_DRIVER_OPT_IN_APPS,
Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS,
Settings.Global.GAME_DRIVER_OPT_OUT_APPS,
- Settings.Global.GAME_DRIVER_BLACKLISTS,
- Settings.Global.GAME_DRIVER_BLACKLIST,
- Settings.Global.GAME_DRIVER_WHITELIST,
+ Settings.Global.GAME_DRIVER_DENYLISTS,
+ Settings.Global.GAME_DRIVER_DENYLIST,
+ Settings.Global.GAME_DRIVER_ALLOWLIST,
Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES,
Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX,
Settings.Global.GPU_DEBUG_LAYER_APP,
diff --git a/packages/SimAppDialog/Android.bp b/packages/SimAppDialog/Android.bp
index ff26710fa2e1..176035f73b65 100644
--- a/packages/SimAppDialog/Android.bp
+++ b/packages/SimAppDialog/Android.bp
@@ -4,7 +4,6 @@ android_app {
srcs: ["src/**/*.java"],
platform_apis: true,
- certificate: "platform",
static_libs: [
"androidx.legacy_legacy-support-v4",
diff --git a/packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png
new file mode 100644
index 000000000000..6c1f1cfdea7c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png
new file mode 100644
index 000000000000..6983c3b880c9
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/one_handed_tutorial.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png
new file mode 100644
index 000000000000..3ff692f0c6fc
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/one_handed_tutorial.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png
new file mode 100644
index 000000000000..75723fb2ea5a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/one_handed_tutorial.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png b/packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png
new file mode 100644
index 000000000000..173abedae48a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/one_handed_tutorial.png
Binary files differ
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index e48fe656d187..308fd88ee6cd 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Instellings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Het dit"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Stort SysUI-hoop"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> gebruik tans jou <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programme gebruik tans jou <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" en "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ligging"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofoon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors is af"</string>
<string name="device_services" msgid="1549944177856658705">"Toesteldienste"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Titelloos"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 300ca0e5b141..f2bf5778b42f 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ቅንብሮች"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ገባኝ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI Heap አራግፍ"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> የእርስዎን <xliff:g id="TYPES_LIST">%2$s</xliff:g> እየተጠቀመ ነው።"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"መተግበሪያዎች የእርስዎን <xliff:g id="TYPES_LIST">%s</xliff:g> እየተጠቀሙ ነው።"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"፣ "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" እና "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"ካሜራ"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"አካባቢ"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"ማይክሮፎን"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ዳሳሾች ጠፍተዋል"</string>
<string name="device_services" msgid="1549944177856658705">"የመሣሪያ አገልግሎቶች"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ርዕስ የለም"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 7f2a405efed2..36280e716c4e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1005,6 +1005,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"الإعدادات"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"حسنًا"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"‏تفريغ ذاكرة SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"التطبيق <xliff:g id="APP">%1$s</xliff:g> يستخدم <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"تستخدم التطبيقات <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" و "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"الكاميرا"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"الموقع"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"الميكروفون"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"إيقاف أجهزة الاستشعار"</string>
<string name="device_services" msgid="1549944177856658705">"خدمات الأجهزة"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"بلا عنوان"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 0345af07cd91..a4cc17b822d5 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ছেটিংবোৰ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"বুজি পালোঁ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI হীপ ডাম্প কৰক"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>এ আপোনাৰ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ব্যৱহাৰ কৰি আছে।"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"এপ্লিকেশ্বনসমূহে আপোনাৰ <xliff:g id="TYPES_LIST">%s</xliff:g> ব্যৱহাৰ কৰি আছে।"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" আৰু "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"কেমেৰা"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"অৱস্থান"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"মাইক্ৰ\'ফ\'ন"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ছেন্সৰ অফ হৈ আছে"</string>
<string name="device_services" msgid="1549944177856658705">"ডিভাইচ সেৱা"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"কোনো শিৰোনাম নাই"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index d0025306d203..9443ba8ac22c 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ayarlar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Anladım"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="TYPES_LIST">%2$s</xliff:g> tətbiqlərindən istifadə edir."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Tətbiqlər <xliff:g id="TYPES_LIST">%s</xliff:g> istifadə edir."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" və "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"məkan"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorlar deaktivdir"</string>
<string name="device_services" msgid="1549944177856658705">"Cihaz Xidmətləri"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Başlıq yoxdur"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 5cca958bbe96..5b8c44599eed 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -990,6 +990,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Podešavanja"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Važi"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Izdvoji SysUI mem."</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> koristi <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kameru"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori su isključeni"</string>
<string name="device_services" msgid="1549944177856658705">"Usluge za uređaje"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 956ef477c927..6ee51682fe85 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -919,7 +919,7 @@
<string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Закрыць хуткія налады."</string>
<string name="accessibility_quick_settings_alarm_set" msgid="7237918261045099853">"Будзільнік пастаўлены."</string>
<string name="accessibility_quick_settings_user" msgid="505821942882668619">"Вы ўвайшлі як <xliff:g id="ID_1">%s</xliff:g>"</string>
- <string name="data_connection_no_internet" msgid="691058178914184544">"Не падключана да інтэрнэту"</string>
+ <string name="data_connection_no_internet" msgid="691058178914184544">"Няма падключэння да інтэрнэту"</string>
<string name="accessibility_quick_settings_open_details" msgid="4879279912389052142">"Паказаць падрабязную інфармацыю."</string>
<string name="accessibility_quick_settings_not_available" msgid="6860875849497473854">"Прычына недаступнасці: <xliff:g id="REASON">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Адкрыць налады <xliff:g id="ID_1">%s</xliff:g>."</string>
@@ -995,6 +995,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Налады"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Зразумела"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Праграма \"<xliff:g id="APP">%1$s</xliff:g>\" выкарыстоўвае: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Праграмы выкарыстоўваюць: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" і "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"геалакацыя"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"мікрафон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчыкі выкл."</string>
<string name="device_services" msgid="1549944177856658705">"Сэрвісы прылады"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без назвы"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index d0836e4509fe..c7bb3d08579c 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Настройки"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Разбрах"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> използва <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Някои приложения използват <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"камерата"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"местополож."</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофона"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Сензорите са изключени"</string>
<string name="device_services" msgid="1549944177856658705">"Услуги за устройството"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Няма заглавие"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index a584955b534d..42e7523aef81 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"সেটিংস"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"বুঝেছি"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> আপনার <xliff:g id="TYPES_LIST">%2$s</xliff:g> ব্যবহার করছে।"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"অ্যাপ্লিকেশনগুলি আপনার <xliff:g id="TYPES_LIST">%s</xliff:g> ব্যবহার করছে।"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" এবং "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"ক্যামেরা"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"লোকেশন"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"মাইক্রোফোন"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"সেন্সর বন্ধ"</string>
<string name="device_services" msgid="1549944177856658705">"ডিভাইস সংক্রান্ত পরিষেবা"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"কোনও শীর্ষক নেই"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 4c872d22054f..16a1aa615c9b 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -990,6 +990,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Postavke"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Razumijem"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Izdvoji SysUI mem."</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> koristi <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije koriste <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kameru"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori su isključeni"</string>
<string name="device_services" msgid="1549944177856658705">"Usluge uređaja"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 7267c31b1f36..fdcec987f438 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configuració"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Entesos"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Aboca espai de SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> està fent servir el següent: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Algunes aplicacions estan fent servir el següent: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"càmera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ubicació"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"micròfon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors desactivats"</string>
<string name="device_services" msgid="1549944177856658705">"Serveis per a dispositius"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sense títol"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 29b5281f689f..ab3b4fb2659c 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -995,6 +995,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Nastavení"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Rozumím"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Výpis haldy SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Aplikace <xliff:g id="APP">%1$s</xliff:g> využívá tato oprávnění: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikace využívají tato oprávnění: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" a "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparát"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"poloha"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzory jsou vypnuty"</string>
<string name="device_services" msgid="1549944177856658705">"Služby zařízení"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index dff770d49e28..0fc9b9495388 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Indstillinger"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Gem SysUI-heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> anvender enhedens <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps anvender enhedens <xliff:g id="TYPES_LIST">%s</xliff:g>"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" og "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"placering"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Deaktiver sensorer"</string>
<string name="device_services" msgid="1549944177856658705">"Enhedstjenester"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 52275fcd637e..a6b137a8e9e5 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Einstellungen"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ok"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> verwendet gerade Folgendes: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps verwenden gerade Folgendes: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" und "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"Kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"Standort"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"Mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensoren aus"</string>
<string name="device_services" msgid="1549944177856658705">"Gerätedienste"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Kein Titel"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index bf4c61994c29..bdd19a18b2dd 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ρυθμίσεις"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Το κατάλαβα"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Στιγμ. μνήμης SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Η εφαρμογή <xliff:g id="APP">%1$s</xliff:g> χρησιμοποιεί τις λειτουργίες <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Οι εφαρμογές χρησιμοποιούν τις λειτουργίες <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" και "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"κάμερα"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"τοποθεσία"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"μικρόφωνο"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Αισθητήρες ανενεργοί"</string>
<string name="device_services" msgid="1549944177856658705">"Υπηρεσίες συσκευής"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Χωρίς τίτλο"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index acb811107463..68a8d30477f6 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Settings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
<string name="device_services" msgid="1549944177856658705">"Device Services"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index e3bad1f83a90..e9856af6cb1e 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Settings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
<string name="device_services" msgid="1549944177856658705">"Device Services"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index acb811107463..68a8d30477f6 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Settings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
<string name="device_services" msgid="1549944177856658705">"Device Services"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index acb811107463..68a8d30477f6 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Settings"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> is using your <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Applications are using your <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" and "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"location"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensors off"</string>
<string name="device_services" msgid="1549944177856658705">"Device Services"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"No title"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 25ec6c384157..eacef2624b05 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‏‎‎Settings‎‏‎‎‏‎"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎Got it‎‏‎‎‏‎"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎Dump SysUI Heap‎‏‎‎‏‎"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is using your ‎‏‎‎‏‏‎<xliff:g id="TYPES_LIST">%2$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎Applications are using your ‎‏‎‎‏‏‎<xliff:g id="TYPES_LIST">%s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‎"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‎, ‎‏‎‎‏‎ "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‎ "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‎‏‏‏‏‎‎‎camera‎‏‎‎‏‎"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎location‎‏‎‎‏‎"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‎microphone‎‏‎‎‏‎"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎Sensors off‎‏‎‎‏‎"</string>
<string name="device_services" msgid="1549944177856658705">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎Device Services‎‏‎‎‏‎"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎No title‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 01bed104a951..94a464bb6afa 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configuración"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Entendido"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Volcar pila de SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hay aplicaciones que están usando tu <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" y "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"cámara"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ubicación"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"micrófono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Se desactivaron los sensores"</string>
<string name="device_services" msgid="1549944177856658705">"Servicios del dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 67678d24a0a6..0e7d376e5884 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ajustes"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Entendido"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Volcar pila de SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> está usando tu <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hay aplicaciones que usan tu <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" y "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"cámara"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ubicación"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"micrófono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desactivados"</string>
<string name="device_services" msgid="1549944177856658705">"Servicios del dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sin título"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index a46fa490b4a8..fc9c73bb10bf 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Seaded"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Selge"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> kasutab järgmisi: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Rakendused kasutavad järgmisi: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ja "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kaamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"asukoht"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Andurid on välja lülitatud"</string>
<string name="device_services" msgid="1549944177856658705">"Seadme teenused"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Pealkiri puudub"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 19fc4f50d0d3..041beab2e74c 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ezarpenak"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ados"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="TYPES_LIST">%2$s</xliff:g> erabiltzen ari da."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikazio batzuk <xliff:g id="TYPES_LIST">%s</xliff:g> erabiltzen ari dira."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" eta "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"kokapena"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofonoa"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sentsoreak desaktibatuta daude"</string>
<string name="device_services" msgid="1549944177856658705">"Gailuetarako zerbitzuak"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ez du izenik"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index b8c87938d423..05e076f55a12 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"تنظیمات"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"متوجه شدم"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> از <xliff:g id="TYPES_LIST">%2$s</xliff:g> شما استفاده می‌کند."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"برنامه‌ها از <xliff:g id="TYPES_LIST">%s</xliff:g> شما استفاده می‌‌کنند."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" و "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"دوربین"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"مکان"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"میکروفون"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"حسگرها خاموش است"</string>
<string name="device_services" msgid="1549944177856658705">"سرویس‌های دستگاه"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"بدون عنوان"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 44a66c31b954..4fccaaca57f2 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Asetukset"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Selvä"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Luo SysUI-keon vedos"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> käyttää ominaisuuksia (<xliff:g id="TYPES_LIST">%2$s</xliff:g>)."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"<xliff:g id="TYPES_LIST">%s</xliff:g> ovat sovellusten käytössä."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ja "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"sijainti"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofoni"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Anturit pois päältä"</string>
<string name="device_services" msgid="1549944177856658705">"Laitepalvelut"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ei nimeä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 15cf6eb40658..4e2074c34a88 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Paramètres"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Copier mémoire SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" et "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"appareil photo"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"position"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microphone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Capteurs désactivés"</string>
<string name="device_services" msgid="1549944177856658705">"Services de l\'appareil"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 784186b013a9..fedec563edcf 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Paramètres"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Copier mémoire SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> utilise votre <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Des applications utilisent votre <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" et "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"appareil photo"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"position"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"micro"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Capteurs désactivés"</string>
<string name="device_services" msgid="1549944177856658705">"Services pour l\'appareil"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
@@ -1021,9 +1028,9 @@
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Paramètres"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Fenêtre des commandes d\'agrandissement"</string>
- <string name="quick_controls_title" msgid="6839108006171302273">"Commandes de contrôle des appareils"</string>
+ <string name="quick_controls_title" msgid="6839108006171302273">"Commandes des appareils"</string>
<string name="quick_controls_subtitle" msgid="1667408093326318053">"Ajouter des commandes pour vos appareils connectés"</string>
- <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurer les commandes de contrôle des appareils"</string>
+ <string name="quick_controls_setup_title" msgid="8901436655997849822">"Configurer les commandes des appareils"</string>
<string name="quick_controls_setup_subtitle" msgid="1681506617879773824">"Appuyez de manière prolongée sur le bouton Marche/Arrêt pour accéder aux commandes"</string>
<string name="controls_providers_title" msgid="6879775889857085056">"Sélectionnez l\'appli pour laquelle ajouter des commandes"</string>
<plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
@@ -1046,7 +1053,7 @@
<string name="controls_favorite_load_error" msgid="5126216176144877419">"Impossible de charger les commandes. Vérifiez l\'application <xliff:g id="APP">%s</xliff:g> pour vous assurer que les paramètres n\'ont pas changé."</string>
<string name="controls_favorite_load_none" msgid="7687593026725357775">"Commandes compatibles indisponibles"</string>
<string name="controls_favorite_other_zone_header" msgid="9089613266575525252">"Autre"</string>
- <string name="controls_dialog_title" msgid="2343565267424406202">"Ajouter aux commandes de contrôle des appareils"</string>
+ <string name="controls_dialog_title" msgid="2343565267424406202">"Ajouter aux commandes des appareils"</string>
<string name="controls_dialog_ok" msgid="2770230012857881822">"Ajouter"</string>
<string name="controls_dialog_message" msgid="342066938390663844">"Suggérée par <xliff:g id="APP">%s</xliff:g>"</string>
<string name="controls_dialog_confirmation" msgid="586517302736263447">"Commandes mises à jour"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index c732c7bbff1f..c1b9024e8b44 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configuración"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"De acordo"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Baleirado mem. SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> está utilizando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Hai aplicacións que están utilizando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"a cámara"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"a localiz."</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"o micrófono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Desactivar sensores"</string>
<string name="device_services" msgid="1549944177856658705">"Servizos do dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sen título"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 5d3d3af8f917..9c2f71790fb0 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"સેટિંગ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"સમજાઈ ગયું"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ઍપ તમારા <xliff:g id="TYPES_LIST">%2$s</xliff:g>નો ઉપયોગ કરી રહી છે."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ઍપ્લિકેશન તમારા <xliff:g id="TYPES_LIST">%s</xliff:g>નો ઉપયોગ કરી રહી છે."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" અને "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"કૅમેરા"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"સ્થાન"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"માઇક્રોફોન"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"સેન્સર બંધ છે"</string>
<string name="device_services" msgid="1549944177856658705">"ડિવાઇસ સેવાઓ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"કોઈ શીર્ષક નથી"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f6bc4cdab087..cc2faa2a598c 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -987,6 +987,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"सेटिंग"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ठीक है"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> आपकी <xliff:g id="TYPES_LIST">%2$s</xliff:g> का इस्तेमाल कर रहा है."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ऐप्लिकेशन आपकी <xliff:g id="TYPES_LIST">%s</xliff:g> का इस्तेमाल कर रहे हैं."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" और "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"कैमरा"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"जगह"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"माइक्रोफ़ोन"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"सेंसर बंद हैं"</string>
<string name="device_services" msgid="1549944177856658705">"डिवाइस सेवाएं"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"कोई शीर्षक नहीं"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index bfd5aa001c24..90251995002d 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -990,6 +990,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Postavke"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Shvaćam"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Izdvoji mem. SysUI-a"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> upotrebljava <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije upotrebljavaju <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparat"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"lokaciju"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori su isključeni"</string>
<string name="device_services" msgid="1549944177856658705">"Usluge uređaja"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez naslova"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index c8f4a467f94b..689d86960c88 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Beállítások"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Értem"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI-memória-kiírás"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"A(z) <xliff:g id="APP">%1$s</xliff:g> használja a következőket: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Több alkalmazás használja a következőket: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" és "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"helyadatok"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Érzékelők kikapcsolva"</string>
<string name="device_services" msgid="1549944177856658705">"Eszközszolgáltatások"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nincs cím"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 53286188af47..a574f26a514d 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -916,7 +916,7 @@
<string name="accessibility_quick_settings_edit" msgid="1523745183383815910">"Խմբագրել կարգավորումների հերթականությունը:"</string>
<string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Էջ <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string>
<string name="tuner_lock_screen" msgid="2267383813241144544">"Կողպէկրան"</string>
- <string name="thermal_shutdown_title" msgid="2702966892682930264">"Հեռախոսն անջատվել է տաքանալու պատճառով"</string>
+ <string name="thermal_shutdown_title" msgid="2702966892682930264">"Հեռախոսն անջատվել էր տաքանալու պատճառով"</string>
<string name="thermal_shutdown_message" msgid="6142269839066172984">"Հեռախոսն այժմ նորմալ է աշխատում։\nՀպեք՝ ավելին իմանալու համար։"</string>
<string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"Ձեր հեռախոսը չափազանց տաք էր, այդ պատճառով այն անջատվել է՝ հովանալու համար: Հեռախոսն այժմ նորմալ աշխատում է:\n\nՀեռախոսը կարող է տաքանալ, եթե՝\n • Օգտագործում եք ռեսուրսատար հավելվածներ (օրինակ՝ խաղեր, տեսանյութեր կամ նավարկման հավելվածներ)\n • Ներբեռնում կամ վերբեռնում եք ծանր ֆայլեր\n • Օգտագործում եք ձեր հեռախոսը բարձր ջերմային պայմաններում"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"Քայլեր գերտաքացման ահազանգի դեպքում"</string>
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Կարգավորումներ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Եղավ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> հավելվածն օգտագործում է ձեր <xliff:g id="TYPES_LIST">%2$s</xliff:g>:"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Հավելվածներն օգտագործում են ձեր <xliff:g id="TYPES_LIST">%s</xliff:g>:"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" և "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"տեսախցիկը"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"վայրը"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"խոսափողը"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Տվիչներն անջատած են"</string>
<string name="device_services" msgid="1549944177856658705">"Սարքի ծառայություններ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Անանուն"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index dfed57b94c51..7cc1b898dedb 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Setelan"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Oke"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Hapus Heap SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> menggunakan <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikasi menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" dan "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"lokasi"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensor nonaktif"</string>
<string name="device_services" msgid="1549944177856658705">"Layanan Perangkat"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Tanpa judul"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 57cdb272f176..8b686b8deb96 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Stillingar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ég skil"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Vista SysUI-gögn"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> er að nota <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Forrit eru að nota <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" og "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"myndavél"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"staðsetning"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"hljóðnemi"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Slökkt á skynjurum"</string>
<string name="device_services" msgid="1549944177856658705">"Tækjaþjónusta"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Enginn titill"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 679eb551e7f0..35742fd4d4db 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Impostazioni"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Esegui dump heap SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"L\'app <xliff:g id="APP">%1$s</xliff:g> sta usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Le app stanno usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"Fotocamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"luogo"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"un microfono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensori disattivati"</string>
<string name="device_services" msgid="1549944177856658705">"Servizi del dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Senza titolo"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index b6a723f00024..1029bb2042db 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -995,6 +995,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"הגדרות"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"הבנתי"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"‏ערימת Dump SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> משתמשת ב<xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"אפליקציות משתמשות ב<xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" וגם "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"מצלמה"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"מיקום"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"מיקרופון"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"החיישנים כבויים"</string>
<string name="device_services" msgid="1549944177856658705">"שירותים למכשיר"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ללא שם"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b70e2e2bc14f..fedd9bb7ffc0 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"設定"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ヒープのダンプ"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>は<xliff:g id="TYPES_LIST">%2$s</xliff:g>を使用しています。"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"アプリは<xliff:g id="TYPES_LIST">%s</xliff:g>を使用しています。"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 、 "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"カメラ"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"現在地情報"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"マイク"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"センサー OFF"</string>
<string name="device_services" msgid="1549944177856658705">"デバイス サービス"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"タイトルなし"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 0dda483b9d16..5c55112ea1fd 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"პარამეტრები"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"გასაგებია"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI გროვის გამოტანა"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>-ის მიერ გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"აპლიკაციების მიერ გამოიყენება თქვენი <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" და "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"კამერა"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"მდებარეობა"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"მიკროფონი"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"სენსორების გამორთვა"</string>
<string name="device_services" msgid="1549944177856658705">"მოწყობილობის სერვისები"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"უსათაურო"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 27bc3ab4aab0..94c8ea33a461 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Параметрлер"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Түсінікті"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> қолданбасында <xliff:g id="TYPES_LIST">%2$s</xliff:g> пайдалануда."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Қолданбаларда <xliff:g id="TYPES_LIST">%s</xliff:g> пайдаланылуда."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" және "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"геодерек"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчиктер өшірулі"</string>
<string name="device_services" msgid="1549944177856658705">"Құрылғы қызметтері"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Атауы жоқ"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 36d5aa8ab45b..5ba460adebf3 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ការកំណត់"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"យល់ហើយ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"ចម្លង SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> កំពុងប្រើ <xliff:g id="TYPES_LIST">%2$s</xliff:g> របស់អ្នក។"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"កម្មវិធី​កំពុងប្រើ <xliff:g id="TYPES_LIST">%s</xliff:g> របស់អ្នក។"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" និង "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"កាមេរ៉ា"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ទីតាំង"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"មីក្រូហ្វូន"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"បិទឧបករណ៍​ចាប់សញ្ញា"</string>
<string name="device_services" msgid="1549944177856658705">"សេវាកម្មឧបករណ៍"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"គ្មាន​ចំណងជើង"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 2034472d18cd..7b8ed88bfd19 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ಅರ್ಥವಾಯಿತು"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"ನಿಮ್ಮ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ಅನ್ನು <xliff:g id="APP">%1$s</xliff:g> ಬಳಸುತ್ತಿದೆ."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ನಿಮ್ಮ <xliff:g id="TYPES_LIST">%s</xliff:g> ಅನ್ನು ಆ್ಯಪ್‌ಗಳು ಬಳಸುತ್ತಿವೆ."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ಮತ್ತು "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"ಕ್ಯಾಮರಾ"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ಸ್ಥಳ"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"ಮೈಕ್ರೋಫೋನ್‌"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ಸೆನ್ಸರ್‌ಗಳು ಆಫ್"</string>
<string name="device_services" msgid="1549944177856658705">"ಸಾಧನ ಸೇವೆಗಳು"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ಯಾವುದೇ ಶೀರ್ಷಿಕೆಯಿಲ್ಲ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index ef4a5f63d0d3..8d1177bec0ea 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"설정"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"확인"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>이(가) <xliff:g id="TYPES_LIST">%2$s</xliff:g>을(를) 사용 중입니다."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"애플리케이션이 <xliff:g id="TYPES_LIST">%s</xliff:g>을(를) 사용 중입니다."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 및 "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"카메라"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"위치"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"마이크"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"센서 사용 안함"</string>
<string name="device_services" msgid="1549944177856658705">"기기 서비스"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"제목 없음"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index cfd91b56ddf5..794de98420d1 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Жөндөөлөр"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Түшүндүм"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> төмөнкүлөрдү колдонуп жатат: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Колдонмолор төмөнкүлөрдү пайдаланып жатышат: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" жана "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"жайгашкан жер"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Сенсорлорду өчүрүү"</string>
<string name="device_services" msgid="1549944177856658705">"Түзмөк кызматтары"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Аталышы жок"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 90b5ad2267ac..2fe3f8075dbb 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ການຕັ້ງຄ່າ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ເຂົ້າໃຈແລ້ວ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງໃຊ້ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ຂອງທ່ານ."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ແອັບພລິເຄຊັນກຳລັງໃຊ້ <xliff:g id="TYPES_LIST">%s</xliff:g> ຂອງທ່ານ."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ແລະ "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"ກ້ອງຖ່າຍຮູບ"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ສະຖານທີ່"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"ໄມໂຄຣໂຟນ"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ປິດການຮັບຮູ້ຢູ່"</string>
<string name="device_services" msgid="1549944177856658705">"ບໍລິການອຸປະກອນ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ບໍ່ມີຊື່"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 5c8e8d9ac8fb..4489b7dd62ee 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -995,6 +995,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Nustatymai"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Supratau"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Pat. „SysUI“ krūvą"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Programa „<xliff:g id="APP">%1$s</xliff:g>“ naudoja: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programos naudoja: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ir "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparatą"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"vietovę"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofoną"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Jutikliai išjungti"</string>
<string name="device_services" msgid="1549944177856658705">"Įrenginio paslaugos"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nėra pavadinimo"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index cbe076896d9f..d4826e42f17c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -28,15 +28,15 @@
<string name="battery_low_percent_format" msgid="4276661262843170964">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="battery_low_percent_format_hybrid" msgid="3985614339605686167">"Atlikušais laiks: <xliff:g id="PERCENTAGE">%1$s</xliff:g> — aptuveni <xliff:g id="TIME">%2$s</xliff:g> (ņemot vērā lietojumu)"</string>
<string name="battery_low_percent_format_hybrid_short" msgid="5917433188456218857">"Atlikušais laiks: <xliff:g id="PERCENTAGE">%1$s</xliff:g> — aptuveni <xliff:g id="TIME">%2$s</xliff:g>"</string>
- <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>. Ir ieslēgts akumulatora jaudas taupīšanas režīms."</string>
+ <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>. Ir ieslēgts akumulatora enerģijas taupīšanas režīms."</string>
<string name="invalid_charger" msgid="4370074072117767416">"Nevar veikt uzlādi, izmantojot USB. Izmantojiet ierīces komplektācijā iekļauto uzlādes ierīci."</string>
<string name="invalid_charger_title" msgid="938685362320735167">"Nevar veikt uzlādi, izmantojot USB"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Izmantojiet ierīces komplektācijā iekļauto uzlādes ierīci"</string>
<string name="battery_low_why" msgid="2056750982959359863">"Iestatījumi"</string>
- <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Vai ieslēgt akumulatora jaudas taupīšanas režīmu?"</string>
- <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Par akumulatora jaudas taupīšanas režīmu"</string>
+ <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Vai ieslēgt akumulatora enerģijas taupīšanas režīmu?"</string>
+ <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Par akumulatora enerģijas taupīšanas režīmu"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Ieslēgt"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"Ieslēgt akumulatora jaudas taupīšanas režīmu"</string>
+ <string name="battery_saver_start_action" msgid="4553256017945469937">"Ieslēgt akumulatora enerģijas taupīšanas režīmu"</string>
<string name="status_bar_settings_settings_button" msgid="534331565185171556">"Iestatījumi"</string>
<string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"Wi-Fi"</string>
<string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automātiska ekrāna pagriešana"</string>
@@ -423,7 +423,7 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Līdz <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Tumšais motīvs"</string>
- <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Jaudas taupīšana"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Enerģijas taupīšana"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Saulrietā"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Līdz saullēktam"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -502,9 +502,9 @@
<string name="user_remove_user_title" msgid="9124124694835811874">"Vai noņemt lietotāju?"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"Tiks dzēstas visas šī lietotāja lietotnes un dati."</string>
<string name="user_remove_user_remove" msgid="8387386066949061256">"Noņemt"</string>
- <string name="battery_saver_notification_title" msgid="8419266546034372562">"Akumulatora jaudas taupīšanas režīms ir ieslēgts"</string>
+ <string name="battery_saver_notification_title" msgid="8419266546034372562">"Akumulatora enerģijas taupīšanas režīms ir ieslēgts"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"Samazina veiktspēju un fona datus"</string>
- <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Izslēgt akumulatora jaudas taupīšanas režīmu"</string>
+ <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Izslēgt akumulatora enerģijas taupīšanas režīmu"</string>
<string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> iegūs piekļuvi visai informācijai, kas ierakstīšanas vai apraides laikā tiks rādīta jūsu ekrānā vai atskaņota jūsu ierīcē. Atļauja attiecas uz tādu informāciju kā paroles, maksājumu informācija, fotoattēli, ziņojumi un jūsu atskaņotais audio saturs."</string>
<string name="media_projection_dialog_service_text" msgid="958000992162214611">"Pakalpojums, kas nodrošina šo funkciju, iegūs piekļuvi visai informācijai, kas ierakstīšanas vai apraides laikā tiks rādīta jūsu ekrānā vai atskaņota jūsu ierīcē. Atļauja attiecas uz tādu informāciju kā paroles, maksājumu informācija, fotoattēli, ziņojumi un jūsu atskaņotais audio saturs."</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Vai vēlaties sākt ierakstīšanu/apraidi?"</string>
@@ -780,8 +780,8 @@
<item quantity="other">%d minūtes</item>
</plurals>
<string name="battery_panel_title" msgid="5931157246673665963">"Akumulatora lietojums"</string>
- <string name="battery_detail_charging_summary" msgid="8821202155297559706">"Akumulatora jaudas taupīšanas režīms uzlādes laikā nav pieejams."</string>
- <string name="battery_detail_switch_title" msgid="6940976502957380405">"Akumulatora jaudas taupīšanas režīms"</string>
+ <string name="battery_detail_charging_summary" msgid="8821202155297559706">"Akumulatora enerģijas taupīšanas režīms uzlādes laikā nav pieejams."</string>
+ <string name="battery_detail_switch_title" msgid="6940976502957380405">"Akumulatora enerģijas taupīšanas režīms"</string>
<string name="battery_detail_switch_summary" msgid="3668748557848025990">"Samazina veiktspēju un fona datus."</string>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"Poga <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="keyboard_key_home" msgid="3734400625170020657">"Sākumvietas taustiņš"</string>
@@ -982,14 +982,21 @@
<string name="slice_permission_checkbox" msgid="4242888137592298523">"Atļaut lietotnei <xliff:g id="APP">%1$s</xliff:g> rādīt sadaļas no jebkuras lietotnes"</string>
<string name="slice_permission_allow" msgid="6340449521277951123">"Atļaut"</string>
<string name="slice_permission_deny" msgid="6870256451658176895">"Neatļaut"</string>
- <string name="auto_saver_title" msgid="6873691178754086596">"Pieskarieties, lai iestatītu akumulatora jaudas taupīšanas režīma grafiku"</string>
+ <string name="auto_saver_title" msgid="6873691178754086596">"Pieskarieties, lai iestatītu akumulatora enerģijas taupīšanas režīma grafiku"</string>
<string name="auto_saver_text" msgid="3214960308353838764">"Ieslēgt, ja akumulators var izlādēties"</string>
<string name="no_auto_saver_action" msgid="7467924389609773835">"Nē, paldies"</string>
<string name="auto_saver_enabled_title" msgid="4294726198280286333">"Ieslēgts akumulatora enerģijas taupīšanas režīma grafiks"</string>
- <string name="auto_saver_enabled_text" msgid="7889491183116752719">"Tiklīdz akumulatora uzlādes līmenis būs zemāks nekā <xliff:g id="PERCENTAGE">%d</xliff:g>%%, tiks automātiski ieslēgts akumulatora jaudas taupīšanas režīms."</string>
+ <string name="auto_saver_enabled_text" msgid="7889491183116752719">"Tiklīdz akumulatora uzlādes līmenis būs zemāks nekā <xliff:g id="PERCENTAGE">%d</xliff:g>%%, tiks automātiski ieslēgts akumulatora enerģijas taupīšanas režīms."</string>
<string name="open_saver_setting_action" msgid="2111461909782935190">"Iestatījumi"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Labi"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Lietotne <xliff:g id="APP">%1$s</xliff:g> izmanto funkcijas <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Lietojumprogrammas izmanto šādas funkcijas: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" un "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"atrašanās vieta"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofons"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensori izslēgti"</string>
<string name="device_services" msgid="1549944177856658705">"Ierīces pakalpojumi"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nav nosaukuma"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 5a000de3e843..4836ecf1574a 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Поставки"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Сфатив"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Извади SysUI-слика"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> користи <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Апликациите користат <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"локација"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Сензорите се исклучени"</string>
<string name="device_services" msgid="1549944177856658705">"Услуги за уредот"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без наслов"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 22392279a919..863ce1152752 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ക്രമീകരണം"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"മനസ്സിലായി"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ഹീപ്പ് ഡമ്പ് ചെയ്യുക"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> നിങ്ങളുടെ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ഉപയോഗിക്കുന്നു."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ആപ്പുകൾ നിങ്ങളുടെ <xliff:g id="TYPES_LIST">%s</xliff:g> ഉപയോഗിക്കുന്നു."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" കൂടാതെ "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"ക്യാമറ"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ലൊക്കേഷന്‍"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"മൈക്രോഫോൺ"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"സെൻസറുകൾ ഓഫാണ്"</string>
<string name="device_services" msgid="1549944177856658705">"ഉപകരണ സേവനങ്ങള്‍"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"പേരില്ല"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 8141ef3a1fc6..107c3101a221 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Тохиргоо"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ойлголоо"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> таны <xliff:g id="TYPES_LIST">%2$s</xliff:g>-г ашиглаж байна."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Аппууд таны <xliff:g id="TYPES_LIST">%s</xliff:g>-г ашиглаж байна."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" болон "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"камер"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"байршил"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Мэдрэгчийг унтраах"</string>
<string name="device_services" msgid="1549944177856658705">"Төхөөрөмжийн үйлчилгээ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Гарчиггүй"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 79b7ae8b12a5..bd2c3a5d09e9 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"सेटिंग्ज"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"समजले"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI हीप डंप करा"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> तुमचे <xliff:g id="TYPES_LIST">%2$s</xliff:g> वापरत आहे."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ॲप्लिकेशन्स तुमचे <xliff:g id="TYPES_LIST">%s</xliff:g> वापरत आहे."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" आणि "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"कॅमेरा"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"स्थान"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"मायक्रोफोन"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"सेन्सर बंद आहेत"</string>
<string name="device_services" msgid="1549944177856658705">"डिव्हाइस सेवा"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक नाही"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 37cbb7edf753..029571b656ea 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Tetapan"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Longgok Tmbunn SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> sedang menggunakan <xliff:g id="TYPES_LIST">%2$s</xliff:g> anda."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikasi sedang menggunakan <xliff:g id="TYPES_LIST">%s</xliff:g> anda."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" dan "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"lokasi"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Penderia dimatikan"</string>
<string name="device_services" msgid="1549944177856658705">"Perkhidmatan Peranti"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Tiada tajuk"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 376ed2fd2d9a..6e632af3c5f4 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ဆက်တင်များ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ရပါပြီ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> က သင်၏ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ကို အသုံးပြုနေသည်။"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"အပလီကေးရှင်းများက သင်၏ <xliff:g id="TYPES_LIST">%s</xliff:g> ကို အသုံးပြုနေသည်။"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"၊ "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" နှင့် "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"ကင်မရာ"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"တည်နေရာ"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"မိုက်ခရိုဖုန်း"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"အာရုံခံကိရိယာများ ပိတ်ထားသည်"</string>
<string name="device_services" msgid="1549944177856658705">"စက်ပစ္စည်းဝန်ဆောင်မှုများ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ခေါင်းစဉ် မရှိပါ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 26268301333c..5e29ca48bf7b 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Innstillinger"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Greit"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI-heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> bruker <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apper bruker <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" og "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"posisjon"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorer er av"</string>
<string name="device_services" msgid="1549944177856658705">"Enhetstjenester"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen tittel"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d962af76ec41..098e0b1911d1 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"सेटिङहरू"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"बुझेँ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ले तपाईंको <xliff:g id="TYPES_LIST">%2$s</xliff:g> प्रयोग गर्दै छ।"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"एपहरूले तपाईंको <xliff:g id="TYPES_LIST">%s</xliff:g> प्रयोग गर्दै छन्‌।"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" र "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"क्यामेरा"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"स्थान"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"माइक्रोफोन"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"सेन्सरहरू निष्क्रिय छन्"</string>
<string name="device_services" msgid="1549944177856658705">"यन्त्रका सेवाहरू"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"शीर्षक छैन"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 7a4de7516e05..e5012182eadc 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -433,7 +433,7 @@
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Starten"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stoppen"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Apparaat"</string>
- <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Veeg omhoog om te schakelen tussen apps"</string>
+ <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swipe omhoog om te schakelen tussen apps"</string>
<string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Sleep naar rechts om snel tussen apps te schakelen"</string>
<string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Overzicht in-/uitschakelen"</string>
<string name="expanded_header_battery_charged" msgid="5307907517976548448">"Opgeladen"</string>
@@ -452,12 +452,12 @@
<string name="keyguard_more_overflow_text" msgid="5819512373606638727">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="7248696377626341060">"Minder urgente meldingen onderaan"</string>
<string name="notification_tap_again" msgid="4477318164947497249">"Tik nog eens om te openen"</string>
- <string name="keyguard_unlock" msgid="8031975796351361601">"Veeg omhoog om te openen"</string>
- <string name="keyguard_retry" msgid="886802522584053523">"Veeg omhoog om het opnieuw te proberen"</string>
+ <string name="keyguard_unlock" msgid="8031975796351361601">"Swipe omhoog om te openen"</string>
+ <string name="keyguard_retry" msgid="886802522584053523">"Swipe omhoog om het opnieuw te proberen"</string>
<string name="do_disclosure_generic" msgid="4896482821974707167">"Dit apparaat is eigendom van je organisatie"</string>
<string name="do_disclosure_with_name" msgid="2091641464065004091">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
- <string name="phone_hint" msgid="6682125338461375925">"Vegen voor telefoon"</string>
- <string name="voice_hint" msgid="7476017460191291417">"Vegen vanaf pictogram voor spraakassistent"</string>
+ <string name="phone_hint" msgid="6682125338461375925">"Swipen voor telefoon"</string>
+ <string name="voice_hint" msgid="7476017460191291417">"Swipen vanaf icoon voor spraakassistent"</string>
<string name="camera_hint" msgid="4519495795000658637">"Vegen voor camera"</string>
<string name="interruption_level_none_with_warning" msgid="8394434073508145437">"Helemaal stil. Hiermee worden schermlezers ook op stil gezet."</string>
<string name="interruption_level_none" msgid="219484038314193379">"Helemaal stil"</string>
@@ -566,7 +566,7 @@
<string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string>
<string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"Vertrouwde gegevens openen"</string>
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Je beheerder heeft netwerkregistratie ingeschakeld, waarmee verkeer op je apparaat wordt bijgehouden.\n\nNeem contact op met je beheerder voor meer informatie."</string>
- <string name="monitoring_description_vpn" msgid="1685428000684586870">"Je hebt een app toestemming gegeven voor het instellen van een VPN-verbinding.\n\nMet deze app kan je apparaat- en netwerkactiviteit worden gecontroleerd, inclusief e-mails, apps en websites."</string>
+ <string name="monitoring_description_vpn" msgid="1685428000684586870">"Je hebt een app rechten gegeven voor het instellen van een VPN-verbinding.\n\nMet deze app kan je apparaat- en netwerkactiviteit worden gecontroleerd, inclusief e-mails, apps en websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Je werkprofiel wordt beheerd door <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nJe beheerder kan je netwerkactiviteit controleren, inclusief e-mails, apps en websites.\n\nNeem contact op met je beheerder voor meer informatie.\n\nJe bent ook verbonden met een VPN, waarmee je netwerkactiviteit kan worden gecontroleerd."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Je bent verbonden met <xliff:g id="APPLICATION">%1$s</xliff:g>, waarmee je netwerkactiviteit (waaronder e-mails, apps en websites) kan worden bijgehouden."</string>
@@ -644,7 +644,7 @@
<string name="output_service_bt_wifi" msgid="7186882540475524124">"Bluetooth en wifi"</string>
<string name="system_ui_tuner" msgid="1471348823289954729">"Systeem-UI-tuner"</string>
<string name="show_battery_percentage" msgid="6235377891802910455">"Percentage ingebouwde batterij weergeven"</string>
- <string name="show_battery_percentage_summary" msgid="9053024758304102915">"Accupercentage weergeven in het pictogram op de statusbalk wanneer er niet wordt opgeladen"</string>
+ <string name="show_battery_percentage_summary" msgid="9053024758304102915">"Accupercentage weergeven in het icoon op de statusbalk wanneer er niet wordt opgeladen"</string>
<string name="quick_settings" msgid="6211774484997470203">"Snelle instellingen"</string>
<string name="status_bar" msgid="4357390266055077437">"Statusbalk"</string>
<string name="overview" msgid="3522318590458536816">"Overzicht"</string>
@@ -861,8 +861,8 @@
<string name="accessibility_key" msgid="3471162841552818281">"Aangepaste navigatieknop"</string>
<string name="left_keycode" msgid="8211040899126637342">"Toetscode links"</string>
<string name="right_keycode" msgid="2480715509844798438">"Toetscode rechts"</string>
- <string name="left_icon" msgid="5036278531966897006">"Pictogram links"</string>
- <string name="right_icon" msgid="1103955040645237425">"Pictogram rechts"</string>
+ <string name="left_icon" msgid="5036278531966897006">"Icoon links"</string>
+ <string name="right_icon" msgid="1103955040645237425">"Icoon rechts"</string>
<string name="drag_to_add_tiles" msgid="8933270127508303672">"Houd vast en sleep om tegels toe te voegen"</string>
<string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Houd vast en sleep om tegels opnieuw in te delen"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"Sleep hier naartoe om te verwijderen"</string>
@@ -872,12 +872,12 @@
<string-array name="clock_options">
<item msgid="3986445361435142273">"Uren, minuten en seconden weergeven"</item>
<item msgid="1271006222031257266">"Uren en minuten weergeven (standaard)"</item>
- <item msgid="6135970080453877218">"Dit pictogram niet weergeven"</item>
+ <item msgid="6135970080453877218">"Dit icoon niet weergeven"</item>
</string-array>
<string-array name="battery_options">
<item msgid="7714004721411852551">"Percentage altijd weergeven"</item>
<item msgid="3805744470661798712">"Percentage weergeven tijdens opladen (standaard)"</item>
- <item msgid="8619482474544321778">"Dit pictogram niet weergeven"</item>
+ <item msgid="8619482474544321778">"Dit icoon niet weergeven"</item>
</string-array>
<string name="tuner_low_priority" msgid="8412666814123009820">"Pictogrammen voor meldingen met lage prioriteit weergeven"</string>
<string name="other" msgid="429768510980739978">"Overig"</string>
@@ -970,7 +970,7 @@
<string name="mobile_data_disable_title" msgid="5366476131671617790">"Mobiele data uitzetten?"</string>
<string name="mobile_data_disable_message" msgid="8604966027899770415">"Je hebt dan geen toegang meer tot data of internet via <xliff:g id="CARRIER">%s</xliff:g>. Internet is alleen nog beschikbaar via wifi."</string>
<string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"je provider"</string>
- <string name="touch_filtered_warning" msgid="8119511393338714836">"Aangezien een app een toestemmingsverzoek afdekt, kan Instellingen je reactie niet verifiëren."</string>
+ <string name="touch_filtered_warning" msgid="8119511393338714836">"Aangezien een app een rechtenverzoek afdekt, kan Instellingen je reactie niet verifiëren."</string>
<string name="slice_permission_title" msgid="3262615140094151017">"<xliff:g id="APP_0">%1$s</xliff:g> toestaan om segmenten van <xliff:g id="APP_2">%2$s</xliff:g> weer te geven?"</string>
<string name="slice_permission_text_1" msgid="6675965177075443714">"- Deze kan informatie lezen van <xliff:g id="APP">%1$s</xliff:g>"</string>
<string name="slice_permission_text_2" msgid="6758906940360746983">"- Deze kan acties uitvoeren in <xliff:g id="APP">%1$s</xliff:g>"</string>
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Instellingen"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> gebruikt je <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Apps gebruiken je <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" en "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"locatie"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microfoon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensoren uit"</string>
<string name="device_services" msgid="1549944177856658705">"Apparaatservices"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Geen titel"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index e112f446acb1..bfd4bd77df31 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ସେଟିଂସ୍"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ବୁଝିଗଲି"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ହିପ୍ ଡମ୍ପ୍ କରନ୍ତୁ"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ଆପଣଙ୍କ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି।"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ଆପ୍ଲିକେସନ୍‍ଗୁଡିକ ଆପଣଙ୍କ <xliff:g id="TYPES_LIST">%s</xliff:g> ବ୍ୟବହାର କରୁଛନ୍ତି।"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ଏବଂ "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"କ୍ୟାମେରା"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ଲୋକେସନ୍‍"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"ମାଇକ୍ରୋଫୋନ୍"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ସେନ୍ସର୍‍ଗୁଡ଼ିକ ବନ୍ଦ ଅଛି"</string>
<string name="device_services" msgid="1549944177856658705">"ଡିଭାଇସ୍‍ ସେବାଗୁଡିକ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"କୌଣସି ଶୀର୍ଷକ ନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 6ac824b59e6b..1df919286a95 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ਸੈਟਿੰਗਾਂ"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ਸਮਝ ਲਿਆ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI ਹੀਪ ਡੰਪ ਕਰੋ"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ਤੁਹਾਡੇ <xliff:g id="TYPES_LIST">%2$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ਐਪਲੀਕੇਸ਼ਨਾਂ ਤੁਹਾਡੇ <xliff:g id="TYPES_LIST">%s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ।"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ਅਤੇ "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"ਕੈਮਰਾ"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ਟਿਕਾਣਾ"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ਸੈਂਸਰ ਬੰਦ ਕਰੋ"</string>
<string name="device_services" msgid="1549944177856658705">"ਡੀਵਾਈਸ ਸੇਵਾਵਾਂ"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index f5ef1a045bdd..56fcbb20f5b5 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -995,6 +995,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ustawienia"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Zrzut stosu SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Aplikacja <xliff:g id="APP">%1$s</xliff:g> używa: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacje używają: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" i "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"aparat"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"lokalizacja"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Wyłącz czujniki"</string>
<string name="device_services" msgid="1549944177856658705">"Usługi urządzenia"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez tytułu"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index c8eaa0ddc4fb..88f603200dc5 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configurações"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ok"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Despejar heap SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplicativos estão usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"câmera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microfone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desativados"</string>
<string name="device_services" msgid="1549944177856658705">"Serviços do dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 341efff0e4cd..5fdb2853551d 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Definições"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Despejar pilha SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"A app <xliff:g id="APP">%1$s</xliff:g> está a utilizar o(a) <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"As aplicações estão a utilizar o(a) <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"câmara"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microfone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desativados"</string>
<string name="device_services" msgid="1549944177856658705">"Serviços do dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
@@ -1015,7 +1022,7 @@
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"As conversas prioritárias irão:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Aparecer na parte superior da secção de conversas."</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Mostrar a imagem do perfil no ecrã de bloqueio."</string>
- <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecem como balões flutuantes por cima de apps."</string>
+ <string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecer como balões flutuantes por cima de apps."</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interrompem o modo Não incomodar."</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"OK"</string>
<string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Definições"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c8eaa0ddc4fb..88f603200dc5 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Configurações"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ok"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Despejar heap SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"O app <xliff:g id="APP">%1$s</xliff:g> está usando <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplicativos estão usando <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" e "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"câmera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"localização"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microfone"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensores desativados"</string>
<string name="device_services" msgid="1549944177856658705">"Serviços do dispositivo"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Sem título"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 08542c02c2e0..d5eecc76144c 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -990,6 +990,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Setări"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Extrageți memoria SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> folosește <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplicațiile folosesc <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" și "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"cameră foto"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"locație"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"microfon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzori dezactivați"</string>
<string name="device_services" msgid="1549944177856658705">"Servicii pentru dispozitiv"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Fără titlu"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 12c489e08e41..50850225c891 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -995,6 +995,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Открыть настройки"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"ОК"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Передача SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"В приложении \"<xliff:g id="APP">%1$s</xliff:g>\" используется <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"В приложениях используется <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"камера"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"местоположение"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчики отключены"</string>
<string name="device_services" msgid="1549944177856658705">"Сервисы устройства"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без названия"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 412050f4bb7f..ff7e816f8336 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"සැකසීම්"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"තේරුණා"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ඔබේ <xliff:g id="TYPES_LIST">%2$s</xliff:g> භාවිත කරමින් සිටී."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"යෙදුම් ඔබේ <xliff:g id="TYPES_LIST">%s</xliff:g> භාවිත කරමින් සිටී."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" සහ "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"කැමරාව"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ස්ථානය"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"මයික්‍රෝෆෝනය"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"සංවේදක ක්‍රියාවිරහිතයි"</string>
<string name="device_services" msgid="1549944177856658705">"උපාංග සේවා"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"මාතෘකාවක් නැත"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f657d4fe71e7..a86da967ab62 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -995,6 +995,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Nastavenia"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Dobre"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> používa zoznam <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikácie používajú zoznam <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" a "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparát"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"poloha"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofón"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Senzory sú vypnuté"</string>
<string name="device_services" msgid="1549944177856658705">"Služby zariadenia"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Bez názvu"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index e1e5852098b9..b9039d8c3cb9 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -995,6 +995,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Nastavitve"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"V redu"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Izvoz kopice SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Aplikacija <xliff:g id="APP">%1$s</xliff:g> uporablja <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacije uporabljajo <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" in "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"fotoaparat"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"lokacijo"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Izklop za tipala"</string>
<string name="device_services" msgid="1549944177856658705">"Storitve naprave"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Brez naslova"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 64d7a2ecac52..2972c5383bee 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Cilësimet"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"E kuptova"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Hidh grumbullin SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> po përdor <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Aplikacionet po përdorin <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" dhe "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamerën"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"vendndodhjen"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofonin"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorët joaktivë"</string>
<string name="device_services" msgid="1549944177856658705">"Shërbimet e pajisjes"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Pa titull"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index fd6f57e64113..77cbb96b3691 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -990,6 +990,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Подешавања"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Важи"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Издвоји SysUI мем."</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> користи <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Апликације користе <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" и "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"камеру"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"локацију"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"микрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Сензори су искључени"</string>
<string name="device_services" msgid="1549944177856658705">"Услуге за уређаје"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без наслова"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index f96dd27aba6d..c7eda4567a68 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Inställningar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI-heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="TYPES_LIST">%2$s</xliff:g> används av <xliff:g id="APP">%1$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"<xliff:g id="TYPES_LIST">%s</xliff:g> används av appar."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" och "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"plats"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorer har inaktiverats"</string>
<string name="device_services" msgid="1549944177856658705">"Enhetstjänster"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Ingen titel"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8b8c24983e98..2804f2f1e106 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Mipangilio"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Nimeelewa"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> inatumia <xliff:g id="TYPES_LIST">%2$s</xliff:g> yako."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Programu zinatumia <xliff:g id="TYPES_LIST">%s</xliff:g> yako."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" na "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"mahali"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"maikrofoni"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Umezima vitambuzi"</string>
<string name="device_services" msgid="1549944177856658705">"Huduma za Kifaa"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Wimbo hauna jina"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index b97e266850c6..ee176fa3c57d 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"அமைப்புகள்"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"சரி"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"உங்கள் <xliff:g id="TYPES_LIST">%2$s</xliff:g>ஐ <xliff:g id="APP">%1$s</xliff:g> ஆப்ஸ் பயன்படுத்துகிறது."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"உங்கள் <xliff:g id="TYPES_LIST">%s</xliff:g> ஆகியவற்றை ஆப்ஸ் பயன்படுத்துகின்றன."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" மற்றும் "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"கேமரா"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"இருப்பிடம்"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"மைக்ரோஃபோன்"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"சென்சார்களை ஆஃப் செய்தல்"</string>
<string name="device_services" msgid="1549944177856658705">"சாதன சேவைகள்"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"தலைப்பு இல்லை"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 13319d9719b8..dc5ea1f29fb5 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"సెట్టింగ్‌లు"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"అర్థమైంది"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"డంప్ SysUI హీప్"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> మీ <xliff:g id="TYPES_LIST">%2$s</xliff:g>ని ఉపయోగిస్తోంది."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"అప్లికేషన్‌లు మీ <xliff:g id="TYPES_LIST">%s</xliff:g>ని ఉపయోగిస్తున్నాయి."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" మరియు "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"కెమెరా"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"లొకేషన్"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"మైక్రోఫోన్"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"సెన్సార్‌లు ఆఫ్"</string>
<string name="device_services" msgid="1549944177856658705">"పరికర సేవలు"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"శీర్షిక లేదు"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index e1c0e7e7a614..ba9fd296f607 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"การตั้งค่า"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"รับทราบ"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ใช้<xliff:g id="TYPES_LIST">%2$s</xliff:g>ของคุณอยู่"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"หลายแอปพลิเคชันใช้<xliff:g id="TYPES_LIST">%s</xliff:g>ของคุณอยู่"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" และ "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"กล้องถ่ายรูป"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"ตำแหน่ง"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"ไมโครโฟน"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"ปิดเซ็นเซอร์"</string>
<string name="device_services" msgid="1549944177856658705">"บริการของอุปกรณ์"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"ไม่มีชื่อ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 20a34e1ded0d..069438f2caed 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Mga Setting"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Ginagamit ng <xliff:g id="APP">%1$s</xliff:g> ang iyong <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Ginagamit ng mga application ang iyong <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" at "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"camera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"lokasyon"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikropono"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Naka-off ang mga sensor"</string>
<string name="device_services" msgid="1549944177856658705">"Mga Serbisyo ng Device"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Walang pamagat"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 4146f307ac18..649b9af53ff6 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Ayarlar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Anladım"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI Yığın Dökümü"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> şunları kullanıyor: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Uygulamalar şunları kullanıyor: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" ve "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"konum"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensörler kapalı"</string>
<string name="device_services" msgid="1549944177856658705">"Cihaz Hizmetleri"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Başlıksız"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 11eb18cc48d2..6cb3ac8ce915 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -995,6 +995,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Налаштування"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"Додаток <xliff:g id="APP">%1$s</xliff:g> використовує <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Додатки використовують <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" і "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"камеру"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"місце"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"мікрофон"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Датчики вимкнено"</string>
<string name="device_services" msgid="1549944177856658705">"Сервіси на пристрої"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Без назви"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index d7645e9bcb5b..804c33436ea6 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"ترتیبات"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"سمجھ آ گئی"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> آپ کی <xliff:g id="TYPES_LIST">%2$s</xliff:g> کا استعمال کر رہی ہے۔"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"ایپلیکیشنز آپ کی <xliff:g id="TYPES_LIST">%s</xliff:g> کا استعمال کر رہی ہیں۔"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"، "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" اور "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"کیمرا"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"مقام"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"مائیکروفون"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"سینسرز آف ہیں"</string>
<string name="device_services" msgid="1549944177856658705">"آلہ کی سروس"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"کوئی عنوان نہیں ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 1fc4f9bea270..6193d33961e6 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Sozlamalar"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> ishlatmoqda: <xliff:g id="TYPES_LIST">%2$s</xliff:g>."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Ilovalarda ishlatilmoqda: <xliff:g id="TYPES_LIST">%s</xliff:g>."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" va "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"kamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"joylashuv"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"mikrofon"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Sensorlar nofaol"</string>
<string name="device_services" msgid="1549944177856658705">"Qurilma xizmatlari"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Nomsiz"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 8df5ee530210..97ffbc623e02 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Cài đặt"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"Trích xuất bộ nhớ SysUI"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g> đang dùng <xliff:g id="TYPES_LIST">%2$s</xliff:g> của bạn."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Các ứng dụng đang dùng <xliff:g id="TYPES_LIST">%s</xliff:g> của bạn."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" và "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"máy ảnh"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"vị trí"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"micrô"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Tắt cảm biến"</string>
<string name="device_services" msgid="1549944177856658705">"Dịch vụ cho thiết bị"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Không có tiêu đề"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index c51982cddac3..b9b146c9fb4b 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"设置"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"知道了"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"转储 SysUI 堆"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"<xliff:g id="APP">%1$s</xliff:g>正在使用您的<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"有多个应用正在使用您的<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 和 "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"相机"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"位置信息"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"麦克风"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"已关闭传感器"</string>
<string name="device_services" msgid="1549944177856658705">"设备服务"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"无标题"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index aa9945fbd956..f2cb185078b5 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"設定"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"知道了"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"轉儲 SysUI 堆"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"「<xliff:g id="APP">%1$s</xliff:g>」正在使用<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"有多個應用程式正在使用<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 和 "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"相機"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"位置"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"麥克風"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"感應器已關閉"</string>
<string name="device_services" msgid="1549944177856658705">"裝置服務"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 92bdfc3f1219..69b52946d698 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"設定"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"我知道了"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"傾印 SysUI 記憶體快照"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"「<xliff:g id="APP">%1$s</xliff:g>」正在使用<xliff:g id="TYPES_LIST">%2$s</xliff:g>。"</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"有多個應用程式正在使用<xliff:g id="TYPES_LIST">%s</xliff:g>。"</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">"、 "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" 和 "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"相機"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"位置"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"麥克風"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"已關閉感應器"</string>
<string name="device_services" msgid="1549944177856658705">"裝置服務"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"無標題"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 4ae126799141..5b899f93e5f9 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -985,6 +985,13 @@
<string name="open_saver_setting_action" msgid="2111461909782935190">"Izilungiselelo"</string>
<string name="auto_saver_okay_action" msgid="7815925750741935386">"Ngiyezwa"</string>
<string name="heap_dump_tile_name" msgid="2464189856478823046">"I-Dump SysUI Heap"</string>
+ <string name="ongoing_privacy_chip_content_single_app" msgid="2969750601815230385">"I-<xliff:g id="APP">%1$s</xliff:g> isebenzisa i-<xliff:g id="TYPES_LIST">%2$s</xliff:g> yakho."</string>
+ <string name="ongoing_privacy_chip_content_multiple_apps" msgid="8341216022442383954">"Izinhlelo zokusebenza zisebenzisa i-<xliff:g id="TYPES_LIST">%s</xliff:g> yakho."</string>
+ <string name="ongoing_privacy_dialog_separator" msgid="1866222499727706187">", "</string>
+ <string name="ongoing_privacy_dialog_last_separator" msgid="5615876114268009767">" kanye "</string>
+ <string name="privacy_type_camera" msgid="7974051382167078332">"ikhamera"</string>
+ <string name="privacy_type_location" msgid="7991481648444066703">"indawo"</string>
+ <string name="privacy_type_microphone" msgid="9136763906797732428">"imakrofoni"</string>
<string name="sensor_privacy_mode" msgid="4462866919026513692">"Izinzwa zivaliwe"</string>
<string name="device_services" msgid="1549944177856658705">"Amasevisi edivayisi"</string>
<string name="music_controls_no_title" msgid="4166497066552290938">"Asikho isihloko"</string>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index f407a8dcc57f..fa620df12b87 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -161,10 +161,6 @@
<!-- The number of milliseconds to extend ambient pulse by when prompted (e.g. on touch) -->
<integer name="ambient_notification_extension_time">10000</integer>
- <!-- In multi-window, determines whether the stack where recents lives should grow from
- the smallest position when being launched. -->
- <bool name="recents_grow_in_multiwindow">true</bool>
-
<!-- Animation duration when using long press on recents to dock -->
<integer name="long_press_dock_anim_duration">250</integer>
@@ -522,6 +518,8 @@
<!-- Defines the blacklist for system icons. That is to say, the icons in the status bar that
are part of the blacklist are never displayed. Each item in the blacklist must be a string
defined in core/res/res/config.xml to properly blacklist the icon.
+
+ TODO: See if we can rename this config variable.
-->
<string-array name="config_statusBarIconBlackList" translatable="false">
<item>@*android:string/status_bar_rotate</item>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8b6543ac73bd..77d3f4513957 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2838,4 +2838,9 @@
<string name="udfps_hbm_enable_command" translatable="false"></string>
<!-- Device-specific payload for disabling the high-brightness mode -->
<string name="udfps_hbm_disable_command" translatable="false"></string>
+
+ <!-- One-Handed Tutorial title [CHAR LIMIT=60] -->
+ <string name="one_handed_tutorial_title">Using one-handed mode</string>
+ <!-- One-Handed Tutorial description [CHAR LIMIT=NONE] -->
+ <string name="one_handed_tutorial_description">To exit, swipe up from the bottom of the screen or tap anywhere above the app</string>
</resources>
diff --git a/packages/SystemUI/res/xml/one_handed_tutorial.xml b/packages/SystemUI/res/xml/one_handed_tutorial.xml
new file mode 100644
index 000000000000..dc54caf0f14a
--- /dev/null
+++ b/packages/SystemUI/res/xml/one_handed_tutorial.xml
@@ -0,0 +1,67 @@
+<?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
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/one_handed_tutorial_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal | center_vertical"
+ android:background="@android:color/transparent">
+
+ <ImageView
+ android:id="@+id/one_handed_tutorial_image"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="0dp"
+ android:gravity="center_horizontal"
+ android:src="@drawable/one_handed_tutorial"
+ android:scaleType="centerInside" />
+
+ <TextView
+ android:id="@+id/one_handed_tutorial_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="0dp"
+ android:gravity="center_horizontal"
+ android:textAlignment="center"
+ android:fontFamily="google-sans-medium"
+ android:text="@string/one_handed_tutorial_title"
+ android:textSize="16sp"
+ android:textStyle="bold"
+ android:textColor="@android:color/white"/>
+
+ <TextView
+ android:id="@+id/one_handed_tutorial_description"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="6dp"
+ android:layout_marginBottom="0dp"
+ android:layout_marginStart="86dp"
+ android:layout_marginEnd="86dp"
+ android:gravity="center_horizontal"
+ android:fontFamily="roboto-regular"
+ android:text="@string/one_handed_tutorial_description"
+ android:textAlignment="center"
+ android:textSize="14sp"
+ android:textStyle="normal"
+ android:alpha="0.7"
+ android:textColor="@android:color/white"/>
+</LinearLayout>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 158763a9ddab..ecf1c2c91770 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -1,10 +1,7 @@
package com.android.keyguard;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
-
import android.animation.Animator;
import android.animation.ValueAnimator;
-import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Paint;
import android.graphics.Paint.Style;
@@ -24,16 +21,10 @@ import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextClock;
-import androidx.annotation.VisibleForTesting;
-
import com.android.internal.colorextraction.ColorExtractor;
-import com.android.internal.colorextraction.ColorExtractor.OnColorsChangedListener;
-import com.android.keyguard.clock.ClockManager;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ClockPlugin;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
@@ -42,16 +33,12 @@ import java.io.PrintWriter;
import java.util.Arrays;
import java.util.TimeZone;
-import javax.inject.Inject;
-import javax.inject.Named;
-
/**
* Switch to show plugin clock when plugin is connected, otherwise it will show default clock.
*/
public class KeyguardClockSwitch extends RelativeLayout {
private static final String TAG = "KeyguardClockSwitch";
- private static final boolean CUSTOM_CLOCKS_ENABLED = true;
/**
* Animation fraction when text is transitioned to/from bold.
@@ -59,21 +46,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
private static final float TO_BOLD_TRANSITION_FRACTION = 0.7f;
/**
- * Controller used to track StatusBar state to know when to show the big_clock_container.
- */
- private final StatusBarStateController mStatusBarStateController;
-
- /**
- * Color extractor used to apply colors from wallpaper to custom clock faces.
- */
- private final SysuiColorExtractor mSysuiColorExtractor;
-
- /**
- * Manager used to know when to show a custom clock face.
- */
- private final ClockManager mClockManager;
-
- /**
* Layout transition that scales the default clock face.
*/
private final Transition mTransition;
@@ -130,42 +102,8 @@ public class KeyguardClockSwitch extends RelativeLayout {
private boolean mSupportsDarkText;
private int[] mColorPalette;
- /**
- * Track the state of the status bar to know when to hide the big_clock_container.
- */
- private int mStatusBarState;
-
- private final StatusBarStateController.StateListener mStateListener =
- new StatusBarStateController.StateListener() {
- @Override
- public void onStateChanged(int newState) {
- mStatusBarState = newState;
- updateBigClockVisibility();
- }
- };
-
- private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
-
- /**
- * Listener for changes to the color palette.
- *
- * The color palette changes when the wallpaper is changed.
- */
- private final OnColorsChangedListener mColorsListener = (extractor, which) -> {
- if ((which & WallpaperManager.FLAG_LOCK) != 0) {
- updateColors();
- }
- };
-
- @Inject
- public KeyguardClockSwitch(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
- StatusBarStateController statusBarStateController, SysuiColorExtractor colorExtractor,
- ClockManager clockManager) {
+ public KeyguardClockSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
- mStatusBarStateController = statusBarStateController;
- mStatusBarState = mStatusBarStateController.getState();
- mSysuiColorExtractor = colorExtractor;
- mClockManager = clockManager;
mClockTransition = new ClockVisibilityTransition().setCutoff(
1 - TO_BOLD_TRANSITION_FRACTION);
@@ -197,29 +135,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
}
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- if (CUSTOM_CLOCKS_ENABLED) {
- mClockManager.addOnClockChangedListener(mClockChangedListener);
- }
- mStatusBarStateController.addCallback(mStateListener);
- mSysuiColorExtractor.addOnColorsChangedListener(mColorsListener);
- updateColors();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- if (CUSTOM_CLOCKS_ENABLED) {
- mClockManager.removeOnClockChangedListener(mClockChangedListener);
- }
- mStatusBarStateController.removeCallback(mStateListener);
- mSysuiColorExtractor.removeOnColorsChangedListener(mColorsListener);
- setClockPlugin(null);
- }
-
- private void setClockPlugin(ClockPlugin plugin) {
+ void setClockPlugin(ClockPlugin plugin, int statusBarState) {
// Disconnect from existing plugin.
if (mClockPlugin != null) {
View smallClockView = mClockPlugin.getView();
@@ -228,7 +144,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
if (mBigClockContainer != null) {
mBigClockContainer.removeAllViews();
- updateBigClockVisibility();
+ updateBigClockVisibility(statusBarState);
}
mClockPlugin.onDestroyView();
mClockPlugin = null;
@@ -256,7 +172,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
View bigClockView = plugin.getBigClockView();
if (bigClockView != null && mBigClockContainer != null) {
mBigClockContainer.addView(bigClockView);
- updateBigClockVisibility();
+ updateBigClockVisibility(statusBarState);
}
// Hide default clock.
if (!plugin.shouldShowStatusArea()) {
@@ -275,7 +191,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
/**
* Set container for big clock face appearing behind NSSL and KeyguardStatusView.
*/
- public void setBigClockContainer(ViewGroup container) {
+ public void setBigClockContainer(ViewGroup container, int statusBarState) {
if (mClockPlugin != null && container != null) {
View bigClockView = mClockPlugin.getBigClockView();
if (bigClockView != null) {
@@ -283,7 +199,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
}
mBigClockContainer = container;
- updateBigClockVisibility();
+ updateBigClockVisibility(statusBarState);
}
/**
@@ -407,9 +323,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
}
- private void updateColors() {
- ColorExtractor.GradientColors colors = mSysuiColorExtractor.getColors(
- WallpaperManager.FLAG_LOCK);
+ void updateColors(ColorExtractor.GradientColors colors) {
mSupportsDarkText = colors.supportsDarkText();
mColorPalette = colors.getColorPalette();
if (mClockPlugin != null) {
@@ -417,12 +331,12 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
}
- private void updateBigClockVisibility() {
+ void updateBigClockVisibility(int statusBarState) {
if (mBigClockContainer == null) {
return;
}
- final boolean inDisplayState = mStatusBarState == StatusBarState.KEYGUARD
- || mStatusBarState == StatusBarState.SHADE_LOCKED;
+ final boolean inDisplayState = statusBarState == StatusBarState.KEYGUARD
+ || statusBarState == StatusBarState.SHADE_LOCKED;
final int visibility = !mShowingHeader && inDisplayState
&& mBigClockContainer.getChildCount() != 0 ? View.VISIBLE : View.GONE;
if (mBigClockContainer.getVisibility() != visibility) {
@@ -506,16 +420,6 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
}
- @VisibleForTesting(otherwise = VisibleForTesting.NONE)
- ClockManager.ClockChangedListener getClockChangedListener() {
- return mClockChangedListener;
- }
-
- @VisibleForTesting(otherwise = VisibleForTesting.NONE)
- StatusBarStateController.StateListener getStateListener() {
- return mStateListener;
- }
-
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardClockSwitch:");
pw.println(" mClockPlugin: " + mClockPlugin);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
new file mode 100644
index 000000000000..f17f1ca797e0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -0,0 +1,119 @@
+/*
+ * 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.keyguard;
+
+import android.app.WallpaperManager;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.colorextraction.ColorExtractor;
+import com.android.keyguard.clock.ClockManager;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+
+import javax.inject.Inject;
+
+/**
+ * Injectable controller for {@link KeyguardClockSwitch}.
+ */
+public class KeyguardClockSwitchController {
+ private static final boolean CUSTOM_CLOCKS_ENABLED = true;
+
+ private final StatusBarStateController mStatusBarStateController;
+ private final SysuiColorExtractor mColorExtractor;
+ private final ClockManager mClockManager;
+ private KeyguardClockSwitch mView;
+
+ private final StatusBarStateController.StateListener mStateListener =
+ new StatusBarStateController.StateListener() {
+ @Override
+ public void onStateChanged(int newState) {
+ mView.updateBigClockVisibility(newState);
+ }
+ };
+
+ /**
+ * Listener for changes to the color palette.
+ *
+ * The color palette changes when the wallpaper is changed.
+ */
+ private final ColorExtractor.OnColorsChangedListener mColorsListener = (extractor, which) -> {
+ if ((which & WallpaperManager.FLAG_LOCK) != 0) {
+ mView.updateColors(getGradientColors());
+ }
+ };
+
+ private ClockManager.ClockChangedListener mClockChangedListener = this::setClockPlugin;
+
+ private final View.OnAttachStateChangeListener mOnAttachStateChangeListener =
+ new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ if (CUSTOM_CLOCKS_ENABLED) {
+ mClockManager.addOnClockChangedListener(mClockChangedListener);
+ }
+ mStatusBarStateController.addCallback(mStateListener);
+ mColorExtractor.addOnColorsChangedListener(mColorsListener);
+ mView.updateColors(getGradientColors());
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ if (CUSTOM_CLOCKS_ENABLED) {
+ mClockManager.removeOnClockChangedListener(mClockChangedListener);
+ }
+ mStatusBarStateController.removeCallback(mStateListener);
+ mColorExtractor.removeOnColorsChangedListener(mColorsListener);
+ mView.setClockPlugin(null, mStatusBarStateController.getState());
+ }
+ };
+
+ @Inject
+ public KeyguardClockSwitchController(StatusBarStateController statusBarStateController,
+ SysuiColorExtractor colorExtractor, ClockManager clockManager) {
+ mStatusBarStateController = statusBarStateController;
+ mColorExtractor = colorExtractor;
+ mClockManager = clockManager;
+ }
+
+ /**
+ * Attach the controller to the view it relates to.
+ */
+ public void attach(KeyguardClockSwitch view) {
+ mView = view;
+ if (mView.isAttachedToWindow()) {
+ mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
+ }
+ mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
+ }
+
+ /**
+ * Set container for big clock face appearing behind NSSL and KeyguardStatusView.
+ */
+ public void setBigClockContainer(ViewGroup bigClockContainer) {
+ mView.setBigClockContainer(bigClockContainer, mStatusBarStateController.getState());
+ }
+
+ private void setClockPlugin(ClockPlugin plugin) {
+ mView.setClockPlugin(plugin, mStatusBarStateController.getState());
+ }
+
+ private ColorExtractor.GradientColors getGradientColors() {
+ return mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 76adf04b21e7..1c47aa0151f0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -141,7 +141,7 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView {
// Sending empty PIN here to query the number of remaining PIN attempts
new CheckSimPin("", mSubId) {
void onSimCheckResponse(final PinResult result) {
- Log.d(LOG_TAG, "onSimCheckResponse " + " dummy One result "
+ Log.d(LOG_TAG, "onSimCheckResponse " + " empty One result "
+ result.toString());
if (result.getAttemptsRemaining() >= 0) {
mRemainingAttempts = result.getAttemptsRemaining();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index a84664ceee3d..5148dd709026 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -195,7 +195,7 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView {
void onSimLockChangedResponse(final PinResult result) {
if (result == null) Log.e(LOG_TAG, "onSimCheckResponse, pin result is NULL");
else {
- Log.d(LOG_TAG, "onSimCheckResponse " + " dummy One result "
+ Log.d(LOG_TAG, "onSimCheckResponse " + " empty One result "
+ result.toString());
if (result.getAttemptsRemaining() >= 0) {
mRemainingAttempts = result.getAttemptsRemaining();
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 58698151b655..521bb8d58c2b 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -225,7 +225,7 @@ public class BatteryMeterView extends LinearLayout implements
}
Dependency.get(TunerService.class)
- .addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ .addTunable(this, StatusBarIconController.ICON_HIDE_LIST);
mIsSubscribedForTunerUpdates = true;
}
@@ -278,8 +278,8 @@ public class BatteryMeterView extends LinearLayout implements
@Override
public void onTuningChanged(String key, String newValue) {
- if (StatusBarIconController.ICON_BLACKLIST.equals(key)) {
- ArraySet<String> icons = StatusBarIconController.getIconBlacklist(
+ if (StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
+ ArraySet<String> icons = StatusBarIconController.getIconHideList(
getContext(), newValue);
setVisibility(icons.contains(mSlotBattery) ? View.GONE : View.VISIBLE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/DisplayIdIndexSupplier.java b/packages/SystemUI/src/com/android/systemui/accessibility/DisplayIdIndexSupplier.java
index 769a344eedac..d5aac1a95847 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/DisplayIdIndexSupplier.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/DisplayIdIndexSupplier.java
@@ -60,6 +60,20 @@ abstract class DisplayIdIndexSupplier<T> {
return instance;
}
+ /**
+ * Gets the object by the element index.
+ *
+ * <p> If the index is bigger than the array size, an {@link ArrayIndexOutOfBoundsException} is
+ * thrown for apps targeting {@link android.os.Build.VERSION_CODES#Q} and later </p>
+ *
+ * @param index the element index
+ * @return T
+ * @see SparseArray#valueAt(int)
+ */
+ public T valueAt(int index) {
+ return mSparseArray.valueAt(index);
+ }
+
@NonNull
protected abstract T createInstance(Display display);
@@ -78,4 +92,13 @@ abstract class DisplayIdIndexSupplier<T> {
public void clear() {
mSparseArray.clear();
}
+
+ /**
+ * Gets the element size.
+ *
+ * @return size of all elements
+ */
+ public int getSize() {
+ return mSparseArray.size();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index 68a0a65ef50f..34f721c94ed2 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -18,6 +18,7 @@ package com.android.systemui.accessibility;
import android.annotation.NonNull;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.graphics.PixelFormat;
import android.provider.Settings;
import android.view.Gravity;
@@ -102,6 +103,14 @@ class MagnificationModeSwitch {
.start();
}
+ void onConfigurationChanged(int configDiff) {
+ if ((configDiff & ActivityInfo.CONFIG_DENSITY) == 0) {
+ return;
+ }
+ applyResourcesValues();
+ mImageView.setImageResource(getIconResId(mMagnificationMode));
+ }
+
private void toggleMagnificationMode() {
final int newMode =
mMagnificationMode ^ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
@@ -112,7 +121,7 @@ class MagnificationModeSwitch {
}
private static ImageView createView(Context context) {
- ImageView imageView = new ImageView(context);
+ ImageView imageView = new ImageView(context);
imageView.setClickable(true);
imageView.setFocusable(true);
imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java
index ffc70bcf63d0..fe07ab67c707 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/ModeSwitchesController.java
@@ -36,7 +36,7 @@ import javax.inject.Singleton;
@Singleton
public class ModeSwitchesController {
- private final SwitchSupplier mSwitchSupplier;
+ private final DisplayIdIndexSupplier<MagnificationModeSwitch> mSwitchSupplier;
public ModeSwitchesController(Context context) {
mSwitchSupplier = new SwitchSupplier(context,
@@ -44,7 +44,7 @@ public class ModeSwitchesController {
}
@VisibleForTesting
- ModeSwitchesController(SwitchSupplier switchSupplier) {
+ ModeSwitchesController(DisplayIdIndexSupplier<MagnificationModeSwitch> switchSupplier) {
mSwitchSupplier = switchSupplier;
}
@@ -81,8 +81,22 @@ public class ModeSwitchesController {
magnificationModeSwitch.removeButton();
}
- @VisibleForTesting
- static class SwitchSupplier extends DisplayIdIndexSupplier<MagnificationModeSwitch> {
+ /**
+ * Called when the configuration has changed, and it updates magnification button UI.
+ *
+ * @param configDiff a bit mask of the differences between the configurations
+ */
+ @MainThread
+ void onConfigurationChanged(int configDiff) {
+ for (int i = 0; i < mSwitchSupplier.getSize(); i++) {
+ final MagnificationModeSwitch magnificationModeSwitch = mSwitchSupplier.valueAt(i);
+ if (magnificationModeSwitch != null) {
+ magnificationModeSwitch.onConfigurationChanged(configDiff);
+ }
+ }
+ }
+
+ private static class SwitchSupplier extends DisplayIdIndexSupplier<MagnificationModeSwitch> {
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 426e400c9fb9..816bcf8f274b 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -25,6 +25,7 @@ import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
+import android.view.SurfaceControl;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IWindowMagnificationConnection;
import android.view.accessibility.IWindowMagnificationConnectionCallback;
@@ -83,6 +84,9 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
if (mWindowMagnificationController != null) {
mWindowMagnificationController.onConfigurationChanged(configDiff);
}
+ if (mModeSwitchesController != null) {
+ mModeSwitchesController.onConfigurationChanged(configDiff);
+ }
}
@Override
@@ -97,7 +101,7 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
mWindowMagnificationController = new WindowMagnificationController(mContext,
mHandler,
new SfVsyncFrameCallbackProvider(),
- null,
+ null, new SurfaceControl.Transaction(),
this);
}
mWindowMagnificationController.enableWindowMagnification(scale, centerX, centerY);
@@ -136,6 +140,13 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
}
@Override
+ public void onSourceBoundsChanged(int displayId, Rect sourceBounds) {
+ if (mWindowMagnificationConnectionImpl != null) {
+ mWindowMagnificationConnectionImpl.onSourceBoundsChanged(displayId, sourceBounds);
+ }
+ }
+
+ @Override
public void requestWindowMagnificationConnection(boolean connect) {
if (connect) {
setWindowMagnificationConnection();
@@ -225,5 +236,15 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
}
}
}
+
+ void onSourceBoundsChanged(int displayId, Rect sourceBounds) {
+ if (mConnectionCallback != null) {
+ try {
+ mConnectionCallback.onSourceBoundsChanged(displayId, sourceBounds);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to inform source bounds changed", e);
+ }
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 8b6581ff1856..798b751c03ee 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -67,7 +67,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
@Surface.Rotation
private int mRotation;
private final Rect mMagnificationFrame = new Rect();
- private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+ private final SurfaceControl.Transaction mTransaction;
private final WindowManager mWm;
@@ -75,6 +75,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private final Rect mTmpRect = new Rect();
private final Rect mMirrorViewBounds = new Rect();
+ private final Rect mSourceBounds = new Rect();
// The root of the mirrored content
private SurfaceControl mMirrorSurface;
@@ -101,22 +102,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private final Rect mMagnificationFrameBoundary = new Rect();
private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
- private final Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback =
- l -> {
- if (mMirrorView != null) {
- final Rect sourceBounds = getSourceBounds(mMagnificationFrame, mScale);
- mTransaction.setGeometry(mMirrorSurface, sourceBounds, mTmpRect,
- Surface.ROTATION_0).apply();
- }
- };
+ private Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback;
@Nullable
private MirrorWindowControl mMirrorWindowControl;
- WindowMagnificationController(Context context,
- @NonNull Handler handler,
+ WindowMagnificationController(Context context, @NonNull Handler handler,
SfVsyncFrameCallbackProvider sfVsyncFrameProvider,
- MirrorWindowControl mirrorWindowControl,
+ MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction,
@NonNull WindowMagnifierCallback callback) {
mContext = context;
mHandler = handler;
@@ -137,6 +130,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
if (mMirrorWindowControl != null) {
mMirrorWindowControl.setWindowDelegate(this);
}
+ mTransaction = transaction;
setInitialStartBounds();
// Initialize listeners.
@@ -153,6 +147,20 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
mMirrorSurfaceViewLayoutChangeListener =
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom)
-> applyTapExcludeRegion();
+
+ mMirrorViewGeometryVsyncCallback =
+ l -> {
+ if (mMirrorView != null && mMirrorSurface != null) {
+ calculateSourceBounds(mMagnificationFrame, mScale);
+ // The final destination for the magnification surface should be at 0,0
+ // since the ViewRootImpl's position will change
+ mTmpRect.set(0, 0, mMagnificationFrame.width(),
+ mMagnificationFrame.height());
+ mTransaction.setGeometry(mMirrorSurface, mSourceBounds, mTmpRect,
+ Surface.ROTATION_0).apply();
+ mWindowMagnifierCallback.onSourceBoundsChanged(mDisplayId, mSourceBounds);
+ }
+ };
}
private void updateDimensions() {
@@ -350,13 +358,9 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
* Modifies the placement of the mirrored content when the position of mMirrorView is updated.
*/
private void modifyWindowMagnification(SurfaceControl.Transaction t) {
- // The final destination for the magnification surface should be at 0,0 since the
- // ViewRootImpl's position will change
- mTmpRect.set(0, 0, mMagnificationFrame.width(), mMagnificationFrame.height());
-
+ mSfVsyncFrameProvider.postFrameCallback(mMirrorViewGeometryVsyncCallback);
updateMirrorViewLayout();
- mSfVsyncFrameProvider.postFrameCallback(mMirrorViewGeometryVsyncCallback);
}
/**
@@ -420,14 +424,14 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
* Calculates the desired source bounds. This will be the area under from the center of the
* displayFrame, factoring in scale.
*/
- private Rect getSourceBounds(Rect displayFrame, float scale) {
+ private void calculateSourceBounds(Rect displayFrame, float scale) {
int halfWidth = displayFrame.width() / 2;
int halfHeight = displayFrame.height() / 2;
int left = displayFrame.left + (halfWidth - (int) (halfWidth / scale));
int right = displayFrame.right - (halfWidth - (int) (halfWidth / scale));
int top = displayFrame.top + (halfHeight - (int) (halfHeight / scale));
int bottom = displayFrame.bottom - (halfHeight - (int) (halfHeight / scale));
- return new Rect(left, top, right, bottom);
+ mSourceBounds.set(left, top, right, bottom);
}
private void setMagnificationFrameBoundary() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java
index 2adb3ebb7bce..e405a89766e2 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnifierCallback.java
@@ -29,4 +29,12 @@ interface WindowMagnifierCallback {
* @param bounds The bounds of window magnifier on the screen.
*/
void onWindowMagnifierBoundsChanged(int displayId, Rect bounds);
+
+ /**
+ * Called when the magnified bounds is changed.
+ *
+ * @param displayId The logical display id.
+ * @param sourceBounds The magnified bounds in screen coordinates.
+ */
+ void onSourceBoundsChanged(int displayId, Rect sourceBounds);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 434bf49ac878..bb572191fe3c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -25,6 +25,8 @@ import static android.service.notification.NotificationListenerService.REASON_CA
import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
import static android.service.notification.NotificationListenerService.REASON_CLICK;
import static android.service.notification.NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED;
+import static android.service.notification.NotificationStats.DISMISSAL_BUBBLE;
+import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.View.INVISIBLE;
@@ -100,8 +102,11 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.coordinator.BubbleCoordinator;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -277,7 +282,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
* This can happen when an app cancels a bubbled notification or when the user dismisses a
* bubble.
*/
- void removeNotification(@NonNull NotificationEntry entry, int reason);
+ void removeNotification(
+ @NonNull NotificationEntry entry,
+ @NonNull DismissedByUserStats stats,
+ int reason);
/**
* Called when a bubbled notification has changed whether it should be
@@ -543,6 +551,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
});
+ // The new pipeline takes care of this as a NotifDismissInterceptor BubbleCoordinator
mNotificationEntryManager.addNotificationRemoveInterceptor(
new NotificationRemoveInterceptor() {
@Override
@@ -551,7 +560,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
NotificationEntry entry,
int dismissReason) {
final boolean isClearAll = dismissReason == REASON_CANCEL_ALL;
- final boolean isUserDimiss = dismissReason == REASON_CANCEL
+ final boolean isUserDismiss = dismissReason == REASON_CANCEL
|| dismissReason == REASON_CLICK;
final boolean isAppCancel = dismissReason == REASON_APP_CANCEL
|| dismissReason == REASON_APP_CANCEL_ALL;
@@ -562,7 +571,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
// previously been dismissed & entry.isRowDismissed would still be true
boolean userRemovedNotif =
(entry != null && entry.isRowDismissed() && !isAppCancel)
- || isClearAll || isUserDimiss || isSummaryCancel;
+ || isClearAll || isUserDismiss || isSummaryCancel;
if (userRemovedNotif) {
return handleDismissalInterception(entry);
@@ -591,8 +600,13 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
addNotifCallback(new NotifCallback() {
@Override
- public void removeNotification(NotificationEntry entry, int reason) {
- mNotificationEntryManager.performRemoveNotification(entry.getSbn(), reason);
+ public void removeNotification(
+ NotificationEntry entry,
+ DismissedByUserStats dismissedByUserStats,
+ int reason
+ ) {
+ mNotificationEntryManager.performRemoveNotification(entry.getSbn(),
+ dismissedByUserStats, reason);
}
@Override
@@ -612,7 +626,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mNotificationEntryManager.getActiveNotificationUnfiltered(
mBubbleData.getSummaryKey(groupKey));
if (summary != null) {
- mNotificationEntryManager.performRemoveNotification(summary.getSbn(),
+ mNotificationEntryManager.performRemoveNotification(
+ summary.getSbn(),
+ getDismissedByUserStats(summary, false),
UNDEFINED_DISMISS_REASON);
}
}
@@ -634,7 +650,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
boolean isSummaryThisNotif = summary.getKey().equals(entry.getKey());
if (!isSummaryThisNotif && (summaryChildren == null
|| summaryChildren.isEmpty())) {
- mNotificationEntryManager.performRemoveNotification(summary.getSbn(),
+ mNotificationEntryManager.performRemoveNotification(
+ summary.getSbn(),
+ getDismissedByUserStats(summary, false),
UNDEFINED_DISMISS_REASON);
}
}
@@ -1331,7 +1349,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
// time to actually remove it
for (NotifCallback cb : mCallbacks) {
if (entry != null) {
- cb.removeNotification(entry, REASON_CANCEL);
+ cb.removeNotification(
+ entry,
+ getDismissedByUserStats(entry, true),
+ REASON_CANCEL);
}
}
} else {
@@ -1487,7 +1508,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
} else {
// non-bubbled children can be removed
for (NotifCallback cb : mCallbacks) {
- cb.removeNotification(child, REASON_GROUP_SUMMARY_CANCELED);
+ cb.removeNotification(
+ child,
+ getDismissedByUserStats(child, true),
+ REASON_GROUP_SUMMARY_CANCELED);
}
}
}
@@ -1502,6 +1526,25 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
}
/**
+ * Gets the DismissedByUserStats used by {@link NotificationEntryManager}.
+ * Will not be necessary when using the new notification pipeline's {@link NotifCollection}.
+ * Instead, this is taken care of by {@link BubbleCoordinator}.
+ */
+ private DismissedByUserStats getDismissedByUserStats(
+ NotificationEntry entry,
+ boolean isVisible) {
+ return new DismissedByUserStats(
+ DISMISSAL_BUBBLE,
+ DISMISS_SENTIMENT_NEUTRAL,
+ NotificationVisibility.obtain(
+ entry.getKey(),
+ entry.getRanking().getRank(),
+ mNotificationEntryManager.getActiveNotificationsCount(),
+ isVisible,
+ NotificationLogger.getNotificationLocation(entry)));
+ }
+
+ /**
* Updates the visibility of the bubbles based on current state.
* Does not un-bubble, just hides or un-hides.
* Updates stack description for TalkBack focus.
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index e26aa554dd61..318a98799013 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -458,15 +458,6 @@ public class BubbleExpandedView extends LinearLayout {
mPointerView.setBackground(mPointerDrawable);
}
- /**
- * Hides the IME if it's showing. This is currently done by dispatching a back press to the AV.
- */
- void hideImeIfVisible() {
- if (mKeyboardVisible) {
- performBackPressIfNeeded();
- }
- }
-
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index ea12c9598b91..b3fbfd6a0f30 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -1081,11 +1081,10 @@ public class BubbleStackView extends FrameLayout
final Bubble bubble = mBubbleData.getSelectedBubble();
if (bubble != null && mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) {
final Intent intent = bubble.getSettingsIntent(mContext);
- collapseStack(() -> {
- mContext.startActivityAsUser(intent, bubble.getUser());
- logBubbleEvent(bubble,
- SysUiStatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
- });
+ mBubbleData.setExpanded(false);
+ mContext.startActivityAsUser(intent, bubble.getUser());
+ logBubbleEvent(bubble,
+ SysUiStatsLog.BUBBLE_UICHANGED__ACTION__HEADER_GO_TO_SETTINGS);
}
});
@@ -1769,36 +1768,6 @@ public class BubbleStackView extends FrameLayout
}
}
- /**
- * Dismiss the stack of bubbles.
- *
- * @deprecated
- */
- @Deprecated
- void stackDismissed(int reason) {
- if (DEBUG_BUBBLE_STACK_VIEW) {
- Log.d(TAG, "stackDismissed: reason=" + reason);
- }
- mBubbleData.dismissAll(reason);
- logBubbleEvent(null /* no bubble associated with bubble stack dismiss */,
- SysUiStatsLog.BUBBLE_UICHANGED__ACTION__STACK_DISMISSED);
- }
-
- /**
- * @deprecated use {@link #setExpanded(boolean)} and
- * {@link BubbleData#setSelectedBubble(Bubble)}
- */
- @Deprecated
- @MainThread
- void collapseStack(Runnable endRunnable) {
- if (DEBUG_BUBBLE_STACK_VIEW) {
- Log.d(TAG, "collapseStack(endRunnable)");
- }
- mBubbleData.setExpanded(false);
- // TODO - use the runnable at end of animation
- endRunnable.run();
- }
-
void showExpandedViewContents(int displayId) {
if (mExpandedBubble != null
&& mExpandedBubble.getExpandedView() != null
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 075318b3f1f7..de5316885b94 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -135,6 +135,7 @@ class MediaCarouselController @Inject constructor(
}
override fun onOverlayChanged() {
+ recreatePlayers()
inflateSettingsButton()
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
index c2631c923e45..1ae54d60d3fa 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
@@ -55,16 +55,16 @@ class SeekBarObserver(private val holder: PlayerViewHolder) : Observer<SeekBarVi
holder.seekBar.maxHeight = seekBarDefaultMaxHeight
}
- data.elapsedTime?.let {
- holder.seekBar.setProgress(it)
- holder.elapsedTimeView.setText(DateUtils.formatElapsedTime(
- it / DateUtils.SECOND_IN_MILLIS))
- }
-
data.duration?.let {
holder.seekBar.setMax(it)
holder.totalTimeView.setText(DateUtils.formatElapsedTime(
it / DateUtils.SECOND_IN_MILLIS))
}
+
+ data.elapsedTime?.let {
+ holder.seekBar.setProgress(it)
+ holder.elapsedTimeView.setText(DateUtils.formatElapsedTime(
+ it / DateUtils.SECOND_IN_MILLIS))
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java
index c581ac677532..264ace749383 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java
@@ -42,4 +42,10 @@ public interface OneHandedAnimationCallback {
default void onOneHandedAnimationCancel(
OneHandedAnimationController.OneHandedTransitionAnimator animator) {
}
+
+ /**
+ * Called when OneHanded animator is updating offset
+ */
+ default void onTutorialAnimationUpdate(int offset) {}
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java
index 1926c44abcba..2b07ac3f4d8a 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java
@@ -28,7 +28,9 @@ import androidx.annotation.VisibleForTesting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import javax.inject.Inject;
@@ -121,7 +123,8 @@ public class OneHandedAnimationController {
private T mEndValue;
private T mCurrentValue;
- private OneHandedAnimationCallback mOneHandedAnimationCallback;
+ private final List<OneHandedAnimationCallback> mOneHandedAnimationCallbacks =
+ new ArrayList<>();
private OneHandedSurfaceTransactionHelper mSurfaceTransactionHelper;
private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
mSurfaceControlTransactionFactory;
@@ -142,9 +145,11 @@ public class OneHandedAnimationController {
@Override
public void onAnimationStart(Animator animation) {
mCurrentValue = mStartValue;
- if (mOneHandedAnimationCallback != null) {
- mOneHandedAnimationCallback.onOneHandedAnimationStart(this);
- }
+ mOneHandedAnimationCallbacks.forEach(
+ (callback) -> {
+ callback.onOneHandedAnimationStart(this);
+ }
+ );
}
@Override
@@ -152,17 +157,21 @@ public class OneHandedAnimationController {
mCurrentValue = mEndValue;
final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
onEndTransaction(mLeash, tx);
- if (mOneHandedAnimationCallback != null) {
- mOneHandedAnimationCallback.onOneHandedAnimationEnd(tx, this);
- }
+ mOneHandedAnimationCallbacks.forEach(
+ (callback) -> {
+ callback.onOneHandedAnimationEnd(tx, this);
+ }
+ );
}
@Override
public void onAnimationCancel(Animator animation) {
mCurrentValue = mEndValue;
- if (mOneHandedAnimationCallback != null) {
- mOneHandedAnimationCallback.onOneHandedAnimationCancel(this);
- }
+ mOneHandedAnimationCallbacks.forEach(
+ (callback) -> {
+ callback.onOneHandedAnimationCancel(this);
+ }
+ );
}
@Override
@@ -173,6 +182,11 @@ public class OneHandedAnimationController {
public void onAnimationUpdate(ValueAnimator animation) {
applySurfaceControlTransaction(mLeash, newSurfaceControlTransaction(),
animation.getAnimatedFraction());
+ mOneHandedAnimationCallbacks.forEach(
+ (callback) -> {
+ callback.onTutorialAnimationUpdate(((Rect) mCurrentValue).top);
+ }
+ );
}
void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
@@ -192,9 +206,9 @@ public class OneHandedAnimationController {
mSurfaceTransactionHelper = helper;
}
- OneHandedTransitionAnimator<T> setOneHandedAnimationCallback(
+ OneHandedTransitionAnimator<T> setOneHandedAnimationCallbacks(
OneHandedAnimationCallback callback) {
- mOneHandedAnimationCallback = callback;
+ mOneHandedAnimationCallbacks.add(callback);
return this;
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
index c0b9258f39fd..8550959aa2c4 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -82,6 +82,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen
private OneHandedAnimationController mAnimationController;
private OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
mSurfaceControlTransactionFactory;
+ private OneHandedTutorialHandler mTutorialHandler;
private List<OneHandedTransitionCallback> mTransitionCallbacks = new ArrayList<>();
@VisibleForTesting
@@ -148,7 +149,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen
@Inject
public OneHandedDisplayAreaOrganizer(Context context,
DisplayController displayController,
- OneHandedAnimationController animationController) {
+ OneHandedAnimationController animationController,
+ OneHandedTutorialHandler tutorialHandler) {
mUpdateHandler = new Handler(OneHandedThread.get().getLooper(), mUpdateCallback);
mAnimationController = animationController;
mDisplayController = displayController;
@@ -157,6 +159,7 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen
mEnterExitAnimationDurationMs = context.getResources().getInteger(
com.android.systemui.R.integer.config_one_handed_translate_animation_duration);
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
+ mTutorialHandler = tutorialHandler;
}
@Override
@@ -272,7 +275,8 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer implemen
mAnimationController.getAnimator(leash, fromBounds, toBounds);
if (animator != null) {
animator.setTransitionDirection(direction)
- .setOneHandedAnimationCallback(mOneHandedAnimationCallback)
+ .setOneHandedAnimationCallbacks(mOneHandedAnimationCallback)
+ .setOneHandedAnimationCallbacks(mTutorialHandler.getAnimationCallback())
.setDuration(durationMs)
.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
index 71c5f8020330..ded386159dca 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java
@@ -53,8 +53,8 @@ import javax.inject.Singleton;
*/
@Singleton
public class OneHandedGestureHandler implements OneHandedTransitionCallback,
- NavigationModeController.ModeChangedListener,
- DisplayChangeController.OnDisplayChangingListener {
+ NavigationModeController.ModeChangedListener,
+ DisplayChangeController.OnDisplayChangingListener {
private static final String TAG = "OneHandedGestureHandler";
private static final boolean DEBUG_GESTURE = false;
@@ -87,8 +87,8 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
* Constructor of OneHandedGestureHandler, we only handle the gesture of
* {@link Display#DEFAULT_DISPLAY}
*
- * @param context {@link Context}
- * @param displayController {@link DisplayController}
+ * @param context {@link Context}
+ * @param displayController {@link DisplayController}
* @param navigationModeController {@link NavigationModeController}
*/
@Inject
@@ -103,7 +103,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback,
mDragDistThreshold = context.getResources().getDimensionPixelSize(
R.dimen.gestures_onehanded_drag_threshold);
final float slop = ViewConfiguration.get(context).getScaledTouchSlop();
- mSquaredSlop = slop * slop;
+ mSquaredSlop = slop * slop;
updateIsEnabled();
}
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
index 70a81aaed249..51e587586852 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedManagerImpl.java
@@ -57,6 +57,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
private final OneHandedGestureHandler mGestureHandler;
private final OneHandedTimeoutHandler mTimeoutHandler;
private final OneHandedTouchHandler mTouchHandler;
+ private final OneHandedTutorialHandler mTutorialHandler;
private final SysUiState mSysUiFlagContainer;
private Context mContext;
@@ -107,6 +108,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
DisplayController displayController,
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
OneHandedTouchHandler touchHandler,
+ OneHandedTutorialHandler tutorialHandler,
OneHandedGestureHandler gestureHandler,
SysUiState sysUiState) {
mContext = context;
@@ -120,6 +122,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
context.getContentResolver());
mTimeoutHandler = OneHandedTimeoutHandler.get();
mTouchHandler = touchHandler;
+ mTutorialHandler = tutorialHandler;
mGestureHandler = gestureHandler;
updateOneHandedEnabled();
setupGestures();
@@ -230,6 +233,7 @@ public class OneHandedManagerImpl implements OneHandedManager, Dumpable {
mDisplayAreaOrganizer.registerTransitionCallback(mTransitionCallback);
mDisplayAreaOrganizer.registerTransitionCallback(mTouchHandler);
mDisplayAreaOrganizer.registerTransitionCallback(mGestureHandler);
+ mDisplayAreaOrganizer.registerTransitionCallback(mTutorialHandler);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
index 3d4338c1e220..d616a3a45b90 100644
--- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java
@@ -58,6 +58,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
OneHandedTouchEventCallback mTouchEventCallback;
private boolean mIsEnabled;
+ private boolean mIsOnStopTransitioning;
private boolean mIsInOutsideRegion;
@Inject
@@ -96,8 +97,9 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
mTimeoutHandler.resetTimer();
- if (mIsInOutsideRegion) {
+ if (mIsInOutsideRegion && !mIsOnStopTransitioning) {
mTouchEventCallback.onStop();
+ mIsOnStopTransitioning = true;
}
// Reset flag for next operation
mIsInOutsideRegion = false;
@@ -146,6 +148,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback, Dumpa
@Override
public void onStopFinished(Rect bounds) {
mLastUpdatedBounds.set(bounds);
+ mIsOnStopTransitioning = false;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
new file mode 100644
index 000000000000..8a67da53e6a2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java
@@ -0,0 +1,161 @@
+/*
+ * 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.onehanded;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.R;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Manages the user tutorial handling for One Handed operations, including animations synchronized
+ * with one-handed translation.
+ * Refer {@link OneHandedGestureHandler} and {@link OneHandedTouchHandler} to see start and stop
+ * one handed gesture
+ */
+@Singleton
+public class OneHandedTutorialHandler implements OneHandedTransitionCallback, Dumpable {
+ private static final String TAG = "OneHandedTutorialHandler";
+ private final Rect mLastUpdatedBounds = new Rect();
+ private final WindowManager mWindowManager;
+
+ private View mTutorialView;
+ private Point mDisplaySize = new Point();
+ private Handler mUpdateHandler;
+
+ /**
+ * Container of the tutorial panel showing at outside region when one handed starting
+ */
+ private ViewGroup mTargetViewContainer;
+ private int mTutorialAreaHeight;
+
+ private final OneHandedAnimationCallback mAnimationCallback = new OneHandedAnimationCallback() {
+ @Override
+ public void onTutorialAnimationUpdate(int offset) {
+ mUpdateHandler.post(() -> onAnimationUpdate(offset));
+ }
+ };
+
+ @Inject
+ public OneHandedTutorialHandler(Context context) {
+ context.getDisplay().getRealSize(mDisplaySize);
+ mUpdateHandler = new Handler();
+ 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));
+ mTutorialView = LayoutInflater.from(context).inflate(R.xml.one_handed_tutorial, null);
+ mTargetViewContainer.addView(mTutorialView);
+ createOrUpdateTutorialTarget();
+ }
+
+ @Override
+ public void onStartFinished(Rect bounds) {
+ mUpdateHandler.post(() -> updateFinished(View.VISIBLE, 0f));
+ }
+
+ @Override
+ public void onStopFinished(Rect bounds) {
+ mUpdateHandler.post(() -> updateFinished(
+ View.INVISIBLE, -mTargetViewContainer.getHeight()));
+ }
+
+ private void updateFinished(int visible, float finalPosition) {
+ mTargetViewContainer.setVisibility(visible);
+ mTargetViewContainer.setTranslationY(finalPosition);
+ }
+
+ /**
+ * Adds the tutorial target view to the WindowManager and update its layout, so it's ready
+ * to be animated in.
+ */
+ private void createOrUpdateTutorialTarget() {
+ mUpdateHandler.post(() -> {
+ if (!mTargetViewContainer.isAttachedToWindow()) {
+ mTargetViewContainer.setVisibility(View.INVISIBLE);
+
+ try {
+ mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
+ } catch (IllegalStateException e) {
+ // This shouldn't happen, but if the target is already added, just update its
+ // layout params.
+ mWindowManager.updateViewLayout(
+ mTargetViewContainer, getTutorialTargetLayoutParams());
+ }
+ } else {
+ mWindowManager.updateViewLayout(mTargetViewContainer,
+ getTutorialTargetLayoutParams());
+ }
+ });
+ }
+
+ OneHandedAnimationCallback getAnimationCallback() {
+ return mAnimationCallback;
+ }
+
+ /**
+ * Returns layout params for the dismiss target, using the latest display metrics.
+ */
+ private WindowManager.LayoutParams getTutorialTargetLayoutParams() {
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ mDisplaySize.x, mTutorialAreaHeight, 0, 0,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSLUCENT);
+ lp.gravity = Gravity.TOP | Gravity.LEFT;
+ lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+ lp.setFitInsetsTypes(0 /* types */);
+ lp.setTitle("one-handed-tutorial-overlay");
+
+ return lp;
+ }
+
+ @Override
+ public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+ final String innerPrefix = " ";
+ pw.println(TAG + "states: ");
+ pw.print(innerPrefix + "mLastUpdatedBounds=");
+ pw.println(mLastUpdatedBounds);
+ }
+
+ private void onAnimationUpdate(float value) {
+ mTargetViewContainer.setVisibility(View.VISIBLE);
+ mTargetViewContainer.setTransitionGroup(true);
+ mTargetViewContainer.setTranslationY(value - mTargetViewContainer.getHeight());
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
index 72019315139b..4931388fe362 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
@@ -53,16 +53,16 @@ public class PipAnimationController {
public static final int TRANSITION_DIRECTION_NONE = 0;
public static final int TRANSITION_DIRECTION_SAME = 1;
public static final int TRANSITION_DIRECTION_TO_PIP = 2;
- public static final int TRANSITION_DIRECTION_TO_FULLSCREEN = 3;
- public static final int TRANSITION_DIRECTION_TO_SPLIT_SCREEN = 4;
+ public static final int TRANSITION_DIRECTION_LEAVE_PIP = 3;
+ public static final int TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN = 4;
public static final int TRANSITION_DIRECTION_REMOVE_STACK = 5;
@IntDef(prefix = { "TRANSITION_DIRECTION_" }, value = {
TRANSITION_DIRECTION_NONE,
TRANSITION_DIRECTION_SAME,
TRANSITION_DIRECTION_TO_PIP,
- TRANSITION_DIRECTION_TO_FULLSCREEN,
- TRANSITION_DIRECTION_TO_SPLIT_SCREEN,
+ TRANSITION_DIRECTION_LEAVE_PIP,
+ TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN,
TRANSITION_DIRECTION_REMOVE_STACK
})
@Retention(RetentionPolicy.SOURCE)
@@ -73,8 +73,8 @@ public class PipAnimationController {
}
public static boolean isOutPipDirection(@TransitionDirection int direction) {
- return direction == TRANSITION_DIRECTION_TO_FULLSCREEN
- || direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
+ return direction == TRANSITION_DIRECTION_LEAVE_PIP
+ || direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN;
}
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 312d6d62128f..7c3743bd8bcf 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -23,12 +23,12 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.systemui.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
+import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
+import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_REMOVE_STACK;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_SAME;
-import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
-import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
import static com.android.systemui.pip.PipAnimationController.isInPipDirection;
import static com.android.systemui.pip.PipAnimationController.isOutPipDirection;
@@ -285,8 +285,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
final WindowContainerTransaction wct = new WindowContainerTransaction();
final Rect destinationBounds = initialConfig.windowConfiguration.getBounds();
final int direction = syncWithSplitScreenBounds(destinationBounds)
- ? TRANSITION_DIRECTION_TO_SPLIT_SCREEN
- : TRANSITION_DIRECTION_TO_FULLSCREEN;
+ ? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
+ : TRANSITION_DIRECTION_LEAVE_PIP;
if (orientationDiffers) {
// Send started callback though animation is ignored.
sendOnPipTransitionStarted(direction);
@@ -303,7 +303,10 @@ public class PipTaskOrganizer extends TaskOrganizer implements
mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds,
mLastReportedBounds);
tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
- wct.setActivityWindowingMode(mToken, direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN
+ // We set to fullscreen here for now, but later it will be set to UNDEFINED for
+ // the proper windowing mode to take place. See #applyWindowingModeChangeOnExit.
+ wct.setActivityWindowingMode(mToken,
+ direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
: WINDOWING_MODE_FULLSCREEN);
wct.setBounds(mToken, destinationBounds);
@@ -327,7 +330,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
wct.setWindowingMode(mToken, getOutPipWindowingMode());
// Simply reset the activity mode set prior to the animation running.
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
- if (mSplitDivider != null && direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN) {
+ if (mSplitDivider != null && direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
wct.reparent(mToken, mSplitDivider.getSecondaryRoot(), true /* onTop */);
}
}
@@ -842,7 +845,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
} else if (isOutPipDirection(direction)) {
// If we are animating to fullscreen, then we need to reset the override bounds
// on the task to ensure that the task "matches" the parent's bounds.
- taskBounds = (direction == TRANSITION_DIRECTION_TO_FULLSCREEN)
+ taskBounds = (direction == TRANSITION_DIRECTION_LEAVE_PIP)
? null : destinationBounds;
applyWindowingModeChangeOnExit(wct, direction);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
index c715398d52da..a13318990f40 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipAccessibilityInteractionConnection.java
@@ -131,7 +131,7 @@ public class PipAccessibilityInteractionConnection
result = true;
break;
case AccessibilityNodeInfo.ACTION_EXPAND:
- mMotionHelper.expandPipToFullscreen();
+ mMotionHelper.expandLeavePip();
result = true;
break;
default:
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 582cd046f9e0..e4d057e76079 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -181,7 +181,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
!= WINDOWING_MODE_PINNED) {
return;
}
- mTouchHandler.getMotionHelper().expandPipToFullscreen(clearedTask /* skipAnimation */);
+ mTouchHandler.getMotionHelper().expandLeavePip(clearedTask /* skipAnimation */);
}
};
@@ -318,7 +318,7 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
*/
@Override
public void expandPip() {
- mTouchHandler.getMotionHelper().expandPipToFullscreen(false /* skipAnimation */);
+ mTouchHandler.getMotionHelper().expandLeavePip(false /* skipAnimation */);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index ca3ef2465498..ee8f295e0c30 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -54,7 +54,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
private static final int SHRINK_STACK_FROM_MENU_DURATION = 250;
private static final int EXPAND_STACK_TO_MENU_DURATION = 250;
- private static final int EXPAND_STACK_TO_FULLSCREEN_DURATION = 300;
+ private static final int LEAVE_PIP_DURATION = 300;
private static final int SHIFT_DURATION = 300;
/** Friction to use for PIP when it moves via physics fling animations. */
@@ -304,16 +304,18 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
}
/**
- * Resizes the pinned stack back to fullscreen.
+ * Resizes the pinned stack back to unknown windowing mode, which could be freeform or
+ * * fullscreen depending on the display area's windowing mode.
*/
- void expandPipToFullscreen() {
- expandPipToFullscreen(false /* skipAnimation */);
+ void expandLeavePip() {
+ expandLeavePip(false /* skipAnimation */);
}
/**
- * Resizes the pinned stack back to fullscreen.
+ * Resizes the pinned stack back to unknown windowing mode, which could be freeform or
+ * fullscreen depending on the display area's windowing mode.
*/
- void expandPipToFullscreen(boolean skipAnimation) {
+ void expandLeavePip(boolean skipAnimation) {
if (DEBUG) {
Log.d(TAG, "exitPip: skipAnimation=" + skipAnimation
+ " callers=\n" + Debug.getCallers(5, " "));
@@ -323,7 +325,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
mPipTaskOrganizer.getUpdateHandler().post(() -> {
mPipTaskOrganizer.exitPip(skipAnimation
? 0
- : EXPAND_STACK_TO_FULLSCREEN_DURATION);
+ : LEAVE_PIP_DURATION);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 5434b62e19b8..7fc2823fc248 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -193,7 +193,7 @@ public class PipTouchHandler {
@Override
public void onPipExpand() {
- mMotionHelper.expandPipToFullscreen();
+ mMotionHelper.expandLeavePip();
}
@Override
@@ -991,7 +991,7 @@ public class PipTouchHandler {
// Expand to fullscreen if this is a double tap
// the PiP should be frozen until the transition ends
setTouchEnabled(false);
- mMotionHelper.expandPipToFullscreen();
+ mMotionHelper.expandLeavePip();
} else if (mMenuState != MENU_STATE_FULL) {
if (!mTouchState.isWaitingForDoubleTap()) {
// User has stalled long enough for this not to be a drag or a double tap, just
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 5f37cc4520a3..df61fd19ad45 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -65,10 +65,6 @@ public class Recents extends SystemUI implements CommandQueue.Callbacks {
}
}
- public void growRecents() {
- mImpl.growRecents();
- }
-
@Override
public void showRecentApps(boolean triggeredFromAltTab) {
// Ensure the device has been provisioned before allowing the user to interact with
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
index 6f5ceabcc9a5..6d1299ba98ac 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
@@ -205,7 +205,8 @@ public class ScreenshotNotificationsController {
mPublicNotificationBuilder
.setContentTitle(mResources.getString(R.string.screenshot_saved_title))
.setContentText(mResources.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mContext, 0, launchIntent, 0))
+ .setContentIntent(PendingIntent
+ .getActivity(mContext, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE))
.setWhen(now)
.setAutoCancel(true)
.setColor(mContext.getColor(
@@ -213,7 +214,8 @@ public class ScreenshotNotificationsController {
mNotificationBuilder
.setContentTitle(mResources.getString(R.string.screenshot_saved_title))
.setContentText(mResources.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mContext, 0, launchIntent, 0))
+ .setContentIntent(PendingIntent
+ .getActivity(mContext, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE))
.setWhen(now)
.setAutoCancel(true)
.setColor(mContext.getColor(
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index eb7231211ea8..4007abb39903 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -16,559 +16,127 @@
package com.android.systemui.stackdivider;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static android.view.Display.DEFAULT_DISPLAY;
-
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.provider.Settings;
-import android.util.Slog;
-import android.view.LayoutInflater;
-import android.view.View;
import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-import android.window.WindowOrganizer;
-import com.android.internal.policy.DividerSnapAlgorithm;
-import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.systemui.recents.Recents;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.wm.shell.common.DisplayChangeController;
-import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayImeController;
-import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.common.SystemWindows;
-import com.android.wm.shell.common.TransactionPool;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Optional;
import java.util.function.Consumer;
import javax.inject.Singleton;
-import dagger.Lazy;
-
/**
* Controls the docked stack divider.
*/
@Singleton
-public class Divider extends SystemUI implements DividerView.DividerCallbacks,
- DisplayController.OnDisplaysChangedListener {
- private static final String TAG = "Divider";
-
- static final boolean DEBUG = false;
-
- static final int DEFAULT_APP_TRANSITION_DURATION = 336;
-
- private final Optional<Lazy<Recents>> mRecentsOptionalLazy;
-
- private DividerWindowManager mWindowManager;
- private DividerView mView;
- private final DividerState mDividerState = new DividerState();
- private boolean mVisible = false;
- private boolean mMinimized = false;
- private boolean mAdjustedForIme = false;
- private boolean mHomeStackResizable = false;
- private ForcedResizableInfoActivityController mForcedResizableController;
- private SystemWindows mSystemWindows;
- private DisplayController mDisplayController;
- private DisplayImeController mImeController;
- final TransactionPool mTransactionPool;
-
- // Keeps track of real-time split geometry including snap positions and ime adjustments
- private SplitDisplayLayout mSplitLayout;
-
- // Transient: this contains the layout calculated for a new rotation requested by WM. This is
- // kept around so that we can wait for a matching configuration change and then use the exact
- // layout that we sent back to WM.
- private SplitDisplayLayout mRotateSplitLayout;
+public class Divider extends SystemUI {
+ private final KeyguardStateController mKeyguardStateController;
+ private final DividerController mDividerController;
- private Handler mHandler;
- private KeyguardStateController mKeyguardStateController;
-
- private WindowManagerProxy mWindowManagerProxy;
-
- private final ArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners =
- new ArrayList<>();
-
- private SplitScreenTaskOrganizer mSplits = new SplitScreenTaskOrganizer(this);
-
- private DisplayChangeController.OnDisplayChangingListener mRotationController =
- (display, fromRotation, toRotation, wct) -> {
- if (!mSplits.isSplitScreenSupported() || mWindowManagerProxy == null) {
- return;
- }
- WindowContainerTransaction t = new WindowContainerTransaction();
- DisplayLayout displayLayout =
- new DisplayLayout(mDisplayController.getDisplayLayout(display));
- SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits);
- sdl.rotateTo(toRotation);
- mRotateSplitLayout = sdl;
- final int position = isDividerVisible()
- ? (mMinimized ? mView.mSnapTargetBeforeMinimized.position
- : mView.getCurrentPosition())
- // snap resets to middle target when not in split-mode
- : sdl.getSnapAlgorithm().getMiddleTarget().position;
- DividerSnapAlgorithm snap = sdl.getSnapAlgorithm();
- final DividerSnapAlgorithm.SnapTarget target =
- snap.calculateNonDismissingSnapTarget(position);
- sdl.resizeSplits(target.position, t);
-
- if (isSplitActive() && mHomeStackResizable) {
- WindowManagerProxy.applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t);
- }
- if (mWindowManagerProxy.queueSyncTransactionIfWaiting(t)) {
- // Because sync transactions are serialized, its possible for an "older"
- // bounds-change to get applied after a screen rotation. In that case, we
- // want to actually defer on that rather than apply immediately. Of course,
- // this means that the bounds may not change until after the rotation so
- // the user might see some artifacts. This should be rare.
- Slog.w(TAG, "Screen rotated while other operations were pending, this may"
- + " result in some graphical artifacts.");
- } else {
- wct.merge(t, true /* transfer */);
- }
- };
-
- private final DividerImeController mImePositionProcessor;
-
- private TaskStackChangeListener mActivityRestartListener = new TaskStackChangeListener() {
- @Override
- public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
- boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
- if (!wasVisible || task.configuration.windowConfiguration.getWindowingMode()
- != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || !mSplits.isSplitScreenSupported()) {
- return;
- }
-
- if (isMinimized()) {
- onUndockingTask();
- }
- }
- };
-
- public Divider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy,
- DisplayController displayController, SystemWindows systemWindows,
- DisplayImeController imeController, Handler handler,
- KeyguardStateController keyguardStateController, TransactionPool transactionPool) {
+ Divider(Context context, DividerController dividerController,
+ KeyguardStateController keyguardStateController) {
super(context);
- mDisplayController = displayController;
- mSystemWindows = systemWindows;
- mImeController = imeController;
- mHandler = handler;
+ mDividerController = dividerController;
mKeyguardStateController = keyguardStateController;
- mRecentsOptionalLazy = recentsOptionalLazy;
- mForcedResizableController = new ForcedResizableInfoActivityController(context, this);
- mTransactionPool = transactionPool;
- mWindowManagerProxy = new WindowManagerProxy(mTransactionPool, mHandler);
- mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler);
}
@Override
public void start() {
- mWindowManager = new DividerWindowManager(mSystemWindows);
- mDisplayController.addDisplayWindowListener(this);
+ mDividerController.start();
// Hide the divider when keyguard is showing. Even though keyguard/statusbar is above
// everything, it is actually transparent except for notifications, so we still need to
// hide any surfaces that are below it.
// TODO(b/148906453): Figure out keyguard dismiss animation for divider view.
mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
@Override
- public void onUnlockedChanged() {
-
- }
-
- @Override
public void onKeyguardShowingChanged() {
- if (!isSplitActive() || mView == null) {
- return;
- }
- mView.setHidden(mKeyguardStateController.isShowing());
- if (!mKeyguardStateController.isShowing()) {
- mImePositionProcessor.updateAdjustForIme();
- }
- }
-
- @Override
- public void onKeyguardFadingAwayChanged() {
-
+ mDividerController.onKeyguardShowingChanged(mKeyguardStateController.isShowing());
}
});
// Don't initialize the divider or anything until we get the default display.
- }
- @Override
- public void onDisplayAdded(int displayId) {
- if (displayId != DEFAULT_DISPLAY) {
- return;
- }
- mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
- mDisplayController.getDisplayLayout(displayId), mSplits);
- mImeController.addPositionProcessor(mImePositionProcessor);
- mDisplayController.addDisplayChangingController(mRotationController);
- if (!ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)) {
- removeDivider();
- return;
- }
- try {
- mSplits.init();
- // Set starting tile bounds based on middle target
- final WindowContainerTransaction tct = new WindowContainerTransaction();
- int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
- mSplitLayout.resizeSplits(midPos, tct);
- WindowOrganizer.applyTransaction(tct);
- } catch (Exception e) {
- Slog.e(TAG, "Failed to register docked stack listener", e);
- removeDivider();
- return;
- }
- ActivityManagerWrapper.getInstance().registerTaskStackListener(mActivityRestartListener);
+ ActivityManagerWrapper.getInstance().registerTaskStackListener(
+ new TaskStackChangeListener() {
+ @Override
+ public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
+ boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
+ if (!wasVisible || task.configuration.windowConfiguration.getWindowingMode()
+ != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || !mDividerController.isSplitScreenSupported()) {
+ return;
+ }
+
+ if (mDividerController.isMinimized()) {
+ onUndockingTask();
+ }
+ }
+ }
+ );
}
@Override
- public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
- if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
- return;
- }
- mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
- mDisplayController.getDisplayLayout(displayId), mSplits);
- if (mRotateSplitLayout == null) {
- int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
- final WindowContainerTransaction tct = new WindowContainerTransaction();
- mSplitLayout.resizeSplits(midPos, tct);
- WindowOrganizer.applyTransaction(tct);
- } else if (mSplitLayout.mDisplayLayout.rotation()
- == mRotateSplitLayout.mDisplayLayout.rotation()) {
- mSplitLayout.mPrimary = new Rect(mRotateSplitLayout.mPrimary);
- mSplitLayout.mSecondary = new Rect(mRotateSplitLayout.mSecondary);
- mRotateSplitLayout = null;
- }
- if (isSplitActive()) {
- update(newConfig);
- }
- }
-
- Handler getHandler() {
- return mHandler;
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ mDividerController.dump(pw);
}
- public DividerView getView() {
- return mView;
+ /** Switch to minimized state if appropriate. */
+ public void setMinimized(final boolean minimized) {
+ mDividerController.setMinimized(minimized);
}
public boolean isMinimized() {
- return mMinimized;
+ return mDividerController.isMinimized();
}
public boolean isHomeStackResizable() {
- return mHomeStackResizable;
- }
-
- /** {@code true} if this is visible */
- public boolean isDividerVisible() {
- return mView != null && mView.getVisibility() == View.VISIBLE;
- }
-
- /**
- * This indicates that at-least one of the splits has content. This differs from
- * isDividerVisible because the divider is only visible once *everything* is in split mode
- * while this only cares if some things are (eg. while entering/exiting as well).
- */
- private boolean isSplitActive() {
- return mSplits.mPrimary != null && mSplits.mSecondary != null
- && (mSplits.mPrimary.topActivityType != ACTIVITY_TYPE_UNDEFINED
- || mSplits.mSecondary.topActivityType != ACTIVITY_TYPE_UNDEFINED);
- }
-
- private void addDivider(Configuration configuration) {
- Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
- mView = (DividerView)
- LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
- DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
- mView.injectDependencies(mWindowManager, mDividerState, this, mSplits, mSplitLayout,
- mImePositionProcessor, mWindowManagerProxy);
- mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
- mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, null /* transaction */);
- final int size = dctx.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_thickness);
- final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
- final int width = landscape ? size : displayLayout.width();
- final int height = landscape ? displayLayout.height() : size;
- mWindowManager.add(mView, width, height, mContext.getDisplayId());
- }
-
- private void removeDivider() {
- if (mView != null) {
- mView.onDividerRemoved();
- }
- mWindowManager.remove();
- }
-
- private void update(Configuration configuration) {
- final boolean isDividerHidden = mView != null && mKeyguardStateController.isShowing();
-
- removeDivider();
- addDivider(configuration);
-
- if (mMinimized) {
- mView.setMinimizedDockStack(true, mHomeStackResizable, null /* transaction */);
- updateTouchable();
- }
- mView.setHidden(isDividerHidden);
- }
-
- void onTaskVanished() {
- mHandler.post(this::removeDivider);
- }
-
- private void updateVisibility(final boolean visible) {
- if (DEBUG) Slog.d(TAG, "Updating visibility " + mVisible + "->" + visible);
- if (mVisible != visible) {
- mVisible = visible;
- mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
-
- if (visible) {
- mView.enterSplitMode(mHomeStackResizable);
- // Update state because animations won't finish.
- mWindowManagerProxy.runInSync(
- t -> mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, t));
-
- } else {
- mView.exitSplitMode();
- mWindowManagerProxy.runInSync(
- t -> mView.setMinimizedDockStack(false, mHomeStackResizable, t));
- }
- // Notify existence listeners
- synchronized (mDockedStackExistsListeners) {
- mDockedStackExistsListeners.removeIf(wf -> {
- Consumer<Boolean> l = wf.get();
- if (l != null) l.accept(visible);
- return l == null;
- });
- }
- }
+ return mDividerController.isHomeStackResizable();
}
- /** Switch to minimized state if appropriate */
- public void setMinimized(final boolean minimized) {
- if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible);
- mHandler.post(() -> {
- if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible);
- if (!mVisible) {
- return;
- }
- setHomeMinimized(minimized, mHomeStackResizable);
- });
- }
-
- private void setHomeMinimized(final boolean minimized, boolean homeStackResizable) {
- if (DEBUG) {
- Slog.d(TAG, "setHomeMinimized min:" + mMinimized + "->" + minimized + " hrsz:"
- + mHomeStackResizable + "->" + homeStackResizable
- + " split:" + isDividerVisible());
- }
- WindowContainerTransaction wct = new WindowContainerTransaction();
- final boolean minimizedChanged = mMinimized != minimized;
- // Update minimized state
- if (minimizedChanged) {
- mMinimized = minimized;
- }
- // Always set this because we could be entering split when mMinimized is already true
- wct.setFocusable(mSplits.mPrimary.token, !mMinimized);
- boolean onlyFocusable = true;
-
- // Update home-stack resizability
- final boolean homeResizableChanged = mHomeStackResizable != homeStackResizable;
- if (homeResizableChanged) {
- mHomeStackResizable = homeStackResizable;
- if (isDividerVisible()) {
- WindowManagerProxy.applyHomeTasksMinimized(
- mSplitLayout, mSplits.mSecondary.token, wct);
- onlyFocusable = false;
- }
- }
-
- // Sync state to DividerView if it exists.
- if (mView != null) {
- final int displayId = mView.getDisplay() != null
- ? mView.getDisplay().getDisplayId() : DEFAULT_DISPLAY;
- // pause ime here (before updateMinimizedDockedStack)
- if (mMinimized) {
- mImePositionProcessor.pause(displayId);
- }
- if (minimizedChanged || homeResizableChanged) {
- // This conflicts with IME adjustment, so only call it when things change.
- mView.setMinimizedDockStack(minimized, getAnimDuration(), homeStackResizable);
- }
- if (!mMinimized) {
- // afterwards so it can end any animations started in view
- mImePositionProcessor.resume(displayId);
- }
- }
- updateTouchable();
- if (onlyFocusable) {
- // If we are only setting focusability, a sync transaction isn't necessary (in fact it
- // can interrupt other animations), so see if it can be submitted on pending instead.
- if (!mSplits.mDivider.getWmProxy().queueSyncTransactionIfWaiting(wct)) {
- WindowOrganizer.applyTransaction(wct);
- }
- } else {
- mWindowManagerProxy.applySyncTransaction(wct);
- }
- }
-
- void setAdjustedForIme(boolean adjustedForIme) {
- if (mAdjustedForIme == adjustedForIme) {
- return;
- }
- mAdjustedForIme = adjustedForIme;
- updateTouchable();
- }
-
- private void updateTouchable() {
- mWindowManager.setTouchable(!mAdjustedForIme);
+ /** Callback for undocking task. */
+ public void onUndockingTask() {
+ mDividerController.onUndockingTask();
}
- /**
- * Workaround for b/62528361, at the time recents has drawn, it may happen before a
- * configuration change to the Divider, and internally, the event will be posted to the
- * subscriber, or DividerView, which has been removed and prevented from resizing. Instead,
- * register the event handler here and proxy the event to the current DividerView.
- */
public void onRecentsDrawn() {
- if (mView != null) {
- mView.onRecentsDrawn();
- }
- }
-
- public void onUndockingTask() {
- if (mView != null) {
- mView.onUndockingTask();
- }
+ mDividerController.onRecentsDrawn();
}
public void onDockedFirstAnimationFrame() {
- if (mView != null) {
- mView.onDockedFirstAnimationFrame();
- }
+ mDividerController.onDockedFirstAnimationFrame();
}
public void onDockedTopTask() {
- if (mView != null) {
- mView.onDockedTopTask();
- }
+ mDividerController.onDockedTopTask();
}
public void onAppTransitionFinished() {
- if (mView == null) {
- return;
- }
- mForcedResizableController.onAppTransitionFinished();
+ mDividerController.onAppTransitionFinished();
}
- @Override
- public void onDraggingStart() {
- mForcedResizableController.onDraggingStart();
- }
-
- @Override
- public void onDraggingEnd() {
- mForcedResizableController.onDraggingEnd();
- }
-
- @Override
- public void growRecents() {
- mRecentsOptionalLazy.ifPresent(recentsLazy -> recentsLazy.get().growRecents());
- }
-
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.print(" mVisible="); pw.println(mVisible);
- pw.print(" mMinimized="); pw.println(mMinimized);
- pw.print(" mAdjustedForIme="); pw.println(mAdjustedForIme);
+ public DividerView getView() {
+ return mDividerController.getDividerView();
}
- long getAnimDuration() {
- float transitionScale = Settings.Global.getFloat(mContext.getContentResolver(),
- Settings.Global.TRANSITION_ANIMATION_SCALE,
- mContext.getResources().getFloat(
- com.android.internal.R.dimen
- .config_appTransitionAnimationDurationScaleDefault));
- final long transitionDuration = DEFAULT_APP_TRANSITION_DURATION;
- return (long) (transitionDuration * transitionScale);
+ /** @return the container token for the secondary split root task. */
+ public WindowContainerToken getSecondaryRoot() {
+ return mDividerController.getSecondaryRoot();
}
/** Register a listener that gets called whenever the existence of the divider changes */
public void registerInSplitScreenListener(Consumer<Boolean> listener) {
- listener.accept(isDividerVisible());
- synchronized (mDockedStackExistsListeners) {
- mDockedStackExistsListeners.add(new WeakReference<>(listener));
- }
- }
-
- void startEnterSplit() {
- update(mDisplayController.getDisplayContext(
- mContext.getDisplayId()).getResources().getConfiguration());
- // Set resizable directly here because applyEnterSplit already resizes home stack.
- mHomeStackResizable = mWindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout);
- }
-
- void startDismissSplit() {
- mWindowManagerProxy.applyDismissSplit(mSplits, mSplitLayout, true /* dismissOrMaximize */);
- updateVisibility(false /* visible */);
- mMinimized = false;
- removeDivider();
- mImePositionProcessor.reset();
+ mDividerController.registerInSplitScreenListener(listener);
}
- void ensureMinimizedSplit() {
- setHomeMinimized(true /* minimized */, mHomeStackResizable);
- if (mView != null && !isDividerVisible()) {
- // Wasn't in split-mode yet, so enter now.
- if (DEBUG) {
- Slog.d(TAG, " entering split mode with minimized=true");
- }
- updateVisibility(true /* visible */);
- }
- }
-
- void ensureNormalSplit() {
- setHomeMinimized(false /* minimized */, mHomeStackResizable);
- if (mView != null && !isDividerVisible()) {
- // Wasn't in split-mode, so enter now.
- if (DEBUG) {
- Slog.d(TAG, " enter split mode unminimized ");
- }
- updateVisibility(true /* visible */);
- }
- }
-
- SplitDisplayLayout getSplitLayout() {
- return mSplitLayout;
- }
-
- WindowManagerProxy getWmProxy() {
- return mWindowManagerProxy;
- }
-
- /** @return the container token for the secondary split root task. */
- public WindowContainerToken getSecondaryRoot() {
- if (mSplits == null || mSplits.mSecondary == null) {
- return null;
- }
- return mSplits.mSecondary.token;
+ /** {@code true} if this is visible */
+ public boolean isDividerVisible() {
+ return mDividerController.isDividerVisible();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java
new file mode 100644
index 000000000000..81649f608581
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerController.java
@@ -0,0 +1,516 @@
+/*
+ * 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.stackdivider;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.app.ActivityTaskManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+import android.window.WindowOrganizer;
+
+import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.systemui.R;
+import com.android.wm.shell.common.DisplayChangeController;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayImeController;
+import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.SystemWindows;
+import com.android.wm.shell.common.TransactionPool;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Controls the docked stack divider.
+ */
+public class DividerController implements DividerView.DividerCallbacks,
+ DisplayController.OnDisplaysChangedListener {
+ static final boolean DEBUG = false;
+ private static final String TAG = "Divider";
+
+ static final int DEFAULT_APP_TRANSITION_DURATION = 336;
+
+ private DividerWindowManager mWindowManager;
+ private DividerView mView;
+ private final DividerState mDividerState = new DividerState();
+ private boolean mVisible = false;
+ private boolean mMinimized = false;
+ private boolean mAdjustedForIme = false;
+ private boolean mHomeStackResizable = false;
+ private ForcedResizableInfoActivityController mForcedResizableController;
+ private SystemWindows mSystemWindows;
+ private DisplayController mDisplayController;
+ private DisplayImeController mImeController;
+ final TransactionPool mTransactionPool;
+
+ // Keeps track of real-time split geometry including snap positions and ime adjustments
+ private SplitDisplayLayout mSplitLayout;
+
+ // Transient: this contains the layout calculated for a new rotation requested by WM. This is
+ // kept around so that we can wait for a matching configuration change and then use the exact
+ // layout that we sent back to WM.
+ private SplitDisplayLayout mRotateSplitLayout;
+
+ private final Handler mHandler;
+ private final WindowManagerProxy mWindowManagerProxy;
+
+ private final ArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners =
+ new ArrayList<>();
+
+ private final SplitScreenTaskOrganizer mSplits;
+ private final DisplayChangeController.OnDisplayChangingListener mRotationController;
+ private final DividerImeController mImePositionProcessor;
+ private final Context mContext;
+ private boolean mIsKeyguardShowing;
+
+ public DividerController(Context context,
+ DisplayController displayController, SystemWindows systemWindows,
+ DisplayImeController imeController, Handler handler, TransactionPool transactionPool) {
+ mContext = context;
+ mDisplayController = displayController;
+ mSystemWindows = systemWindows;
+ mImeController = imeController;
+ mHandler = handler;
+ mForcedResizableController = new ForcedResizableInfoActivityController(context, this);
+ mTransactionPool = transactionPool;
+ mWindowManagerProxy = new WindowManagerProxy(mTransactionPool, mHandler);
+ mSplits = new SplitScreenTaskOrganizer(this);
+ mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler);
+ mRotationController =
+ (display, fromRotation, toRotation, wct) -> {
+ if (!mSplits.isSplitScreenSupported() || mWindowManagerProxy == null) {
+ return;
+ }
+ WindowContainerTransaction t = new WindowContainerTransaction();
+ DisplayLayout displayLayout =
+ new DisplayLayout(mDisplayController.getDisplayLayout(display));
+ SplitDisplayLayout sdl =
+ new SplitDisplayLayout(mContext, displayLayout, mSplits);
+ sdl.rotateTo(toRotation);
+ mRotateSplitLayout = sdl;
+ final int position = isDividerVisible()
+ ? (mMinimized ? mView.mSnapTargetBeforeMinimized.position
+ : mView.getCurrentPosition())
+ // snap resets to middle target when not in split-mode
+ : sdl.getSnapAlgorithm().getMiddleTarget().position;
+ DividerSnapAlgorithm snap = sdl.getSnapAlgorithm();
+ final DividerSnapAlgorithm.SnapTarget target =
+ snap.calculateNonDismissingSnapTarget(position);
+ sdl.resizeSplits(target.position, t);
+
+ if (isSplitActive() && mHomeStackResizable) {
+ WindowManagerProxy
+ .applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t);
+ }
+ if (mWindowManagerProxy.queueSyncTransactionIfWaiting(t)) {
+ // Because sync transactions are serialized, its possible for an "older"
+ // bounds-change to get applied after a screen rotation. In that case, we
+ // want to actually defer on that rather than apply immediately. Of course,
+ // this means that the bounds may not change until after the rotation so
+ // the user might see some artifacts. This should be rare.
+ Slog.w(TAG, "Screen rotated while other operations were pending, this may"
+ + " result in some graphical artifacts.");
+ } else {
+ wct.merge(t, true /* transfer */);
+ }
+ };
+ }
+
+ /** Inits the divider service. */
+ public void start() {
+ mWindowManager = new DividerWindowManager(mSystemWindows);
+ mDisplayController.addDisplayWindowListener(this);
+ // Don't initialize the divider or anything until we get the default display.
+ }
+
+ /** Returns {@code true} if split screen is supported on the device. */
+ public boolean isSplitScreenSupported() {
+ return mSplits.isSplitScreenSupported();
+ }
+
+ /** Called when keyguard showing state changed. */
+ public void onKeyguardShowingChanged(boolean isShowing) {
+ if (!isSplitActive() || mView == null) {
+ return;
+ }
+ mView.setHidden(isShowing);
+ if (!isShowing) {
+ mImePositionProcessor.updateAdjustForIme();
+ }
+ mIsKeyguardShowing = isShowing;
+ }
+
+ @Override
+ public void onDisplayAdded(int displayId) {
+ if (displayId != DEFAULT_DISPLAY) {
+ return;
+ }
+ mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+ mDisplayController.getDisplayLayout(displayId), mSplits);
+ mImeController.addPositionProcessor(mImePositionProcessor);
+ mDisplayController.addDisplayChangingController(mRotationController);
+ if (!ActivityTaskManager.supportsSplitScreenMultiWindow(mContext)) {
+ removeDivider();
+ return;
+ }
+ try {
+ mSplits.init();
+ // Set starting tile bounds based on middle target
+ final WindowContainerTransaction tct = new WindowContainerTransaction();
+ int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+ mSplitLayout.resizeSplits(midPos, tct);
+ WindowOrganizer.applyTransaction(tct);
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to register docked stack listener", e);
+ removeDivider();
+ return;
+ }
+ }
+
+ @Override
+ public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+ if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
+ return;
+ }
+ mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+ mDisplayController.getDisplayLayout(displayId), mSplits);
+ if (mRotateSplitLayout == null) {
+ int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+ final WindowContainerTransaction tct = new WindowContainerTransaction();
+ mSplitLayout.resizeSplits(midPos, tct);
+ WindowOrganizer.applyTransaction(tct);
+ } else if (mSplitLayout.mDisplayLayout.rotation()
+ == mRotateSplitLayout.mDisplayLayout.rotation()) {
+ mSplitLayout.mPrimary = new Rect(mRotateSplitLayout.mPrimary);
+ mSplitLayout.mSecondary = new Rect(mRotateSplitLayout.mSecondary);
+ mRotateSplitLayout = null;
+ }
+ if (isSplitActive()) {
+ update(newConfig);
+ }
+ }
+
+ /** Posts task to handler dealing with divider. */
+ void post(Runnable task) {
+ mHandler.post(task);
+ }
+
+ /** Returns {@link DividerView}. */
+ public DividerView getDividerView() {
+ return mView;
+ }
+
+ /** Returns {@code true} if one of the split screen is in minimized mode. */
+ public boolean isMinimized() {
+ return mMinimized;
+ }
+
+ public boolean isHomeStackResizable() {
+ return mHomeStackResizable;
+ }
+
+ /** Returns {@code true} if the divider is visible. */
+ public boolean isDividerVisible() {
+ return mView != null && mView.getVisibility() == View.VISIBLE;
+ }
+
+ /**
+ * This indicates that at-least one of the splits has content. This differs from
+ * isDividerVisible because the divider is only visible once *everything* is in split mode
+ * while this only cares if some things are (eg. while entering/exiting as well).
+ */
+ private boolean isSplitActive() {
+ return mSplits.mPrimary != null && mSplits.mSecondary != null
+ && (mSplits.mPrimary.topActivityType != ACTIVITY_TYPE_UNDEFINED
+ || mSplits.mSecondary.topActivityType != ACTIVITY_TYPE_UNDEFINED);
+ }
+
+ private void addDivider(Configuration configuration) {
+ Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
+ mView = (DividerView)
+ LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
+ DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
+ mView.injectDependencies(mWindowManager, mDividerState, this, mSplits, mSplitLayout,
+ mImePositionProcessor, mWindowManagerProxy);
+ mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
+ mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, null /* transaction */);
+ final int size = dctx.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_divider_thickness);
+ final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
+ final int width = landscape ? size : displayLayout.width();
+ final int height = landscape ? displayLayout.height() : size;
+ mWindowManager.add(mView, width, height, mContext.getDisplayId());
+ }
+
+ private void removeDivider() {
+ if (mView != null) {
+ mView.onDividerRemoved();
+ }
+ mWindowManager.remove();
+ }
+
+ private void update(Configuration configuration) {
+ final boolean isDividerHidden = mView != null && mIsKeyguardShowing;
+
+ removeDivider();
+ addDivider(configuration);
+
+ if (mMinimized) {
+ mView.setMinimizedDockStack(true, mHomeStackResizable, null /* transaction */);
+ updateTouchable();
+ }
+ mView.setHidden(isDividerHidden);
+ }
+
+ void onTaskVanished() {
+ mHandler.post(this::removeDivider);
+ }
+
+ private void updateVisibility(final boolean visible) {
+ if (DEBUG) Slog.d(TAG, "Updating visibility " + mVisible + "->" + visible);
+ if (mVisible != visible) {
+ mVisible = visible;
+ mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+
+ if (visible) {
+ mView.enterSplitMode(mHomeStackResizable);
+ // Update state because animations won't finish.
+ mWindowManagerProxy.runInSync(
+ t -> mView.setMinimizedDockStack(mMinimized, mHomeStackResizable, t));
+
+ } else {
+ mView.exitSplitMode();
+ mWindowManagerProxy.runInSync(
+ t -> mView.setMinimizedDockStack(false, mHomeStackResizable, t));
+ }
+ // Notify existence listeners
+ synchronized (mDockedStackExistsListeners) {
+ mDockedStackExistsListeners.removeIf(wf -> {
+ Consumer<Boolean> l = wf.get();
+ if (l != null) l.accept(visible);
+ return l == null;
+ });
+ }
+ }
+ }
+
+ /** Switch to minimized state if appropriate. */
+ public void setMinimized(final boolean minimized) {
+ if (DEBUG) Slog.d(TAG, "posting ext setMinimized " + minimized + " vis:" + mVisible);
+ mHandler.post(() -> {
+ if (DEBUG) Slog.d(TAG, "run posted ext setMinimized " + minimized + " vis:" + mVisible);
+ if (!mVisible) {
+ return;
+ }
+ setHomeMinimized(minimized);
+ });
+ }
+
+ private void setHomeMinimized(final boolean minimized) {
+ if (DEBUG) {
+ Slog.d(TAG, "setHomeMinimized min:" + mMinimized + "->" + minimized + " hrsz:"
+ + mHomeStackResizable + " split:" + isDividerVisible());
+ }
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ final boolean minimizedChanged = mMinimized != minimized;
+ // Update minimized state
+ if (minimizedChanged) {
+ mMinimized = minimized;
+ }
+ // Always set this because we could be entering split when mMinimized is already true
+ wct.setFocusable(mSplits.mPrimary.token, !mMinimized);
+
+ // Sync state to DividerView if it exists.
+ if (mView != null) {
+ final int displayId = mView.getDisplay() != null
+ ? mView.getDisplay().getDisplayId() : DEFAULT_DISPLAY;
+ // pause ime here (before updateMinimizedDockedStack)
+ if (mMinimized) {
+ mImePositionProcessor.pause(displayId);
+ }
+ if (minimizedChanged) {
+ // This conflicts with IME adjustment, so only call it when things change.
+ mView.setMinimizedDockStack(minimized, getAnimDuration(), mHomeStackResizable);
+ }
+ if (!mMinimized) {
+ // afterwards so it can end any animations started in view
+ mImePositionProcessor.resume(displayId);
+ }
+ }
+ updateTouchable();
+
+ // If we are only setting focusability, a sync transaction isn't necessary (in fact it
+ // can interrupt other animations), so see if it can be submitted on pending instead.
+ if (!mWindowManagerProxy.queueSyncTransactionIfWaiting(wct)) {
+ WindowOrganizer.applyTransaction(wct);
+ }
+ }
+
+ void setAdjustedForIme(boolean adjustedForIme) {
+ if (mAdjustedForIme == adjustedForIme) {
+ return;
+ }
+ mAdjustedForIme = adjustedForIme;
+ updateTouchable();
+ }
+
+ private void updateTouchable() {
+ mWindowManager.setTouchable(!mAdjustedForIme);
+ }
+
+ /**
+ * Workaround for b/62528361, at the time recents has drawn, it may happen before a
+ * configuration change to the Divider, and internally, the event will be posted to the
+ * subscriber, or DividerView, which has been removed and prevented from resizing. Instead,
+ * register the event handler here and proxy the event to the current DividerView.
+ */
+ public void onRecentsDrawn() {
+ if (mView != null) {
+ mView.onRecentsDrawn();
+ }
+ }
+
+ /** Called when there's a task undocking. */
+ public void onUndockingTask() {
+ if (mView != null) {
+ mView.onUndockingTask();
+ }
+ }
+
+ /** Called when the first docked animation frame rendered. */
+ public void onDockedFirstAnimationFrame() {
+ if (mView != null) {
+ mView.onDockedFirstAnimationFrame();
+ }
+ }
+
+ /** Called when top task docked. */
+ public void onDockedTopTask() {
+ if (mView != null) {
+ mView.onDockedTopTask();
+ }
+ }
+
+ /** Called when app transition finished. */
+ public void onAppTransitionFinished() {
+ if (mView == null) {
+ return;
+ }
+ mForcedResizableController.onAppTransitionFinished();
+ }
+
+ @Override
+ public void onDraggingStart() {
+ mForcedResizableController.onDraggingStart();
+ }
+
+ @Override
+ public void onDraggingEnd() {
+ mForcedResizableController.onDraggingEnd();
+ }
+
+ /** Dumps current status of Divider.*/
+ public void dump(PrintWriter pw) {
+ pw.print(" mVisible="); pw.println(mVisible);
+ pw.print(" mMinimized="); pw.println(mMinimized);
+ pw.print(" mAdjustedForIme="); pw.println(mAdjustedForIme);
+ }
+
+ long getAnimDuration() {
+ float transitionScale = Settings.Global.getFloat(mContext.getContentResolver(),
+ Settings.Global.TRANSITION_ANIMATION_SCALE,
+ mContext.getResources().getFloat(
+ com.android.internal.R.dimen
+ .config_appTransitionAnimationDurationScaleDefault));
+ final long transitionDuration = DEFAULT_APP_TRANSITION_DURATION;
+ return (long) (transitionDuration * transitionScale);
+ }
+
+ /** Registers listener that gets called whenever the existence of the divider changes. */
+ public void registerInSplitScreenListener(Consumer<Boolean> listener) {
+ listener.accept(isDividerVisible());
+ synchronized (mDockedStackExistsListeners) {
+ mDockedStackExistsListeners.add(new WeakReference<>(listener));
+ }
+ }
+
+ void startEnterSplit() {
+ update(mDisplayController.getDisplayContext(
+ mContext.getDisplayId()).getResources().getConfiguration());
+ // Set resizable directly here because applyEnterSplit already resizes home stack.
+ mHomeStackResizable = mWindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout);
+ }
+
+ void startDismissSplit() {
+ mWindowManagerProxy.applyDismissSplit(mSplits, mSplitLayout, true /* dismissOrMaximize */);
+ updateVisibility(false /* visible */);
+ mMinimized = false;
+ removeDivider();
+ mImePositionProcessor.reset();
+ }
+
+ void ensureMinimizedSplit() {
+ setHomeMinimized(true /* minimized */);
+ if (mView != null && !isDividerVisible()) {
+ // Wasn't in split-mode yet, so enter now.
+ if (DEBUG) {
+ Slog.d(TAG, " entering split mode with minimized=true");
+ }
+ updateVisibility(true /* visible */);
+ }
+ }
+
+ void ensureNormalSplit() {
+ setHomeMinimized(false /* minimized */);
+ if (mView != null && !isDividerVisible()) {
+ // Wasn't in split-mode, so enter now.
+ if (DEBUG) {
+ Slog.d(TAG, " enter split mode unminimized ");
+ }
+ updateVisibility(true /* visible */);
+ }
+ }
+
+ SplitDisplayLayout getSplitLayout() {
+ return mSplitLayout;
+ }
+
+ WindowManagerProxy getWmProxy() {
+ return mWindowManagerProxy;
+ }
+
+ /** @return the container token for the secondary split root task. */
+ public WindowContainerToken getSecondaryRoot() {
+ if (mSplits == null || mSplits.mSecondary == null) {
+ return null;
+ }
+ return mSplits.mSecondary.token;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
index d5f7b39b8e61..a10242a689a2 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java
@@ -34,7 +34,7 @@ import com.android.systemui.R;
/**
* View for the handle in the docked stack divider.
*/
-public class DividerHandleView extends View {
+class DividerHandleView extends View {
private final static Property<DividerHandleView, Integer> WIDTH_PROPERTY
= new Property<DividerHandleView, Integer>(Integer.class, "width") {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
index 84ec38744e98..c915f071297f 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerImeController.java
@@ -38,7 +38,7 @@ import com.android.wm.shell.common.TransactionPool;
class DividerImeController implements DisplayImeController.ImePositionProcessor {
private static final String TAG = "DividerImeController";
- private static final boolean DEBUG = Divider.DEBUG;
+ private static final boolean DEBUG = DividerController.DEBUG;
private static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
@@ -100,15 +100,15 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
}
private DividerView getView() {
- return mSplits.mDivider.getView();
+ return mSplits.mDividerController.getDividerView();
}
private SplitDisplayLayout getLayout() {
- return mSplits.mDivider.getSplitLayout();
+ return mSplits.mDividerController.getSplitLayout();
}
private boolean isDividerVisible() {
- return mSplits.mDivider.isDividerVisible();
+ return mSplits.mDividerController.isDividerVisible();
}
private boolean getSecondaryHasFocus(int displayId) {
@@ -151,7 +151,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
mSecondaryHasFocus = getSecondaryHasFocus(displayId);
final boolean targetAdjusted = splitIsVisible && imeShouldShow && mSecondaryHasFocus
&& !imeIsFloating && !getLayout().mDisplayLayout.isLandscape()
- && !mSplits.mDivider.isMinimized();
+ && !mSplits.mDividerController.isMinimized();
if (mLastAdjustTop < 0) {
mLastAdjustTop = imeShouldShow ? hiddenTop : shownTop;
} else if (mLastAdjustTop != (imeShouldShow ? mShownTop : mHiddenTop)) {
@@ -236,7 +236,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
}
- if (!mSplits.mDivider.getWmProxy().queueSyncTransactionIfWaiting(wct)) {
+ if (!mSplits.mDividerController.getWmProxy().queueSyncTransactionIfWaiting(wct)) {
WindowOrganizer.applyTransaction(wct);
}
}
@@ -250,7 +250,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
: DisplayImeController.ANIMATION_DURATION_HIDE_MS);
}
}
- mSplits.mDivider.setAdjustedForIme(mTargetShown && !mPaused);
+ mSplits.mDividerController.setAdjustedForIme(mTargetShown && !mPaused);
}
public void updateAdjustForIme() {
@@ -343,10 +343,12 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
mAnimation.setInterpolator(DisplayImeController.INTERPOLATOR);
mAnimation.addListener(new AnimatorListenerAdapter() {
private boolean mCancel = false;
+
@Override
public void onAnimationCancel(Animator animation) {
mCancel = true;
}
+
@Override
public void onAnimationEnd(Animator animation) {
SurfaceControl.Transaction t = mTransactionPool.acquire();
@@ -400,7 +402,8 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor
mTargetAdjusted = mPausedTargetAdjusted;
updateDimTargets();
final DividerView view = getView();
- if ((mTargetAdjusted != mAdjusted) && !mSplits.mDivider.isMinimized() && view != null) {
+ if ((mTargetAdjusted != mAdjusted) && !mSplits.mDividerController.isMinimized()
+ && view != null) {
// End unminimize animations since they conflict with adjustment animations.
view.finishAnimations();
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
index c24431c22d62..db0aef8a0611 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
@@ -20,18 +20,14 @@ import android.content.Context;
import android.os.Handler;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.recents.Recents;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TransactionPool;
-import java.util.Optional;
-
import javax.inject.Singleton;
-import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
@@ -42,11 +38,12 @@ import dagger.Provides;
public class DividerModule {
@Singleton
@Provides
- static Divider provideDivider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy,
- DisplayController displayController, SystemWindows systemWindows,
- DisplayImeController imeController, @Main Handler handler,
+ static Divider provideDivider(Context context, DisplayController displayController,
+ SystemWindows systemWindows, DisplayImeController imeController, @Main Handler handler,
KeyguardStateController keyguardStateController, TransactionPool transactionPool) {
- return new Divider(context, recentsOptionalLazy, displayController, systemWindows,
- imeController, handler, keyguardStateController, transactionPool);
+ // TODO(b/161116823): fetch DividerProxy from WM shell lib.
+ DividerController dividerController = new DividerController(context, displayController,
+ systemWindows, imeController, handler, transactionPool);
+ return new Divider(context, dividerController, keyguardStateController);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
index 3a5c61e6d7f0..8e79d51ee209 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerState.java
@@ -21,6 +21,5 @@ package com.android.systemui.stackdivider;
*/
public class DividerState {
public boolean animateAfterRecentsDrawn;
- public boolean growAfterRecentsDrawn;
public float mRatioPositionBeforeMinimized;
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index b6c6afd523b3..e5c02d6fc454 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -76,12 +76,11 @@ import java.util.function.Consumer;
public class DividerView extends FrameLayout implements OnTouchListener,
OnComputeInternalInsetsListener {
private static final String TAG = "DividerView";
- private static final boolean DEBUG = Divider.DEBUG;
+ private static final boolean DEBUG = DividerController.DEBUG;
public interface DividerCallbacks {
void onDraggingStart();
void onDraggingEnd();
- void growRecents();
}
static final long TOUCH_ANIMATION_DURATION = 150;
@@ -148,7 +147,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private DividerCallbacks mCallback;
private final AnimationHandler mAnimationHandler = new AnimationHandler();
- private boolean mGrowRecents;
private ValueAnimator mCurrentAnimator;
private boolean mEntranceAnimationRunning;
private boolean mExitAnimationRunning;
@@ -304,7 +302,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
R.dimen.docked_stack_divider_lift_elevation);
mLongPressEntraceAnimDuration = getResources().getInteger(
R.integer.long_press_dock_anim_duration);
- mGrowRecents = getResources().getBoolean(R.bool.recents_grow_in_multiwindow);
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
mFlingAnimationUtils = new FlingAnimationUtils(getResources().getDisplayMetrics(), 0.3f);
boolean landscape = getResources().getConfiguration().orientation
@@ -437,17 +434,17 @@ public class DividerView extends FrameLayout implements OnTouchListener,
releaseBackground();
}
- public void stopDragging(int position, SnapTarget target, long duration,
+ private void stopDragging(int position, SnapTarget target, long duration,
Interpolator interpolator) {
stopDragging(position, target, duration, 0 /* startDelay*/, 0 /* endDelay */, interpolator);
}
- public void stopDragging(int position, SnapTarget target, long duration,
+ private void stopDragging(int position, SnapTarget target, long duration,
Interpolator interpolator, long endDelay) {
stopDragging(position, target, duration, 0 /* startDelay*/, endDelay, interpolator);
}
- public void stopDragging(int position, SnapTarget target, long duration, long startDelay,
+ private void stopDragging(int position, SnapTarget target, long duration, long startDelay,
long endDelay, Interpolator interpolator) {
mHandle.setTouching(false, true /* animate */);
flingTo(position, target, duration, startDelay, endDelay, interpolator);
@@ -1319,39 +1316,11 @@ public class DividerView extends FrameLayout implements OnTouchListener,
mBackground.getRight(), mBackground.getBottom(), Op.UNION);
}
- /**
- * Checks whether recents will grow when invoked. This happens in multi-window when recents is
- * very small. When invoking recents, we shrink the docked stack so recents has more space.
- *
- * @return the position of the divider when recents grows, or
- * {@link #INVALID_RECENTS_GROW_TARGET} if recents won't grow
- */
- public int growsRecents() {
- boolean result = mGrowRecents
- && mDockSide == WindowManager.DOCKED_TOP
- && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position;
- if (result) {
- return getSnapAlgorithm().getMiddleTarget().position;
- } else {
- return INVALID_RECENTS_GROW_TARGET;
- }
- }
-
- void onRecentsActivityStarting() {
- if (mGrowRecents && mDockSide == WindowManager.DOCKED_TOP
- && getSnapAlgorithm().getMiddleTarget() != getSnapAlgorithm().getLastSplitTarget()
- && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
- mState.growAfterRecentsDrawn = true;
- startDragging(false /* animate */, false /* touching */);
- }
- }
-
void onDockedFirstAnimationFrame() {
saveSnapTargetBeforeMinimized(mSplitLayout.getSnapAlgorithm().getMiddleTarget());
}
void onDockedTopTask() {
- mState.growAfterRecentsDrawn = false;
mState.animateAfterRecentsDrawn = true;
startDragging(false /* animate */, false /* touching */);
updateDockSide();
@@ -1377,15 +1346,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
200 /* endDelay */);
});
}
- if (mState.growAfterRecentsDrawn) {
- mState.growAfterRecentsDrawn = false;
- updateDockSide();
- if (mCallback != null) {
- mCallback.growRecents();
- }
- stopDragging(position, getSnapAlgorithm().getMiddleTarget(), 336,
- Interpolators.FAST_OUT_SLOW_IN);
- }
}
void onUndockingTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index db7996eed7f0..f412cc00981b 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -75,7 +75,8 @@ public class ForcedResizableInfoActivityController {
}
}
- public ForcedResizableInfoActivityController(Context context, Divider divider) {
+ public ForcedResizableInfoActivityController(Context context,
+ DividerController dividerController) {
mContext = context;
ActivityManagerWrapper.getInstance().registerTaskStackListener(
new TaskStackChangeListener() {
@@ -95,7 +96,7 @@ public class ForcedResizableInfoActivityController {
activityLaunchOnSecondaryDisplayFailed();
}
});
- divider.registerInSplitScreenListener(mDockedStackExistsListener);
+ dividerController.registerInSplitScreenListener(mDockedStackExistsListener);
}
public void onAppTransitionFinished() {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index 7a313dc0622b..ef5e8a15882c 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -35,7 +35,7 @@ import android.window.TaskOrganizer;
class SplitScreenTaskOrganizer extends TaskOrganizer {
private static final String TAG = "SplitScreenTaskOrg";
- private static final boolean DEBUG = Divider.DEBUG;
+ private static final boolean DEBUG = DividerController.DEBUG;
RunningTaskInfo mPrimary;
RunningTaskInfo mSecondary;
@@ -44,13 +44,13 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
SurfaceControl mPrimaryDim;
SurfaceControl mSecondaryDim;
Rect mHomeBounds = new Rect();
- final Divider mDivider;
+ final DividerController mDividerController;
private boolean mSplitScreenSupported = false;
final SurfaceSession mSurfaceSession = new SurfaceSession();
- SplitScreenTaskOrganizer(Divider divider) {
- mDivider = divider;
+ SplitScreenTaskOrganizer(DividerController dividerController) {
+ mDividerController = dividerController;
}
void init() throws RemoteException {
@@ -75,11 +75,11 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
}
SurfaceControl.Transaction getTransaction() {
- return mDivider.mTransactionPool.acquire();
+ return mDividerController.mTransactionPool.acquire();
}
void releaseTransaction(SurfaceControl.Transaction t) {
- mDivider.mTransactionPool.release(t);
+ mDividerController.mTransactionPool.release(t);
}
@Override
@@ -140,7 +140,7 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
t.apply();
releaseTransaction(t);
- mDivider.onTaskVanished();
+ mDividerController.onTaskVanished();
}
}
}
@@ -150,7 +150,7 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
if (taskInfo.displayId != DEFAULT_DISPLAY) {
return;
}
- mDivider.getHandler().post(() -> handleTaskInfoChanged(taskInfo));
+ mDividerController.post(() -> handleTaskInfoChanged(taskInfo));
}
/**
@@ -169,7 +169,7 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
}
final boolean secondaryImpliedMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
|| (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
- && mDivider.isHomeStackResizable());
+ && mDividerController.isHomeStackResizable());
final boolean primaryWasEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
final boolean secondaryWasEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
if (info.token.asBinder() == mPrimary.token.asBinder()) {
@@ -181,7 +181,7 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
final boolean secondaryIsEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
final boolean secondaryImpliesMinimize = mSecondary.topActivityType == ACTIVITY_TYPE_HOME
|| (mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS
- && mDivider.isHomeStackResizable());
+ && mDividerController.isHomeStackResizable());
if (DEBUG) {
Log.d(TAG, "onTaskInfoChanged " + mPrimary + " " + mSecondary);
}
@@ -197,14 +197,14 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
Log.d(TAG, " at-least one split empty " + mPrimary.topActivityType
+ " " + mSecondary.topActivityType);
}
- if (mDivider.isDividerVisible()) {
+ if (mDividerController.isDividerVisible()) {
// Was in split-mode, which means we are leaving split, so continue that.
// This happens when the stack in the primary-split is dismissed.
if (DEBUG) {
Log.d(TAG, " was in split, so this means leave it "
+ mPrimary.topActivityType + " " + mSecondary.topActivityType);
}
- mDivider.startDismissSplit();
+ mDividerController.startDismissSplit();
} else if (!primaryIsEmpty && primaryWasEmpty && secondaryWasEmpty) {
// Wasn't in split-mode (both were empty), but now that the primary split is
// populated, we should fully enter split by moving everything else into secondary.
@@ -213,15 +213,15 @@ class SplitScreenTaskOrganizer extends TaskOrganizer {
if (DEBUG) {
Log.d(TAG, " was not in split, but primary is populated, so enter it");
}
- mDivider.startEnterSplit();
+ mDividerController.startEnterSplit();
}
} else if (secondaryImpliesMinimize) {
// Both splits are populated but the secondary split has a home/recents stack on top,
// so enter minimized mode.
- mDivider.ensureMinimizedSplit();
+ mDividerController.ensureMinimizedSplit();
} else {
// Both splits are populated by normal activities, so make sure we aren't minimized.
- mDivider.ensureNormalSplit();
+ mDividerController.ensureNormalSplit();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java
index 6812f62422a7..f2500e59abab 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SyncTransactionQueue.java
@@ -33,7 +33,7 @@ import java.util.ArrayList;
* Helper for serializing sync-transactions and corresponding callbacks.
*/
class SyncTransactionQueue {
- private static final boolean DEBUG = Divider.DEBUG;
+ private static final boolean DEBUG = DividerController.DEBUG;
private static final String TAG = "SyncTransactionQueue";
// Just a little longer than the sync-engine timeout of 5s
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 2b3681281064..82b10bd40b17 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -50,7 +50,7 @@ import java.util.concurrent.Executors;
/**
* Proxy to simplify calls into window manager/activity manager
*/
-public class WindowManagerProxy {
+class WindowManagerProxy {
private static final String TAG = "WindowManagerProxy";
private static final int[] HOME_AND_RECENTS = {ACTIVITY_TYPE_HOME, ACTIVITY_TYPE_RECENTS};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
index ca0f62ea7538..b813b6280c12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
@@ -20,9 +20,16 @@ import static android.service.notification.NotificationListenerService.Ranking;
import android.content.ContentResolver;
import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import javax.inject.Inject;
@@ -35,23 +42,42 @@ import javax.inject.Singleton;
* should show an indicator.
*/
@Singleton
-public class AssistantFeedbackController {
+public class AssistantFeedbackController extends ContentObserver {
+ private final Uri FEEDBACK_URI
+ = Settings.Global.getUriFor(Settings.Global.NOTIFICATION_FEEDBACK_ENABLED);
private ContentResolver mResolver;
+ private boolean mFeedbackEnabled;
+
/** Injected constructor */
@Inject
public AssistantFeedbackController(Context context) {
+ super(new Handler(Looper.getMainLooper()));
mResolver = context.getContentResolver();
+ mResolver.registerContentObserver(FEEDBACK_URI, false, this, UserHandle.USER_ALL);
+ update(null);
+ }
+
+ @Override
+ public void onChange(boolean selfChange, @Nullable Uri uri, int flags) {
+ update(uri);
+ }
+
+ @VisibleForTesting
+ public void update(@Nullable Uri uri) {
+ if (uri == null || FEEDBACK_URI.equals(uri)) {
+ mFeedbackEnabled = Settings.Global.getInt(mResolver,
+ Settings.Global.NOTIFICATION_FEEDBACK_ENABLED, 0)
+ != 0;
+ }
}
/**
* Determines whether to show any user controls related to the assistant. This is based on the
- * settings flag {@link Settings.Secure.NOTIFICATION_FEEDBACK_ENABLED}
+ * settings flag {@link Settings.Global.NOTIFICATION_FEEDBACK_ENABLED}
*/
public boolean isFeedbackEnabled() {
- return Settings.Secure.getIntForUser(mResolver,
- Settings.Secure.NOTIFICATION_FEEDBACK_ENABLED, 0,
- UserHandle.USER_CURRENT) == 1;
+ return mFeedbackEnabled;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index aba9e1005559..e1ff872456eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -15,7 +15,6 @@
*/
package com.android.systemui.statusbar.notification;
-import static android.service.notification.NotificationListenerService.REASON_CANCEL;
import static android.service.notification.NotificationListenerService.REASON_ERROR;
import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_UNKNOWN;
@@ -24,14 +23,11 @@ import static com.android.systemui.statusbar.notification.row.NotificationRowCon
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
-import android.content.Context;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
-import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -41,7 +37,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dumpable;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationListener;
@@ -54,11 +49,11 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.Assert;
import com.android.systemui.util.leak.LeakDetector;
@@ -147,8 +142,6 @@ public class NotificationEntryManager implements
private final NotificationRankingManager mRankingManager;
private final FeatureFlags mFeatureFlags;
private final ForegroundServiceDismissalFeatureController mFgsFeatureController;
- private final HeadsUpManager mHeadsUpManager;
- private final StatusBarStateController mStatusBarStateController;
private NotificationPresenter mPresenter;
private RankingMap mLatestRankingMap;
@@ -213,8 +206,7 @@ public class NotificationEntryManager implements
Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
LeakDetector leakDetector,
ForegroundServiceDismissalFeatureController fgsFeatureController,
- HeadsUpManager headsUpManager,
- StatusBarStateController statusBarStateController
+ IStatusBarService statusBarService
) {
mLogger = logger;
mGroupManager = groupManager;
@@ -225,11 +217,7 @@ public class NotificationEntryManager implements
mRemoteInputManagerLazy = notificationRemoteInputManagerLazy;
mLeakDetector = leakDetector;
mFgsFeatureController = fgsFeatureController;
- mHeadsUpManager = headsUpManager;
- mStatusBarStateController = statusBarStateController;
-
- mStatusBarService = IStatusBarService.Stub.asInterface(
- ServiceManager.checkService(Context.STATUS_BAR_SERVICE));
+ mStatusBarService = statusBarService;
}
/** Once called, the NEM will start processing notification events from system server. */
@@ -284,16 +272,23 @@ public class NotificationEntryManager implements
}
/**
- * Requests a notification to be removed.
+ * User requests a notification to be removed.
*
* @param n the notification to remove.
* @param reason why it is being removed e.g. {@link NotificationListenerService#REASON_CANCEL},
* or 0 if unknown.
*/
- public void performRemoveNotification(StatusBarNotification n, int reason) {
- final NotificationVisibility nv = obtainVisibility(n.getKey());
+ public void performRemoveNotification(
+ StatusBarNotification n,
+ @NonNull DismissedByUserStats stats,
+ int reason
+ ) {
removeNotificationInternal(
- n.getKey(), null, nv, false /* forceRemove */, true /* removedByUser */,
+ n.getKey(),
+ null,
+ stats.notificationVisibility,
+ false /* forceRemove */,
+ stats,
reason);
}
@@ -337,7 +332,11 @@ public class NotificationEntryManager implements
*/
private void handleInflationException(StatusBarNotification n, Exception e) {
removeNotificationInternal(
- n.getKey(), null, null, true /* forceRemove */, false /* removedByUser */,
+ n.getKey(),
+ null,
+ null,
+ true /* forceRemove */,
+ null /* dismissedByUserStats */,
REASON_ERROR);
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onInflationError(n, e);
@@ -435,19 +434,28 @@ public class NotificationEntryManager implements
reapplyFilterAndSort("addVisibleNotification");
}
-
- public void removeNotification(String key, RankingMap ranking,
- int reason) {
- removeNotificationInternal(key, ranking, obtainVisibility(key), false /* forceRemove */,
- false /* removedByUser */, reason);
+ @VisibleForTesting
+ protected void removeNotification(String key, RankingMap ranking, int reason) {
+ removeNotificationInternal(
+ key,
+ ranking,
+ obtainVisibility(key),
+ false /* forceRemove */,
+ null /* dismissedByUserStats */,
+ reason);
}
+ /**
+ * Internally remove a notification because system server has reported the notification
+ * should be removed OR the user has manually dismissed the notification
+ * @param dismissedByUserStats non-null if the user manually dismissed the notification
+ */
private void removeNotificationInternal(
String key,
@Nullable RankingMap ranking,
@Nullable NotificationVisibility visibility,
boolean forceRemove,
- boolean removedByUser,
+ DismissedByUserStats dismissedByUserStats,
int reason) {
final NotificationEntry entry = getActiveNotificationUnfiltered(key);
@@ -512,11 +520,11 @@ public class NotificationEntryManager implements
handleGroupSummaryRemoved(key);
removeVisibleNotification(key);
updateNotifications("removeNotificationInternal");
- removedByUser |= entryDismissed;
+ final boolean removedByUser = dismissedByUserStats != null;
mLogger.logNotifRemoved(entry.getKey(), removedByUser);
if (removedByUser && visibility != null) {
- sendNotificationRemovalToServer(entry.getKey(), entry.getSbn(), visibility);
+ sendNotificationRemovalToServer(entry.getSbn(), dismissedByUserStats);
}
for (NotificationEntryListener listener : mNotificationEntryListeners) {
listener.onEntryRemoved(entry, visibility, removedByUser, reason);
@@ -534,30 +542,18 @@ public class NotificationEntryManager implements
}
private void sendNotificationRemovalToServer(
- String key,
StatusBarNotification notification,
- NotificationVisibility nv) {
- final String pkg = notification.getPackageName();
- final String tag = notification.getTag();
- final int id = notification.getId();
- final int userId = notification.getUser().getIdentifier();
+ DismissedByUserStats dismissedByUserStats) {
try {
- int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
- if (mHeadsUpManager.isAlerting(key)) {
- dismissalSurface = NotificationStats.DISMISSAL_PEEK;
- } else if (mStatusBarStateController.isDozing()) {
- dismissalSurface = NotificationStats.DISMISSAL_AOD;
- }
- int dismissalSentiment = NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
mStatusBarService.onNotificationClear(
- pkg,
- tag,
- id,
- userId,
+ notification.getPackageName(),
+ notification.getTag(),
+ notification.getId(),
+ notification.getUser().getIdentifier(),
notification.getKey(),
- dismissalSurface,
- dismissalSentiment,
- nv);
+ dismissedByUserStats.dismissalSurface,
+ dismissedByUserStats.dismissalSentiment,
+ dismissedByUserStats.notificationVisibility);
} catch (RemoteException ex) {
// system process is dead if we're here.
}
@@ -641,11 +637,7 @@ public class NotificationEntryManager implements
// Construct the expanded view.
if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
- mNotificationRowBinderLazy.get()
- .inflateViews(
- entry,
- () -> performRemoveNotification(notification, REASON_CANCEL),
- mInflationCallback);
+ mNotificationRowBinderLazy.get().inflateViews(entry, mInflationCallback);
}
mPendingNotifications.put(key, entry);
@@ -675,7 +667,7 @@ public class NotificationEntryManager implements
final String key = notification.getKey();
abortExistingInflation(key, "updateNotification");
- NotificationEntry entry = getActiveNotificationUnfiltered(key);
+ final NotificationEntry entry = getActiveNotificationUnfiltered(key);
if (entry == null) {
return;
}
@@ -701,11 +693,7 @@ public class NotificationEntryManager implements
}
if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
- mNotificationRowBinderLazy.get()
- .inflateViews(
- entry,
- () -> performRemoveNotification(notification, REASON_CANCEL),
- mInflationCallback);
+ mNotificationRowBinderLazy.get().inflateViews(entry, mInflationCallback);
}
updateNotifications("updateNotificationInternal");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
index 81494eddd989..0ea685793214 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
@@ -19,7 +19,6 @@ package com.android.systemui.statusbar.notification.collection;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.notification.collection.coordinator.PreparationCoordinator;
import java.util.ArrayList;
@@ -39,9 +38,8 @@ public class GroupEntry extends ListEntry {
Collections.unmodifiableList(mChildren);
private int mUntruncatedChildCount;
- @VisibleForTesting
- public GroupEntry(String key) {
- super(key);
+ GroupEntry(String key, long creationTime) {
+ super(key, creationTime);
}
@Override
@@ -59,8 +57,7 @@ public class GroupEntry extends ListEntry {
return mUnmodifiableChildren;
}
- @VisibleForTesting
- public void setSummary(@Nullable NotificationEntry summary) {
+ void setSummary(@Nullable NotificationEntry summary) {
mSummary = summary;
}
@@ -98,6 +95,6 @@ public class GroupEntry extends ListEntry {
return mChildren;
}
- public static final GroupEntry ROOT_ENTRY = new GroupEntry("<root>");
+ public static final GroupEntry ROOT_ENTRY = new GroupEntry("<root>", 0);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
index 97c1523887ad..3a0520115d67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
@@ -19,6 +19,8 @@ package com.android.systemui.statusbar.notification.collection;
import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_NOT_CANCELED;
import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.NOT_DISMISSED;
+import static java.util.Objects.requireNonNull;
+
import com.android.systemui.statusbar.NotificationInteractionTracker;
import java.util.Arrays;
@@ -56,7 +58,7 @@ public class ListDumper {
List<NotificationEntry> children = ge.getChildren();
for (int childIndex = 0; childIndex < children.size(); childIndex++) {
dumpEntry(children.get(childIndex),
- Integer.toString(topEntryIndex) + "." + Integer.toString(childIndex),
+ topEntryIndex + "." + childIndex,
childEntryIndent,
sb,
true,
@@ -118,7 +120,7 @@ public class ListDumper {
}
if (includeRecordKeeping) {
- NotificationEntry notifEntry = entry.getRepresentativeEntry();
+ NotificationEntry notifEntry = requireNonNull(entry.getRepresentativeEntry());
StringBuilder rksb = new StringBuilder();
if (!notifEntry.mLifetimeExtenders.isEmpty()) {
@@ -165,7 +167,9 @@ public class ListDumper {
.append(" ");
}
- rksb.append("interacted=").append(hasBeenInteractedWith ? "yes" : "no").append(" ");
+ if (hasBeenInteractedWith) {
+ rksb.append("interacted=yes ");
+ }
String rkString = rksb.toString();
if (!rkString.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index 837374fe2201..65f5dc4e5f7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar.notification.collection;
+import android.annotation.UptimeMillisLong;
+
import androidx.annotation.Nullable;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
@@ -27,14 +29,16 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
*/
public abstract class ListEntry {
private final String mKey;
+ private final long mCreationTime;
int mFirstAddedIteration = -1;
private final ListAttachState mPreviousAttachState = ListAttachState.create();
private final ListAttachState mAttachState = ListAttachState.create();
- ListEntry(String key) {
+ ListEntry(String key, long creationTime) {
mKey = key;
+ mCreationTime = creationTime;
}
public String getKey() {
@@ -42,6 +46,19 @@ public abstract class ListEntry {
}
/**
+ * The SystemClock.uptimeMillis() when this object was created. In general, this means the
+ * moment when NotificationManager notifies our listener about the existence of this entry.
+ *
+ * This value will not change if the notification is updated, although it will change if the
+ * notification is removed and then re-posted. It is also wholly independent from
+ * Notification#when.
+ */
+ @UptimeMillisLong
+ public long getCreationTime() {
+ return mCreationTime;
+ }
+
+ /**
* Should return the "representative entry" for this ListEntry. For NotificationEntries, its
* the entry itself. For groups, it should be the summary (but if a summary doesn't exist,
* this can return null). This method exists to interface with
@@ -79,6 +96,14 @@ public abstract class ListEntry {
}
/**
+ * True if this entry has been attached to the shade at least once in its lifetime (it may not
+ * currently be attached).
+ */
+ public boolean hasBeenAttachedBefore() {
+ return mFirstAddedIteration != -1;
+ }
+
+ /**
* Stores the current attach state into {@link #getPreviousAttachState()}} and then starts a
* fresh attach state (all entries will be null/default-initialized).
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
index d081e114855e..aaf5c4d6594b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
@@ -16,17 +16,10 @@
package com.android.systemui.statusbar.notification.collection;
-import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
-
-import android.service.notification.NotificationStats;
-
import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
-import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
@@ -81,7 +74,6 @@ public class NotifInflaterImpl implements NotifInflater {
try {
requireBinder().inflateViews(
entry,
- getDismissCallback(entry),
wrapInflationCallback(callback));
} catch (InflationException e) {
mNotifErrorManager.setInflationError(entry, e);
@@ -93,30 +85,6 @@ public class NotifInflaterImpl implements NotifInflater {
entry.abortTask();
}
- private Runnable getDismissCallback(NotificationEntry entry) {
- return new Runnable() {
- @Override
- public void run() {
- int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
- /*
- * TODO: determine dismissal surface (ie: shade / headsup / aod)
- * see {@link NotificationLogger#logNotificationClear}
- */
- mNotifCollection.dismissNotification(
- entry,
- new DismissedByUserStats(
- dismissalSurface,
- DISMISS_SENTIMENT_NEUTRAL,
- NotificationVisibility.obtain(entry.getKey(),
- entry.getRanking().getRank(),
- mNotifPipeline.getShadeListCount(),
- true,
- NotificationLogger.getNotificationLocation(entry))
- ));
- }
- };
- }
-
private NotificationContentInflater.InflationCallback wrapInflationCallback(
InflationCallback callback) {
return new NotificationContentInflater.InflationCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt
deleted file mode 100644
index 339809e0770b..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.collection
-
-import android.annotation.MainThread
-import android.view.ViewGroup
-
-import com.android.systemui.statusbar.FeatureFlags
-import com.android.systemui.statusbar.notification.VisualStabilityManager
-import com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY
-import com.android.systemui.statusbar.notification.stack.NotificationListItem
-import com.android.systemui.util.Assert
-
-import java.io.FileDescriptor
-import java.io.PrintWriter
-import java.lang.IllegalStateException
-import javax.inject.Inject
-import javax.inject.Singleton
-
-/**
- * A consumer of a Notification tree built by [ShadeListBuilder] which will update the notification
- * presenter with the minimum operations required to make the old tree match the new one
- */
-@MainThread
-@Singleton
-class NotifViewManager @Inject constructor(
- private val rowRegistry: NotifViewBarn,
- private val stabilityManager: VisualStabilityManager,
- private val featureFlags: FeatureFlags
-) {
- var currentNotifs = listOf<ListEntry>()
-
- private lateinit var listContainer: SimpleNotificationListContainer
-
- fun attach(listBuilder: ShadeListBuilder) {
- if (featureFlags.isNewNotifPipelineRenderingEnabled) {
- listBuilder.setOnRenderListListener { entries: List<ListEntry> ->
- this.onNotifTreeBuilt(entries)
- }
- }
- }
-
- fun setViewConsumer(consumer: SimpleNotificationListContainer) {
- listContainer = consumer
- }
-
- /**
- * Callback for when the tree is rebuilt
- */
- fun onNotifTreeBuilt(notifList: List<ListEntry>) {
- Assert.isMainThread()
-
- /*
- * The assumption here is that anything from the old NotificationViewHierarchyManager that
- * is responsible for filtering is done via the NotifFilter logic. This tree we get should
- * be *the stuff to display* +/- redacted stuff
- */
-
- detachRows(notifList)
- attachRows(notifList)
-
- currentNotifs = notifList
- }
-
- private fun detachRows(entries: List<ListEntry>) {
- // To properly detach rows, we are looking to remove any view in the consumer that is not
- // present in the incoming list.
- //
- // Every listItem was top-level, so it's entry's parent was ROOT_ENTRY, but now
- // there are two possibilities:
- //
- // 1. It is not present in the entry list
- // 1a. It has moved to be a child in the entry list - transfer it
- // 1b. It is gone completely - remove it
- // 2. It is present in the entry list - diff the children
- getListItems(listContainer)
- .filter {
- // Ignore things that are showing the blocking helper
- !it.isBlockingHelperShowing
- }
- .forEach { listItem ->
- val noLongerTopLevel = listItem.entry.parent != ROOT_ENTRY
- val becameChild = noLongerTopLevel && listItem.entry.parent != null
-
- val idx = entries.indexOf(listItem.entry)
-
- if (noLongerTopLevel) {
- // Summaries won't become children; remove the whole group
- if (listItem.isSummaryWithChildren) {
- listItem.removeAllChildren()
- }
-
- if (becameChild) {
- // Top-level element is becoming a child, don't generate an animation
- listContainer.setChildTransferInProgress(true)
- }
- listContainer.removeListItem(listItem)
- listContainer.setChildTransferInProgress(false)
- } else if (entries[idx] is GroupEntry) {
- // A top-level entry exists. If it's a group, diff the children
- val groupChildren = (entries[idx] as GroupEntry).children
- listItem.attachedChildren?.forEach { listChild ->
- if (!groupChildren.contains(listChild.entry)) {
- listItem.removeChildNotification(listChild)
-
- // TODO: the old code only calls this if the notif is gone from
- // NEM.getActiveNotificationUnfiltered(). Do we care?
- listContainer.notifyGroupChildRemoved(
- listChild.view, listChild.view.parent as ViewGroup)
- }
- }
- }
- }
- }
-
- /** Convenience method for getting a sequence of [NotificationListItem]s */
- private fun getListItems(container: SimpleNotificationListContainer):
- Sequence<NotificationListItem> {
- return (0 until container.getContainerChildCount()).asSequence()
- .map { container.getContainerChildAt(it) }
- .filterIsInstance<NotificationListItem>()
- }
-
- private fun attachRows(entries: List<ListEntry>) {
-
- var orderChanged = false
-
- // To attach rows we can use _this one weird trick_: if the intended view to add does not
- // have a parent, then simply add it (and its children).
- entries.forEach { entry ->
- // TODO: We should eventually map GroupEntry's themselves to views so that we don't
- // depend on representativeEntry here which may actually be null in the future
- val listItem = rowRegistry.requireView(entry.representativeEntry!!)
-
- if (listItem.view.parent == null) {
- listContainer.addListItem(listItem)
- stabilityManager.notifyViewAddition(listItem.view)
- }
-
- if (entry is GroupEntry) {
- for ((idx, childEntry) in entry.children.withIndex()) {
- val childListItem = rowRegistry.requireView(childEntry)
- // Child hasn't been added yet. add it!
- if (listItem.attachedChildren == null ||
- !listItem.attachedChildren.contains(childListItem)) {
- // TODO: old code here just Log.wtf()'d here. This might wreak havoc
- if (childListItem.view.parent != null) {
- throw IllegalStateException("trying to add a notification child that " +
- "already has a parent. class: " +
- "${childListItem.view.parent?.javaClass} " +
- "\n child: ${childListItem.view}"
- )
- }
-
- listItem.addChildNotification(childListItem, idx)
- stabilityManager.notifyViewAddition(childListItem.view)
- listContainer.notifyGroupChildAdded(childListItem.view)
- }
- }
-
- // finally after removing and adding has been performed we can apply the order
- orderChanged = orderChanged ||
- listItem.applyChildOrder(
- getChildListFromParent(entry),
- stabilityManager,
- null /*TODO: stability callback */
- )
- listItem.setUntruncatedChildCount(entry.untruncatedChildCount)
- }
- }
-
- if (orderChanged) {
- listContainer.generateChildOrderChangedEvent()
- }
- }
-
- private fun getChildListFromParent(parent: ListEntry): List<NotificationListItem> {
- if (parent is GroupEntry) {
- return parent.children.map { child -> rowRegistry.requireView(child) }
- .toList()
- }
-
- return emptyList()
- }
-
- fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
- }
-}
-
-private const val TAG = "NotifViewDataSource" \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index bd65ef06f3a9..387247eb6c5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -35,7 +35,6 @@ import static com.android.systemui.statusbar.notification.stack.NotificationSect
import static java.util.Objects.requireNonNull;
-import android.annotation.CurrentTimeMillisLong;
import android.app.Notification;
import android.app.Notification.MessagingStyle.Message;
import android.app.NotificationChannel;
@@ -96,7 +95,6 @@ public final class NotificationEntry extends ListEntry {
private final String mKey;
private StatusBarNotification mSbn;
private Ranking mRanking;
- private long mCreationTime;
/*
* Bookkeeping members
@@ -198,11 +196,10 @@ public final class NotificationEntry extends ListEntry {
boolean allowFgsDismissal,
long creationTime
) {
- super(requireNonNull(requireNonNull(sbn).getKey()));
+ super(requireNonNull(requireNonNull(sbn).getKey()), creationTime);
requireNonNull(ranking);
- mCreationTime = creationTime;
mKey = sbn.getKey();
setSbn(sbn);
setRanking(ranking);
@@ -255,21 +252,6 @@ public final class NotificationEntry extends ListEntry {
}
/**
- * A timestamp of SystemClock.uptimeMillis() of when this entry was first created, regardless
- * of any changes to the data presented. It is set once on creation and will never change, and
- * allows us to know exactly how long this notification has been alive for in our listener
- * service. It is entirely unrelated to the information inside of the notification.
- *
- * This is different to Notification#when because it persists throughout updates, whereas
- * system server treats every single call to notify() as a new notification and we handle
- * updates to NotificationEntry locally.
- */
- @CurrentTimeMillisLong
- public long getCreationTime() {
- return mCreationTime;
- }
-
- /**
* Should only be called by NotificationEntryManager and friends.
* TODO: Make this package-private
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index a86ab41141a6..d45f89cb6fe5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -47,6 +47,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
import com.android.systemui.util.Assert;
import com.android.systemui.util.time.SystemClock;
@@ -321,6 +322,7 @@ public class ShadeListBuilder implements Dumpable {
mPipelineState.incrementTo(STATE_FINALIZING);
logChanges();
freeEmptyGroups();
+ cleanupPluggables();
// Step 8: Dispatch the new list, first to any listeners and then to the view layer
dispatchOnBeforeRenderList(mReadOnlyNotifList);
@@ -421,7 +423,7 @@ public class ShadeListBuilder implements Dumpable {
GroupEntry group = mGroups.get(topLevelKey);
if (group == null) {
- group = new GroupEntry(topLevelKey);
+ group = new GroupEntry(topLevelKey, mSystemClock.uptimeMillis());
group.mFirstAddedIteration = mIterationCount;
mGroups.put(topLevelKey, group);
}
@@ -673,6 +675,20 @@ public class ShadeListBuilder implements Dumpable {
}
}
+ private void cleanupPluggables() {
+ callOnCleanup(mNotifPreGroupFilters);
+ callOnCleanup(mNotifPromoters);
+ callOnCleanup(mNotifFinalizeFilters);
+ callOnCleanup(mNotifComparators);
+ callOnCleanup(mNotifSections);
+ }
+
+ private void callOnCleanup(List<? extends Pluggable<?>> pluggables) {
+ for (int i = 0; i < pluggables.size(); i++) {
+ pluggables.get(i).onCleanup();
+ }
+ }
+
private final Comparator<ListEntry> mTopLevelComparator = (o1, o2) -> {
int cmp = Integer.compare(o1.getSection(), o2.getSection());
@@ -849,7 +865,7 @@ public class ShadeListBuilder implements Dumpable {
}
};
- private static final String TAG = "NotifListBuilderImpl";
+ private static final String TAG = "ShadeListBuilder";
private static final int MIN_CHILDREN_FOR_GROUP = 2;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SimpleNotificationListContainer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SimpleNotificationListContainer.kt
deleted file mode 100644
index 2dbe555af519..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SimpleNotificationListContainer.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.collection
-
-import android.view.View
-import android.view.ViewGroup
-import com.android.systemui.statusbar.notification.stack.NotificationListItem
-
-/**
- * Minimal interface of what [NotifViewManager] needs from [NotificationListContainer]
- */
-interface SimpleNotificationListContainer {
- /** Called to signify that a top-level element is becoming a child in the shade */
- fun setChildTransferInProgress(b: Boolean)
- /** Used to generate a list of [NotificationListItem] */
- fun getContainerChildAt(i: Int): View
- /** Similar to above */
- fun getContainerChildCount(): Int
- /** Remove a [NotificationListItem] from the container */
- fun removeListItem(li: NotificationListItem)
- /** Add a [NotificationListItem] to the container */
- fun addListItem(li: NotificationListItem)
- /** Allows [NotifViewManager] to notify the container about a group child removal */
- fun notifyGroupChildRemoved(row: View, parent: ViewGroup)
- /** Allows [NotifViewManager] to notify the container about a group child addition */
- fun notifyGroupChildAdded(row: View)
- /** [NotifViewManager] calls this when the order of the children changes */
- fun generateChildOrderChangedEvent()
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
index 92426e54ec91..08462c183bd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
@@ -16,10 +16,6 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
-import static android.service.notification.NotificationStats.DISMISSAL_OTHER;
-import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
-
-import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -27,7 +23,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import java.util.HashSet;
import java.util.Set;
@@ -101,7 +96,6 @@ public class BubbleCoordinator implements Coordinator {
@Override
public boolean shouldInterceptDismissal(NotificationEntry entry) {
- // TODO: b/149041810 add support for intercepting app-cancelled bubble notifications
// for experimental bubbles
if (mBubbleController.handleDismissalInterception(entry)) {
mInterceptedDismissalEntries.add(entry.getKey());
@@ -121,17 +115,21 @@ public class BubbleCoordinator implements Coordinator {
private final BubbleController.NotifCallback mNotifCallback =
new BubbleController.NotifCallback() {
@Override
- public void removeNotification(NotificationEntry entry, int reason) {
+ public void removeNotification(
+ NotificationEntry entry,
+ DismissedByUserStats dismissedByUserStats,
+ int reason
+ ) {
if (isInterceptingDismissal(entry)) {
mInterceptedDismissalEntries.remove(entry.getKey());
mOnEndDismissInterception.onEndDismissInterception(mDismissInterceptor, entry,
- createDismissedByUserStats(entry));
+ dismissedByUserStats);
} else if (mNotifPipeline.getAllNotifs().contains(entry)) {
// Bubbles are hiding the notifications from the shade, but the bubble was
// deleted; therefore, the notification should be cancelled as if it were a user
// dismissal (this won't re-enter handleInterceptDimissal because Bubbles
// will have already marked it as no longer a bubble)
- mNotifCollection.dismissNotification(entry, createDismissedByUserStats(entry));
+ mNotifCollection.dismissNotification(entry, dismissedByUserStats);
}
}
@@ -149,16 +147,4 @@ public class BubbleCoordinator implements Coordinator {
private boolean isInterceptingDismissal(NotificationEntry entry) {
return mInterceptedDismissalEntries.contains(entry.getKey());
}
-
- private DismissedByUserStats createDismissedByUserStats(NotificationEntry entry) {
- return new DismissedByUserStats(
- DISMISSAL_OTHER,
- DISMISS_SENTIMENT_NEUTRAL,
- NotificationVisibility.obtain(entry.getKey(),
- entry.getRanking().getRank(),
- mNotifPipeline.getShadeListCount(),
- true, // was visible as a bubble
- NotificationLogger.getNotificationLocation(entry))
- );
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index b7738569ad3c..95ba759df547 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -64,6 +64,8 @@ public class KeyguardCoordinator implements Coordinator {
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final HighPriorityProvider mHighPriorityProvider;
+ private boolean mHideSilentNotificationsOnLockscreen;
+
@Inject
public KeyguardCoordinator(
Context context,
@@ -86,6 +88,8 @@ public class KeyguardCoordinator implements Coordinator {
@Override
public void attach(NotifPipeline pipeline) {
+ readShowSilentNotificationSetting();
+
setupInvalidateNotifListCallbacks();
pipeline.addFinalizeFilter(mNotifFilter);
}
@@ -147,7 +151,7 @@ public class KeyguardCoordinator implements Coordinator {
return false;
}
if (NotificationUtils.useNewInterruptionModel(mContext)
- && hideSilentNotificationsOnLockscreen()) {
+ && mHideSilentNotificationsOnLockscreen) {
return mHighPriorityProvider.isHighPriority(entry);
} else {
return entry.getRepresentativeEntry() != null
@@ -155,11 +159,6 @@ public class KeyguardCoordinator implements Coordinator {
}
}
- private boolean hideSilentNotificationsOnLockscreen() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0;
- }
-
private void setupInvalidateNotifListCallbacks() {
// register onKeyguardShowing callback
mKeyguardStateController.addCallback(mKeyguardCallback);
@@ -169,6 +168,11 @@ public class KeyguardCoordinator implements Coordinator {
final ContentObserver settingsObserver = new ContentObserver(mMainHandler) {
@Override
public void onChange(boolean selfChange, Uri uri) {
+ if (uri.equals(Settings.Secure.getUriFor(
+ Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS))) {
+ readShowSilentNotificationSetting();
+ }
+
if (mKeyguardStateController.isShowing()) {
invalidateListFromFilter("Settings " + uri + " changed");
}
@@ -192,6 +196,12 @@ public class KeyguardCoordinator implements Coordinator {
false,
settingsObserver);
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS),
+ false,
+ settingsObserver,
+ UserHandle.USER_ALL);
+
// register (maybe) public mode changed callbacks:
mStatusBarStateController.addCallback(mStatusBarStateListener);
mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() {
@@ -208,6 +218,14 @@ public class KeyguardCoordinator implements Coordinator {
mNotifFilter.invalidateList();
}
+ private void readShowSilentNotificationSetting() {
+ mHideSilentNotificationsOnLockscreen =
+ Settings.Secure.getInt(
+ mContext.getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS,
+ 1) == 0;
+ }
+
private final KeyguardStateController.Callback mKeyguardCallback =
new KeyguardStateController.Callback() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index 4159d43e34ec..ee2bb6b1d190 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator;
import static com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.IntDef;
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
@@ -28,22 +30,21 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
-import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
-import com.android.systemui.statusbar.notification.collection.NotifViewBarn;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.render.NotifViewBarn;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
+import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager.NotifInflationErrorListener;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Set;
import javax.inject.Inject;
@@ -81,35 +82,48 @@ public class PreparationCoordinator implements Coordinator {
*/
private final int mChildBindCutoff;
+ /** How long we can delay a group while waiting for all children to inflate */
+ private final long mMaxGroupInflationDelay;
+
@Inject
public PreparationCoordinator(
PreparationCoordinatorLogger logger,
- NotifInflaterImpl notifInflater,
+ NotifInflater notifInflater,
NotifInflationErrorManager errorManager,
NotifViewBarn viewBarn,
IStatusBarService service) {
- this(logger, notifInflater, errorManager, viewBarn, service, CHILD_BIND_CUTOFF);
+ this(
+ logger,
+ notifInflater,
+ errorManager,
+ viewBarn,
+ service,
+ CHILD_BIND_CUTOFF,
+ MAX_GROUP_INFLATION_DELAY);
}
@VisibleForTesting
PreparationCoordinator(
PreparationCoordinatorLogger logger,
- NotifInflaterImpl notifInflater,
+ NotifInflater notifInflater,
NotifInflationErrorManager errorManager,
NotifViewBarn viewBarn,
IStatusBarService service,
- int childBindCutoff) {
+ int childBindCutoff,
+ long maxGroupInflationDelay) {
mLogger = logger;
mNotifInflater = notifInflater;
mNotifErrorManager = errorManager;
- mNotifErrorManager.addInflationErrorListener(mInflationErrorListener);
mViewBarn = viewBarn;
mStatusBarService = service;
mChildBindCutoff = childBindCutoff;
+ mMaxGroupInflationDelay = maxGroupInflationDelay;
}
@Override
public void attach(NotifPipeline pipeline) {
+ mNotifErrorManager.addInflationErrorListener(mInflationErrorListener);
+
pipeline.addCollectionListener(mNotifCollectionListener);
// Inflate after grouping/sorting since that affects what views to inflate.
pipeline.addOnBeforeFinalizeFilterListener(mOnBeforeFinalizeFilterListener);
@@ -127,7 +141,6 @@ public class PreparationCoordinator implements Coordinator {
@Override
public void onEntryUpdated(NotificationEntry entry) {
abortInflation(entry, "entryUpdated");
- mInflatingNotifs.remove(entry);
@InflationState int state = getInflationState(entry);
if (state == STATE_INFLATED) {
mInflationStates.put(entry, STATE_INFLATED_INVALID);
@@ -145,7 +158,6 @@ public class PreparationCoordinator implements Coordinator {
@Override
public void onEntryCleanUp(NotificationEntry entry) {
mInflationStates.remove(entry);
- mInflatingNotifs.remove(entry);
mViewBarn.removeViewForEntry(entry);
}
};
@@ -165,17 +177,32 @@ public class PreparationCoordinator implements Coordinator {
};
private final NotifFilter mNotifInflatingFilter = new NotifFilter(TAG + "Inflating") {
+ private final Map<GroupEntry, Boolean> mIsDelayedGroupCache = new ArrayMap<>();
+
/**
- * Filters out notifications that aren't inflated
+ * Filters out notifications that either (a) aren't inflated or (b) are part of a group
+ * that isn't completely inflated yet
*/
@Override
public boolean shouldFilterOut(NotificationEntry entry, long now) {
- return !isInflated(entry);
+ final GroupEntry parent = requireNonNull(entry.getParent());
+ Boolean isMemberOfDelayedGroup = mIsDelayedGroupCache.get(parent);
+ if (isMemberOfDelayedGroup == null) {
+ isMemberOfDelayedGroup = shouldWaitForGroupToInflate(parent, now);
+ mIsDelayedGroupCache.put(parent, isMemberOfDelayedGroup);
+ }
+
+ return !isInflated(entry) || isMemberOfDelayedGroup;
+ }
+
+ @Override
+ public void onCleanup() {
+ mIsDelayedGroupCache.clear();
}
};
- private final NotifInflationErrorManager.NotifInflationErrorListener mInflationErrorListener =
- new NotifInflationErrorManager.NotifInflationErrorListener() {
+ private final NotifInflationErrorListener mInflationErrorListener =
+ new NotifInflationErrorListener() {
@Override
public void onNotifInflationError(NotificationEntry entry, Exception e) {
mViewBarn.removeViewForEntry(entry);
@@ -191,8 +218,9 @@ public class PreparationCoordinator implements Coordinator {
sbn.getUid(),
sbn.getInitialPid(),
e.getMessage(),
- sbn.getUserId());
+ sbn.getUser().getIdentifier());
} catch (RemoteException ex) {
+ // System server is dead, nothing to do about that
}
mNotifInflationErrorFilter.invalidateList();
}
@@ -297,11 +325,36 @@ public class PreparationCoordinator implements Coordinator {
private @InflationState int getInflationState(NotificationEntry entry) {
Integer stateObj = mInflationStates.get(entry);
- Objects.requireNonNull(stateObj,
+ requireNonNull(stateObj,
"Asking state of a notification preparation coordinator doesn't know about");
return stateObj;
}
+ private boolean shouldWaitForGroupToInflate(GroupEntry group, long now) {
+ if (group == GroupEntry.ROOT_ENTRY || group.hasBeenAttachedBefore()) {
+ return false;
+ }
+ if (isBeyondGroupInitializationWindow(group, now)) {
+ mLogger.logGroupInflationTookTooLong(group.getKey());
+ return false;
+ }
+ if (mInflatingNotifs.contains(group.getSummary())) {
+ mLogger.logDelayingGroupRelease(group.getKey(), group.getSummary().getKey());
+ return true;
+ }
+ for (NotificationEntry child : group.getChildren()) {
+ if (mInflatingNotifs.contains(child) && !child.hasBeenAttachedBefore()) {
+ mLogger.logDelayingGroupRelease(group.getKey(), child.getKey());
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isBeyondGroupInitializationWindow(GroupEntry entry, long now) {
+ return now - entry.getCreationTime() > mMaxGroupInflationDelay;
+ }
+
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"STATE_"},
value = {STATE_UNINFLATED, STATE_INFLATED_INVALID, STATE_INFLATED, STATE_ERROR})
@@ -328,6 +381,8 @@ public class PreparationCoordinator implements Coordinator {
*/
private static final int EXTRA_VIEW_BUFFER_COUNT = 1;
+ private static final long MAX_GROUP_INFLATION_DELAY = 500;
+
private static final int CHILD_BIND_CUTOFF =
NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED + EXTRA_VIEW_BUFFER_COUNT;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt
index 75e7bc9b79a2..dd4794f0a452 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt
@@ -40,6 +40,23 @@ class PreparationCoordinatorLogger @Inject constructor(
"NOTIF INFLATION ABORTED $str1 reason=$str2"
})
}
+
+ fun logGroupInflationTookTooLong(groupKey: String) {
+ buffer.log(TAG, LogLevel.WARNING, {
+ str1 = groupKey
+ }, {
+ "Group inflation took too long far $str1, releasing children early"
+ })
+ }
+
+ fun logDelayingGroupRelease(groupKey: String, childKey: String) {
+ buffer.log(TAG, LogLevel.DEBUG, {
+ str1 = groupKey
+ str2 = childKey
+ }, {
+ "Delaying release of group $str1 because child $str2 is still inflating"
+ })
+ }
}
private const val TAG = "PreparationCoordinator" \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
index 710b137d2795..1215ade2abb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinder.java
@@ -38,7 +38,6 @@ public interface NotificationRowBinder {
*/
void inflateViews(
NotificationEntry entry,
- Runnable onDismissRunnable,
NotificationRowContentBinder.InflationCallback callback)
throws InflationException;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 85a3bc91dc7e..8849824380d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -32,7 +32,6 @@ import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.icon.IconManager;
-import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
import com.android.systemui.statusbar.notification.row.NotifBindPipeline;
@@ -59,7 +58,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
private final NotificationLockscreenUserManager mNotificationLockscreenUserManager;
private final NotifBindPipeline mNotifBindPipeline;
private final RowContentBindStage mRowContentBindStage;
- private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
private final Provider<RowInflaterTask> mRowInflaterTaskProvider;
private final ExpandableNotificationRowComponent.Builder
mExpandableNotificationRowComponentBuilder;
@@ -79,7 +77,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotifBindPipeline notifBindPipeline,
RowContentBindStage rowContentBindStage,
- NotificationInterruptStateProvider notificationInterruptionStateProvider,
Provider<RowInflaterTask> rowInflaterTaskProvider,
ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder,
IconManager iconManager,
@@ -90,7 +87,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
mMessagingUtil = notificationMessagingUtil;
mNotificationRemoteInputManager = notificationRemoteInputManager;
mNotificationLockscreenUserManager = notificationLockscreenUserManager;
- mNotificationInterruptStateProvider = notificationInterruptionStateProvider;
mRowInflaterTaskProvider = rowInflaterTaskProvider;
mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder;
mIconManager = iconManager;
@@ -120,7 +116,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
@Override
public void inflateViews(
NotificationEntry entry,
- Runnable onDismissRunnable,
NotificationRowContentBinder.InflationCallback callback)
throws InflationException {
ViewGroup parent = mListContainer.getViewParentForNotification(entry);
@@ -131,7 +126,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
row.reset();
updateRow(entry, row);
inflateContentViews(entry, row, callback);
- entry.getRowController().setOnDismissRunnable(onDismissRunnable);
} else {
mIconManager.createIcons(entry);
mRowInflaterTaskProvider.get().inflate(mContext, parent, entry,
@@ -141,7 +135,6 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
mExpandableNotificationRowComponentBuilder
.expandableNotificationRow(row)
.notificationEntry(entry)
- .onDismissRunnable(onDismissRunnable)
.onExpandClickListener(mPresenter)
.build();
ExpandableNotificationRowController rowController =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnDismissCallbackImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnDismissCallbackImpl.java
new file mode 100644
index 000000000000..36adf9b87674
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnDismissCallbackImpl.java
@@ -0,0 +1,83 @@
+/*
+ * 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.collection.inflation;
+
+import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
+
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationStats;
+
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.OnDismissCallback;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+/**
+ * Callback used when a user:
+ * 1. Manually dismisses a notification {@see ExpandableNotificationRow}.
+ * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}.
+ * {@see StatusBarNotificationActivityStarter}
+ */
+public class OnDismissCallbackImpl implements OnDismissCallback {
+ private final NotifPipeline mNotifPipeline;
+ private final NotifCollection mNotifCollection;
+ private final HeadsUpManager mHeadsUpManager;
+ private final StatusBarStateController mStatusBarStateController;
+
+ public OnDismissCallbackImpl(
+ NotifPipeline notifPipeline,
+ NotifCollection notifCollection,
+ HeadsUpManager headsUpManager,
+ StatusBarStateController statusBarStateController
+ ) {
+ mNotifPipeline = notifPipeline;
+ mNotifCollection = notifCollection;
+ mHeadsUpManager = headsUpManager;
+ mStatusBarStateController = statusBarStateController;
+ }
+
+ @Override
+ public void onDismiss(
+ NotificationEntry entry,
+ @NotificationListenerService.NotificationCancelReason int cancellationReason
+ ) {
+ int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
+ if (mHeadsUpManager.isAlerting(entry.getKey())) {
+ dismissalSurface = NotificationStats.DISMISSAL_PEEK;
+ } else if (mStatusBarStateController.isDozing()) {
+ dismissalSurface = NotificationStats.DISMISSAL_AOD;
+ }
+
+ mNotifCollection.dismissNotification(
+ entry,
+ new DismissedByUserStats(
+ dismissalSurface,
+ DISMISS_SENTIMENT_NEUTRAL,
+ NotificationVisibility.obtain(
+ entry.getKey(),
+ entry.getRanking().getRank(),
+ mNotifPipeline.getShadeListCount(),
+ true,
+ NotificationLogger.getNotificationLocation(entry)))
+ );
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
index f150257df252..9782c3ef55fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java
@@ -25,11 +25,12 @@ import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
-import com.android.systemui.statusbar.notification.collection.NotifViewManager;
import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.render.NotifViewManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifViewManagerBuilder;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import java.io.FileDescriptor;
@@ -50,9 +51,9 @@ public class NotifPipelineInitializer implements Dumpable {
private final NotifCoordinators mNotifPluggableCoordinators;
private final NotifInflaterImpl mNotifInflater;
private final DumpManager mDumpManager;
+ private final NotifViewManagerBuilder mNotifViewManagerBuilder;
private final FeatureFlags mFeatureFlags;
- private final NotifViewManager mNotifViewManager;
@Inject
public NotifPipelineInitializer(
@@ -63,8 +64,8 @@ public class NotifPipelineInitializer implements Dumpable {
NotifCoordinators notifCoordinators,
NotifInflaterImpl notifInflater,
DumpManager dumpManager,
- FeatureFlags featureFlags,
- NotifViewManager notifViewManager) {
+ NotifViewManagerBuilder notifViewManagerBuilder,
+ FeatureFlags featureFlags) {
mPipelineWrapper = pipelineWrapper;
mGroupCoalescer = groupCoalescer;
mNotifCollection = notifCollection;
@@ -73,7 +74,7 @@ public class NotifPipelineInitializer implements Dumpable {
mDumpManager = dumpManager;
mNotifInflater = notifInflater;
mFeatureFlags = featureFlags;
- mNotifViewManager = notifViewManager;
+ mNotifViewManagerBuilder = notifViewManagerBuilder;
}
/** Hooks the new pipeline up to NotificationManager */
@@ -93,8 +94,10 @@ public class NotifPipelineInitializer implements Dumpable {
mNotifPluggableCoordinators.attach(mPipelineWrapper);
// Wire up pipeline
- mNotifViewManager.setViewConsumer(listContainer);
- mNotifViewManager.attach(mListBuilder);
+ if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+ NotifViewManager notifViewManager = mNotifViewManagerBuilder.build(listContainer);
+ notifViewManager.attach(mListBuilder);
+ }
mListBuilder.attach(mNotifCollection);
mNotifCollection.attach(mGroupCoalescer);
mGroupCoalescer.attach(notificationService);
@@ -104,7 +107,6 @@ public class NotifPipelineInitializer implements Dumpable {
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- mNotifViewManager.dump(fd, pw, args);
mNotifPluggableCoordinators.dump(fd, pw, args);
mGroupCoalescer.dump(fd, pw, args);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnDismissCallbackImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnDismissCallbackImpl.java
new file mode 100644
index 000000000000..94ffa8f8c5ed
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnDismissCallbackImpl.java
@@ -0,0 +1,81 @@
+/*
+ * 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.collection.legacy;
+
+import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
+
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationStats;
+
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.OnDismissCallback;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+
+/**
+ * Callback used when a user:
+ * 1. Manually dismisses a notification {@see ExpandableNotificationRow}.
+ * 2. Clicks on a notification with flag {@link android.app.Notification#FLAG_AUTO_CANCEL}.
+ * {@see StatusBarNotificationActivityStarter}
+ */
+public class OnDismissCallbackImpl implements OnDismissCallback {
+ private final NotificationEntryManager mNotificationEntryManager;
+ private final HeadsUpManager mHeadsUpManager;
+ private final StatusBarStateController mStatusBarStateController;
+
+ public OnDismissCallbackImpl(
+ NotificationEntryManager notificationEntryManager,
+ HeadsUpManager headsUpManager,
+ StatusBarStateController statusBarStateController
+ ) {
+ mNotificationEntryManager = notificationEntryManager;
+ mHeadsUpManager = headsUpManager;
+ mStatusBarStateController = statusBarStateController;
+ }
+
+ @Override
+ public void onDismiss(
+ NotificationEntry entry,
+ @NotificationListenerService.NotificationCancelReason int cancellationReason
+ ) {
+ int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
+ if (mHeadsUpManager.isAlerting(entry.getKey())) {
+ dismissalSurface = NotificationStats.DISMISSAL_PEEK;
+ } else if (mStatusBarStateController.isDozing()) {
+ dismissalSurface = NotificationStats.DISMISSAL_AOD;
+ }
+
+ mNotificationEntryManager.performRemoveNotification(
+ entry.getSbn(),
+ new DismissedByUserStats(
+ dismissalSurface,
+ DISMISS_SENTIMENT_NEUTRAL,
+ NotificationVisibility.obtain(
+ entry.getKey(),
+ entry.getRanking().getRank(),
+ mNotificationEntryManager.getActiveNotificationsCount(),
+ true,
+ NotificationLogger.getNotificationLocation(entry))),
+ cancellationReason
+ );
+ }
+}
+
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
index aa107824729e..67f8bfeaf141 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -125,13 +125,18 @@ class ShadeListBuilderLogger @Inject constructor(
str2 = prevParent?.key
str3 = newParent?.key
}, {
- if (str2 == null && str3 != null) {
- "(Build $int1) ATTACHED {$str1}"
+
+ val action = if (str2 == null && str3 != null) {
+ "ATTACHED"
} else if (str2 != null && str3 == null) {
- "(Build $int1) DETACHED {$str1}"
+ "DETACHED"
+ } else if (str2 == null && str3 == null) {
+ "MODIFIED (DETACHED)"
} else {
- "(Build $int1) MODIFIED {$str1}"
+ "MODIFIED (ATTACHED)"
}
+
+ "(Build $int1) $action {$str1}"
})
}
@@ -146,7 +151,7 @@ class ShadeListBuilderLogger @Inject constructor(
} else if (str1 != null && str2 == null) {
"(Build $int1) Parent was {$str1}"
} else {
- "(Build $int1) Reparent: {$str2} -> {$str3}"
+ "(Build $int1) Reparent: {$str1} -> {$str2}"
}
})
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
index 4270408d0c66..8e4fb7523767 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
@@ -55,11 +55,17 @@ public abstract class Pluggable<This> {
}
/** Set a listener to be notified when a pluggable is invalidated. */
- public void setInvalidationListener(PluggableListener<This> listener) {
+ public final void setInvalidationListener(PluggableListener<This> listener) {
mListener = listener;
}
/**
+ * Called on the pluggable once at the end of every pipeline run. Override this method to
+ * perform any necessary cleanup.
+ */
+ public void onCleanup() { }
+
+ /**
* Listener interface for when pluggables are invalidated.
*
* @param <T> The type of pluggable that is being listened to.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewBarn.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt
index e7948cd1216e..54000950e3ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewBarn.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt
@@ -14,26 +14,22 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection
+package com.android.systemui.statusbar.notification.collection.render
import android.view.textclassifier.Log
-import com.android.systemui.statusbar.notification.stack.NotificationListItem
-import java.lang.IllegalStateException
-
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import javax.inject.Inject
import javax.inject.Singleton
/**
- * The ViewBarn is just a map from [ListEntry] to an instance of [NotificationListItem] which is
- * usually just an [ExpandableNotificationRow]
+ * The ViewBarn is just a map from [ListEntry] to an instance of an [ExpandableNotificationRow].
*/
@Singleton
class NotifViewBarn @Inject constructor() {
- private val DEBUG = false
-
- private val rowMap = mutableMapOf<String, NotificationListItem>()
+ private val rowMap = mutableMapOf<String, ExpandableNotificationRow>()
- fun requireView(forEntry: ListEntry): NotificationListItem {
+ fun requireView(forEntry: ListEntry): ExpandableNotificationRow {
if (DEBUG) {
Log.d(TAG, "requireView: $forEntry.key")
}
@@ -45,7 +41,7 @@ class NotifViewBarn @Inject constructor() {
return li
}
- fun registerViewForEntry(entry: ListEntry, view: NotificationListItem) {
+ fun registerViewForEntry(entry: ListEntry, view: ExpandableNotificationRow) {
if (DEBUG) {
Log.d(TAG, "registerViewForEntry: $entry.key")
}
@@ -60,4 +56,6 @@ class NotifViewBarn @Inject constructor() {
}
}
-private const val TAG = "NotifViewBarn" \ No newline at end of file
+private const val TAG = "NotifViewBarn"
+
+private const val DEBUG = false \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewManager.kt
new file mode 100644
index 000000000000..f2e2c39ab612
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewManager.kt
@@ -0,0 +1,240 @@
+/*
+ * 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.collection.render
+
+import android.annotation.MainThread
+import android.view.View
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer
+import javax.inject.Inject
+
+/**
+ * A consumer of a Notification tree built by [ShadeListBuilder] which will update the notification
+ * presenter with the minimum operations required to make the old tree match the new one
+ */
+@MainThread
+class NotifViewManager constructor(
+ private val listContainer: NotificationListContainer,
+ private val viewBarn: NotifViewBarn,
+ private val logger: NotifViewManagerLogger
+) {
+ private val rootNode = RootWrapper(listContainer)
+ private val rows = mutableMapOf<ListEntry, RowNode>()
+
+ fun attach(listBuilder: ShadeListBuilder) {
+ listBuilder.setOnRenderListListener(::onNewNotifTree)
+ }
+
+ private fun onNewNotifTree(tree: List<ListEntry>) {
+ // Step 1: Detach all views whose parents have changed
+ detachRowsWithModifiedParents()
+
+ // Step 2: Attach all new views and reattach all views whose parents changed.
+ // Also reorder existing children to match the spec we've received
+ val orderChanged = addAndReorderChildren(rootNode, tree)
+ if (orderChanged) {
+ listContainer.generateChildOrderChangedEvent()
+ }
+ }
+
+ private fun detachRowsWithModifiedParents() {
+ val toRemove = mutableListOf<ListEntry>()
+ for (row in rows.values) {
+ val oldParentEntry = row.nodeParent?.entry
+ val newParentEntry = row.entry.parent
+
+ if (newParentEntry != oldParentEntry) {
+ // If the parent is null, then we should remove the child completely. If not, then
+ // the parent merely changed: we'll detach it for now and then attach it to the
+ // new parent in step 2.
+ val isTransfer = newParentEntry != null
+ if (!isTransfer) {
+ toRemove.add(row.entry)
+ }
+
+ if (!isTransfer && !isAttachedToRootEntry(oldParentEntry)) {
+ // If our view parent has also been removed (i.e. is no longer attached to the
+ // root entry) then we skip removing the child here
+ logger.logSkippingDetach(row.entry.key, row.nodeParent?.entry?.key)
+ } else {
+ logger.logDetachingChild(
+ row.entry.key,
+ isTransfer,
+ oldParentEntry?.key,
+ newParentEntry?.key)
+ row.nodeParent?.removeChild(row, isTransfer)
+ row.nodeParent = null
+ }
+ }
+ }
+ rows.keys.removeAll(toRemove)
+ }
+
+ private fun addAndReorderChildren(parent: ParentNode, childEntries: List<ListEntry>): Boolean {
+ var orderChanged = false
+ for ((index, entry) in childEntries.withIndex()) {
+ val row = getRowNode(entry)
+ val currView = parent.getChildViewAt(index)
+ if (currView != row.view) {
+ when (row.nodeParent) {
+ null -> {
+ logger.logAttachingChild(row.entry.key, parent.entry.key)
+ parent.addChildAt(row, index)
+ row.nodeParent = parent
+ }
+ parent -> {
+ logger.logMovingChild(row.entry.key, parent.entry.key, index)
+ parent.moveChild(row, index)
+ orderChanged = true
+ }
+ else -> {
+ throw IllegalStateException("Child ${row.entry.key} should have parent " +
+ "${parent.entry.key} but is actually " +
+ "${row.nodeParent?.entry?.key}")
+ }
+ }
+ }
+ if (row is GroupWrapper) {
+ val childOrderChanged = addAndReorderChildren(row, row.entry.children)
+ orderChanged = orderChanged || childOrderChanged
+ }
+ }
+ // TODO: setUntruncatedChildCount
+
+ return orderChanged
+ }
+
+ private fun getRowNode(entry: ListEntry): RowNode {
+ return rows.getOrPut(entry) {
+ when (entry) {
+ is NotificationEntry -> RowWrapper(entry, viewBarn.requireView(entry))
+ is GroupEntry ->
+ GroupWrapper(
+ entry,
+ viewBarn.requireView(checkNotNull(entry.summary)),
+ listContainer)
+ else -> throw RuntimeException(
+ "Unexpected entry type for ${entry.key}: ${entry.javaClass}")
+ }
+ }
+ }
+}
+
+class NotifViewManagerBuilder @Inject constructor(
+ private val viewBarn: NotifViewBarn,
+ private val logger: NotifViewManagerLogger
+) {
+ fun build(listContainer: NotificationListContainer): NotifViewManager {
+ return NotifViewManager(listContainer, viewBarn, logger)
+ }
+}
+
+private fun isAttachedToRootEntry(entry: ListEntry?): Boolean {
+ return when (entry) {
+ null -> false
+ ROOT_ENTRY -> true
+ else -> isAttachedToRootEntry(entry.parent)
+ }
+}
+
+private interface Node {
+ val entry: ListEntry
+ val nodeParent: ParentNode?
+}
+
+private interface ParentNode : Node {
+ fun getChildViewAt(index: Int): View?
+ fun addChildAt(child: RowNode, index: Int)
+ fun moveChild(child: RowNode, index: Int)
+ fun removeChild(child: RowNode, isTransfer: Boolean)
+}
+
+private interface RowNode : Node {
+ val view: ExpandableNotificationRow
+ override var nodeParent: ParentNode?
+}
+
+private class RootWrapper(
+ private val listContainer: NotificationListContainer
+) : ParentNode {
+ override val entry: ListEntry = ROOT_ENTRY
+ override val nodeParent: ParentNode? = null
+
+ override fun getChildViewAt(index: Int): View? {
+ return listContainer.getContainerChildAt(index)
+ }
+
+ override fun addChildAt(child: RowNode, index: Int) {
+ listContainer.addContainerViewAt(child.view, index)
+ }
+
+ override fun moveChild(child: RowNode, index: Int) {
+ listContainer.changeViewPosition(child.view, index)
+ }
+
+ override fun removeChild(child: RowNode, isTransfer: Boolean) {
+ if (isTransfer) {
+ listContainer.setChildTransferInProgress(true)
+ }
+ listContainer.removeContainerView(child.view)
+ if (isTransfer) {
+ listContainer.setChildTransferInProgress(false)
+ }
+ }
+}
+
+private class GroupWrapper(
+ override val entry: GroupEntry,
+ override val view: ExpandableNotificationRow,
+ val listContainer: NotificationListContainer
+) : RowNode, ParentNode {
+
+ override var nodeParent: ParentNode? = null
+
+ override fun getChildViewAt(index: Int): View? {
+ return view.getChildNotificationAt(index)
+ }
+
+ override fun addChildAt(child: RowNode, index: Int) {
+ view.addChildNotification(child.view, index)
+ listContainer.notifyGroupChildAdded(child.view)
+ }
+
+ override fun moveChild(child: RowNode, index: Int) {
+ view.removeChildNotification(child.view)
+ view.addChildNotification(child.view, index)
+ }
+
+ override fun removeChild(child: RowNode, isTransfer: Boolean) {
+ view.removeChildNotification(child.view)
+ if (isTransfer) {
+ listContainer.notifyGroupChildRemoved(child.view, view)
+ }
+ }
+}
+
+private class RowWrapper(
+ override val entry: NotificationEntry,
+ override val view: ExpandableNotificationRow
+) : RowNode {
+ override var nodeParent: ParentNode? = null
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewManagerLogger.kt
new file mode 100644
index 000000000000..3d561264d367
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewManagerLogger.kt
@@ -0,0 +1,72 @@
+/*
+ * 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.collection.render
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationLog
+import javax.inject.Inject
+
+class NotifViewManagerLogger @Inject constructor(
+ @NotificationLog private val buffer: LogBuffer
+) {
+ fun logDetachingChild(
+ key: String,
+ isTransfer: Boolean,
+ oldParent: String?,
+ newParent: String?
+ ) {
+ buffer.log(TAG, LogLevel.DEBUG, {
+ str1 = key
+ bool1 = isTransfer
+ str2 = oldParent
+ str3 = newParent
+ }, {
+ "Detach $str1 isTransfer=$bool1 oldParent=$str2 newParent=$str3"
+ })
+ }
+
+ fun logSkippingDetach(key: String, parent: String?) {
+ buffer.log(TAG, LogLevel.DEBUG, {
+ str1 = key
+ str2 = parent
+ }, {
+ "Skipping detach of $str1 because its parent $str2 is also being detached"
+ })
+ }
+
+ fun logAttachingChild(key: String, parent: String) {
+ buffer.log(TAG, LogLevel.DEBUG, {
+ str1 = key
+ str2 = parent
+ }, {
+ "Attaching view $str1 to $str2"
+ })
+ }
+
+ fun logMovingChild(key: String, parent: String, toIndex: Int) {
+ buffer.log(TAG, LogLevel.DEBUG, {
+ str1 = key
+ str2 = parent
+ int1 = toIndex
+ }, {
+ "Moving child view $str1 in $str2 to index $int1"
+ })
+ }
+}
+
+private const val TAG = "NotifViewManager" \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index d661b5e2b7cf..046dc3c8dce6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -25,6 +25,7 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.dagger.qualifiers.Background;
@@ -40,9 +41,13 @@ import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFea
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
+import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.inflation.OnDismissCallbackImpl;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.init.NotificationsController;
@@ -56,6 +61,7 @@ import com.android.systemui.statusbar.notification.logging.NotificationPanelLogg
import com.android.systemui.statusbar.notification.row.ChannelEditorDialogController;
import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.row.OnDismissCallback;
import com.android.systemui.statusbar.notification.row.PriorityOnboardingDialogController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -90,8 +96,7 @@ public interface NotificationsModule {
Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
LeakDetector leakDetector,
ForegroundServiceDismissalFeatureController fgsFeatureController,
- HeadsUpManager headsUpManager,
- StatusBarStateController statusBarStateController) {
+ IStatusBarService statusBarService) {
return new NotificationEntryManager(
logger,
groupManager,
@@ -102,8 +107,7 @@ public interface NotificationsModule {
notificationRemoteInputManagerLazy,
leakDetector,
fgsFeatureController,
- headsUpManager,
- statusBarStateController);
+ statusBarService);
}
/** Provides an instance of {@link NotificationGutsManager} */
@@ -217,8 +221,34 @@ public interface NotificationsModule {
return featureFlags.isNewNotifPipelineRenderingEnabled() ? pipeline.get() : entryManager;
}
+ /**
+ * Provide a dismissal callback that's triggered when a user manually dismissed a notification
+ * from the notification shade or it gets auto-cancelled by click.
+ */
+ @Provides
+ @Singleton
+ static OnDismissCallback provideOnDismissCallback(
+ FeatureFlags featureFlags,
+ HeadsUpManager headsUpManager,
+ StatusBarStateController statusBarStateController,
+ Lazy<NotifPipeline> pipeline,
+ Lazy<NotifCollection> notifCollection,
+ NotificationEntryManager entryManager) {
+ return featureFlags.isNewNotifPipelineRenderingEnabled()
+ ? new OnDismissCallbackImpl(
+ pipeline.get(), notifCollection.get(), headsUpManager,
+ statusBarStateController)
+ : new com.android.systemui.statusbar.notification.collection
+ .legacy.OnDismissCallbackImpl(
+ entryManager, headsUpManager, statusBarStateController);
+ }
+
/** */
@Binds
NotificationInterruptStateProvider bindNotificationInterruptStateProvider(
NotificationInterruptStateProviderImpl notificationInterruptStateProviderImpl);
+
+ /** */
+ @Binds
+ NotifInflater bindNotifInflater(NotifInflaterImpl notifInflaterImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index d1ce8d1cf4c7..22d0357b14c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.row;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL;
+
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
@@ -92,7 +94,6 @@ 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.NotificationChildrenContainer;
-import com.android.systemui.statusbar.notification.stack.NotificationListItem;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.SwipeableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -115,8 +116,7 @@ import java.util.function.Consumer;
* the group summary (which contains 1 or more child notifications).
*/
public class ExpandableNotificationRow extends ActivatableNotificationView
- implements PluginListener<NotificationMenuRowPlugin>, SwipeableView,
- NotificationListItem {
+ implements PluginListener<NotificationMenuRowPlugin>, SwipeableView {
private static final boolean DEBUG = false;
private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
@@ -323,7 +323,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private View mGroupParentWhenDismissed;
private boolean mShelfIconVisible;
private boolean mAboveShelf;
- private Runnable mOnDismissRunnable;
+ private OnDismissCallback mOnDismissCallback;
private boolean mIsLowPriority;
private boolean mIsColorized;
private boolean mUseIncreasedCollapsedHeight;
@@ -801,17 +801,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
row.setIsChildInGroup(true, this);
}
- /**
- * Same as {@link #addChildNotification(ExpandableNotificationRow, int)}, but takes a
- * {@link NotificationListItem} instead
- *
- * @param childItem item
- * @param childIndex index
- */
- public void addChildNotification(NotificationListItem childItem, int childIndex) {
- addChildNotification((ExpandableNotificationRow) childItem.getView(), childIndex);
- }
-
public void removeChildNotification(ExpandableNotificationRow row) {
if (mChildrenContainer != null) {
mChildrenContainer.removeNotification(row);
@@ -821,9 +810,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
row.setBottomRoundness(0.0f, false /* animate */);
}
- @Override
- public void removeChildNotification(NotificationListItem child) {
- removeChildNotification((ExpandableNotificationRow) child.getView());
+ /** Returns the child notification at [index], or null if no such child. */
+ @Nullable
+ public ExpandableNotificationRow getChildNotificationAt(int index) {
+ if (mChildrenContainer == null
+ || mChildrenContainer.getAttachedChildren().size() <= index) {
+ return null;
+ } else {
+ return mChildrenContainer.getAttachedChildren().get(index);
+ }
}
@Override
@@ -914,7 +909,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
* @param callback the callback to invoked in case it is not allowed
* @return whether the list order has changed
*/
- public boolean applyChildOrder(List<? extends NotificationListItem> childOrder,
+ public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
VisualStabilityManager visualStabilityManager,
VisualStabilityManager.Callback callback) {
return mChildrenContainer != null && mChildrenContainer.applyChildOrder(childOrder,
@@ -1321,11 +1316,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
onAttachedChildrenCountChanged();
}
- @Override
- public View getView() {
- return this;
- }
-
public void setForceUnlocked(boolean forceUnlocked) {
mForceUnlocked = forceUnlocked;
if (mIsSummaryWithChildren) {
@@ -1456,10 +1446,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
dismiss(fromAccessibility);
if (mEntry.isClearable()) {
- // TODO: beverlyt, log dismissal
- // TODO: track dismiss sentiment
- if (mOnDismissRunnable != null) {
- mOnDismissRunnable.run();
+ if (mOnDismissCallback != null) {
+ mOnDismissCallback.onDismiss(mEntry, REASON_CANCEL);
}
}
}
@@ -1476,8 +1464,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return mIsBlockingHelperShowing && mNotificationTranslationFinished;
}
- void setOnDismissRunnable(Runnable onDismissRunnable) {
- mOnDismissRunnable = onDismissRunnable;
+ void setOnDismissCallback(OnDismissCallback onDismissCallback) {
+ mOnDismissCallback = onDismissCallback;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index c9839355b9ba..86a3271c4eac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -30,7 +30,6 @@ import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.dagger.AppName;
-import com.android.systemui.statusbar.notification.row.dagger.DismissRunnable;
import com.android.systemui.statusbar.notification.row.dagger.NotificationKey;
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -66,7 +65,7 @@ public class ExpandableNotificationRowController {
private final ExpandableNotificationRow.CoordinateOnClickListener mOnAppOpsClickListener;
private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener;
private final NotificationGutsManager mNotificationGutsManager;
- private Runnable mOnDismissRunnable;
+ private final OnDismissCallback mOnDismissCallback;
private final FalsingManager mFalsingManager;
private final boolean mAllowLongPress;
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
@@ -84,7 +83,7 @@ public class ExpandableNotificationRowController {
StatusBarStateController statusBarStateController,
NotificationGutsManager notificationGutsManager,
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress,
- @DismissRunnable Runnable onDismissRunnable, FalsingManager falsingManager,
+ OnDismissCallback onDismissCallback, FalsingManager falsingManager,
PeopleNotificationIdentifier peopleNotificationIdentifier) {
mView = view;
mActivatableNotificationViewController = activatableNotificationViewController;
@@ -101,7 +100,7 @@ public class ExpandableNotificationRowController {
mOnExpandClickListener = onExpandClickListener;
mStatusBarStateController = statusBarStateController;
mNotificationGutsManager = notificationGutsManager;
- mOnDismissRunnable = onDismissRunnable;
+ mOnDismissCallback = onDismissCallback;
mOnAppOpsClickListener = mNotificationGutsManager::openGuts;
mOnFeedbackClickListener = mNotificationGutsManager::openGuts;
mAllowLongPress = allowLongPress;
@@ -130,7 +129,7 @@ public class ExpandableNotificationRowController {
mStatusBarStateController,
mPeopleNotificationIdentifier
);
- mView.setOnDismissRunnable(mOnDismissRunnable);
+ mView.setOnDismissCallback(mOnDismissCallback);
mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
if (mAllowLongPress) {
mView.setLongPressListener((v, x, y, item) -> {
@@ -163,10 +162,4 @@ public class ExpandableNotificationRowController {
private void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
mNotificationLogger.onExpansionChanged(key, userAction, expanded);
}
-
- /** */
- public void setOnDismissRunnable(Runnable onDismissRunnable) {
- mOnDismissRunnable = onDismissRunnable;
- mView.setOnDismissRunnable(onDismissRunnable);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnDismissCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnDismissCallback.java
new file mode 100644
index 000000000000..f1aed899e060
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/OnDismissCallback.java
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+import android.service.notification.NotificationListenerService;
+
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+/**
+ * Callback when a user clicks on an auto-cancelled notification or manually swipes to dismiss the
+ * notification.
+ */
+public interface OnDismissCallback {
+
+ /**
+ * Handle a user interaction that triggers a notification dismissal.
+ */
+ void onDismiss(
+ NotificationEntry entry,
+ @NotificationListenerService.NotificationCancelReason int cancellationReason);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java
index 321656df504a..28ddf5971bcb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/ExpandableNotificationRowComponent.java
@@ -54,8 +54,6 @@ public interface ExpandableNotificationRowComponent {
@BindsInstance
Builder notificationEntry(NotificationEntry entry);
@BindsInstance
- Builder onDismissRunnable(@DismissRunnable Runnable runnable);
- @BindsInstance
Builder onExpandClickListener(ExpandableNotificationRow.OnExpandClickListener presenter);
ExpandableNotificationRowComponent build();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 907b89040a28..93c2377ccfae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -447,7 +447,7 @@ public class NotificationChildrenContainer extends ViewGroup {
* @param callback
* @return whether the list order has changed
*/
- public boolean applyChildOrder(List<? extends NotificationListItem> childOrder,
+ public boolean applyChildOrder(List<ExpandableNotificationRow> childOrder,
VisualStabilityManager visualStabilityManager,
VisualStabilityManager.Callback callback) {
if (childOrder == null) {
@@ -456,7 +456,7 @@ public class NotificationChildrenContainer extends ViewGroup {
boolean result = false;
for (int i = 0; i < mAttachedChildren.size() && i < childOrder.size(); i++) {
ExpandableNotificationRow child = mAttachedChildren.get(i);
- ExpandableNotificationRow desiredChild = (ExpandableNotificationRow) childOrder.get(i);
+ ExpandableNotificationRow desiredChild = childOrder.get(i);
if (child != desiredChild) {
if (visualStabilityManager.canReorderNotification(desiredChild)) {
mAttachedChildren.remove(desiredChild);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
index 09ab1d89473e..72f32161038a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListContainer.java
@@ -18,15 +18,15 @@ package com.android.systemui.statusbar.notification.stack;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
-import android.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
+import androidx.annotation.Nullable;
+
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.SimpleNotificationListContainer;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -35,8 +35,9 @@ import com.android.systemui.statusbar.notification.row.ExpandableView;
* Interface representing the entity that contains notifications. It can have
* notification views added and removed from it, and will manage displaying them to the user.
*/
-public interface NotificationListContainer extends ExpandableView.OnHeightChangedListener,
- VisibilityLocationProvider, SimpleNotificationListContainer {
+public interface NotificationListContainer extends
+ ExpandableView.OnHeightChangedListener,
+ VisibilityLocationProvider {
/**
* Called when a child is being transferred.
@@ -91,6 +92,7 @@ public interface NotificationListContainer extends ExpandableView.OnHeightChange
* @param i ith child to get
* @return the ith child in the list container
*/
+ @Nullable
View getContainerChildAt(int i);
/**
@@ -108,6 +110,11 @@ public interface NotificationListContainer extends ExpandableView.OnHeightChange
void addContainerView(View v);
/**
+ * Add a view to the container at a particular index
+ */
+ void addContainerViewAt(View v, int index);
+
+ /**
* Sets the maximum number of notifications to display.
*
* @param maxNotifications max number of notifications to display
@@ -188,13 +195,10 @@ public interface NotificationListContainer extends ExpandableView.OnHeightChange
return true;
}
- default void setWillExpand(boolean willExpand) {};
-
/**
- * Remove a list item from the container
- * @param v the item to remove
+ * Tells the container that an animation is about to expand it.
*/
- void removeListItem(@NonNull NotificationListItem v);
+ default void setWillExpand(boolean willExpand) {}
void setNotificationActivityStarter(NotificationActivityStarter notificationActivityStarter);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java
deleted file mode 100644
index c2dd2296aa17..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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 android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.view.View;
-
-import com.android.systemui.statusbar.notification.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-
-import java.util.List;
-
-/**
-* A NotificationListItem is a child view of the notification list that can yield a
-* NotificationEntry when asked. I.e., it's an ExpandableNotificationRow but doesn't require us
-* to strictly rely on ExpandableNotificationRow as our consumed type
- */
-public interface NotificationListItem {
- /** @return entry for this item */
- @NonNull
- NotificationEntry getEntry();
-
- /** @return true if the blocking helper is showing */
- boolean isBlockingHelperShowing();
-
- /** @return true if this list item is a summary with children */
- boolean isSummaryWithChildren();
-
- // This generic is kind of ugly - we should change this once the old VHM is gone
- /** @return list of the children of this item */
- List<? extends NotificationListItem> getAttachedChildren();
-
- /** remove all children from this list item */
- void removeAllChildren();
-
- /** remove particular child */
- void removeChildNotification(NotificationListItem child);
-
- /** add an item as a child */
- void addChildNotification(NotificationListItem child, int childIndex);
-
- /** set the child count view should display */
- void setUntruncatedChildCount(int count);
-
- /** Update the order of the children with the new list */
- boolean applyChildOrder(
- List<? extends NotificationListItem> childOrderList,
- VisualStabilityManager vsm,
- @Nullable VisualStabilityManager.Callback callback);
-
- /** return the associated view for this list item */
- @NonNull
- View getView();
-}
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 b9d31a93f408..66a541a923a4 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
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.statusbar.notification.stack;
@@ -3387,21 +3387,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
@Override
- public void notifyGroupChildRemoved(View child, ViewGroup parent) {
- notifyGroupChildRemoved((ExpandableView) child, parent);
- }
-
- @Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void notifyGroupChildAdded(ExpandableView row) {
onViewAddedInternal(row);
}
- @Override
- public void notifyGroupChildAdded(View view) {
- notifyGroupChildAdded((ExpandableView) view);
- }
-
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void setAnimationsEnabled(boolean animationsEnabled) {
mAnimationsEnabled = animationsEnabled;
@@ -5246,20 +5236,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
@Override
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void removeListItem(NotificationListItem v) {
- removeContainerView(v.getView());
- }
-
- @Override
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void addContainerView(View v) {
Assert.isMainThread();
addView(v);
}
@Override
- public void addListItem(NotificationListItem v) {
- addContainerView(v.getView());
+ public void addContainerViewAt(View v, int index) {
+ Assert.isMainThread();
+ addView(v, index);
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -6596,40 +6581,25 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
} else {
final List<Pair<NotificationEntry, DismissedByUserStats>>
entriesWithRowsDismissedFromShade = new ArrayList<>();
- final List<DismissedByUserStats> dismissalUserStats = new ArrayList<>();
final int numVisibleEntries = mNotifPipeline.getShadeListCount();
for (int i = 0; i < viewsToRemove.size(); i++) {
final NotificationEntry entry = viewsToRemove.get(i).getEntry();
- final DismissedByUserStats stats =
- new DismissedByUserStats(
- DISMISSAL_SHADE,
- DISMISS_SENTIMENT_NEUTRAL,
- NotificationVisibility.obtain(
- entry.getKey(),
- entry.getRanking().getRank(),
- numVisibleEntries,
- true,
- NotificationLogger.getNotificationLocation(entry)));
entriesWithRowsDismissedFromShade.add(
- new Pair<NotificationEntry, DismissedByUserStats>(entry, stats));
+ new Pair<NotificationEntry, DismissedByUserStats>(
+ entry,
+ getDismissedByUserStats(entry, numVisibleEntries)));
}
mNotifCollection.dismissNotifications(entriesWithRowsDismissedFromShade);
}
} else {
for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
if (canChildBeDismissed(rowToRemove)) {
- if (selectedRows == ROWS_ALL) {
- // TODO: This is a listener method; we shouldn't be calling it. Can we just
- // call performRemoveNotification as below?
- mEntryManager.removeNotification(
- rowToRemove.getEntry().getKey(),
- null /* ranking */,
- NotificationListenerService.REASON_CANCEL_ALL);
- } else {
- mEntryManager.performRemoveNotification(
- rowToRemove.getEntry().getSbn(),
- NotificationListenerService.REASON_CANCEL_ALL);
- }
+ mEntryManager.performRemoveNotification(
+ rowToRemove.getEntry().getSbn(),
+ getDismissedByUserStats(
+ rowToRemove.getEntry(),
+ mEntryManager.getActiveNotificationsCount()),
+ NotificationListenerService.REASON_CANCEL_ALL);
} else {
rowToRemove.resetTranslation();
}
@@ -6643,6 +6613,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
}
+ private DismissedByUserStats getDismissedByUserStats(
+ NotificationEntry entry,
+ int numVisibleEntries
+ ) {
+ return new DismissedByUserStats(
+ DISMISSAL_SHADE,
+ DISMISS_SENTIMENT_NEUTRAL,
+ NotificationVisibility.obtain(
+ entry.getKey(),
+ entry.getRanking().getRank(),
+ numVisibleEntries,
+ true,
+ NotificationLogger.getNotificationLocation(entry)));
+ }
+
// ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
@ShadeViewRefactor(RefactorComponent.INPUT)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 303a0831b52f..0e76c904f8cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -152,6 +152,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
private final Context mContext;
private final int mWakeUpDelay;
private int mMode;
+ private BiometricSourceType mBiometricType;
private KeyguardViewController mKeyguardViewController;
private DozeScrimController mDozeScrimController;
private KeyguardViewMediator mKeyguardViewMediator;
@@ -340,6 +341,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
Trace.endSection();
return;
}
+ mBiometricType = biometricSourceType;
mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
.setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
Optional.ofNullable(BiometricUiEvent.SUCCESS_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
@@ -615,6 +617,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
private void resetMode() {
mMode = MODE_NONE;
+ mBiometricType = null;
mNotificationShadeWindowController.setForceDozeBrightness(false);
if (mStatusBar.getNavigationBarView() != null) {
mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
@@ -680,8 +683,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
/**
* Successful authentication with fingerprint, face, or iris when the lockscreen fades away
*/
- public boolean isUnlockFading() {
- return mMode == MODE_UNLOCK_FADING;
+ public BiometricSourceType getBiometricType() {
+ return mBiometricType;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index e05ba12781c4..1d82e0808332 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -241,7 +241,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
/**
* Set that we are exiting the headsUp pinned mode, but some notifications might still be
- * animating out. This is used to keep the touchable regions in a sane state.
+ * animating out. This is used to keep the touchable regions in a reasonable state.
*/
void setHeadsUpGoingAway(boolean headsUpGoingAway) {
if (headsUpGoingAway != mHeadsUpGoingAway) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index 74d9f5402e36..bfe0684b5411 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -84,7 +84,9 @@ class KeyguardLiftController constructor(
val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
!statusBarStateController.isDozing
- val shouldListen = onKeyguard || bouncerVisible
+ val userId = KeyguardUpdateMonitor.getCurrentUser()
+ val isFaceEnabled = keyguardUpdateMonitor.isFaceAuthEnabledForUser(userId)
+ val shouldListen = (onKeyguard || bouncerVisible) && isFaceEnabled
if (shouldListen != isListening) {
isListening = shouldListen
@@ -95,4 +97,4 @@ class KeyguardLiftController constructor(
}
}
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
index 141bdc242861..1dc0f070835b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
@@ -83,6 +83,7 @@ public class LockscreenLockIconController {
private boolean mWakeAndUnlockRunning;
private boolean mShowingLaunchAffordance;
private boolean mBouncerShowingScrimmed;
+ private boolean mFingerprintUnlock;
private int mStatusBarState = StatusBarState.SHADE;
private LockIcon mLockIcon;
@@ -377,14 +378,19 @@ public class LockscreenLockIconController {
/**
* We need to hide the lock whenever there's a fingerprint unlock, otherwise you'll see the
* icon on top of the black front scrim.
+ * We also want to halt padlock the animation when we're in face bypass mode or dismissing the
+ * keyguard with fingerprint.
* @param wakeAndUnlock are we wake and unlocking
* @param isUnlock are we currently unlocking
*/
- public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock) {
+ public void onBiometricAuthModeChanged(boolean wakeAndUnlock, boolean isUnlock,
+ BiometricSourceType type) {
if (wakeAndUnlock) {
mWakeAndUnlockRunning = true;
}
- if (isUnlock && mKeyguardBypassController.getBypassEnabled() && canBlockUpdates()) {
+ mFingerprintUnlock = type == BiometricSourceType.FINGERPRINT;
+ if (isUnlock && (mFingerprintUnlock || mKeyguardBypassController.getBypassEnabled())
+ && canBlockUpdates()) {
// We don't want the icon to change while we are unlocking
mBlockUpdates = true;
}
@@ -498,10 +504,13 @@ public class LockscreenLockIconController {
private boolean updateIconVisibility() {
boolean onAodOrDocked = mStatusBarStateController.isDozing() && mDocked;
boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance;
- if (mKeyguardBypassController.getBypassEnabled() && !mBouncerShowingScrimmed) {
+ boolean fingerprintOrBypass = mFingerprintUnlock
+ || mKeyguardBypassController.getBypassEnabled();
+ if (fingerprintOrBypass && !mBouncerShowingScrimmed) {
if ((mHeadsUpManagerPhone.isHeadsUpGoingAway()
|| mHeadsUpManagerPhone.hasPinnedHeadsUp()
- || mStatusBarState == StatusBarState.KEYGUARD)
+ || mStatusBarState == StatusBarState.KEYGUARD
+ || mStatusBarState == StatusBarState.SHADE)
&& !mNotificationWakeUpCoordinator.getNotificationsFullyHidden()) {
invisible = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index f43fa648a1a2..6297052550c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -1211,6 +1211,9 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
}
private void updateAccessibilityServicesState(AccessibilityManager accessibilityManager) {
+ if (mNavigationBarView == null) {
+ return;
+ }
boolean[] feedbackEnabled = new boolean[1];
int a11yFlags = getA11yButtonState(feedbackEnabled);
@@ -1428,6 +1431,9 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ if (mNavigationBarView == null) {
+ return;
+ }
String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)
|| Intent.ACTION_SCREEN_ON.equals(action)) {
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 375af6b099c2..99cb4760a8d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -62,7 +62,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
-import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardClockSwitchController;
import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -124,6 +124,7 @@ import java.util.function.Consumer;
import java.util.function.Function;
import javax.inject.Inject;
+import javax.inject.Provider;
@StatusBarComponent.StatusBarScope
public class NotificationPanelViewController extends PanelViewController {
@@ -252,6 +253,7 @@ public class NotificationPanelViewController extends PanelViewController {
private final ConversationNotificationManager mConversationNotificationManager;
private final MediaHierarchyManager mMediaHierarchyManager;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ private final Provider<KeyguardClockSwitchController> mKeyguardClockSwitchControllerProvider;
private KeyguardAffordanceHelper mAffordanceHelper;
private KeyguardUserSwitcher mKeyguardUserSwitcher;
@@ -495,7 +497,8 @@ public class NotificationPanelViewController extends PanelViewController {
ConversationNotificationManager conversationNotificationManager,
MediaHierarchyManager mediaHierarchyManager,
BiometricUnlockController biometricUnlockController,
- StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ Provider<KeyguardClockSwitchController> keyguardClockSwitchControllerProvider) {
super(view, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
@@ -507,6 +510,7 @@ public class NotificationPanelViewController extends PanelViewController {
mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
mMediaHierarchyManager = mediaHierarchyManager;
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ mKeyguardClockSwitchControllerProvider = keyguardClockSwitchControllerProvider;
mView.setWillNotDraw(!DEBUG);
mInjectionInflationController = injectionInflationController;
mFalsingManager = falsingManager;
@@ -579,9 +583,11 @@ public class NotificationPanelViewController extends PanelViewController {
mKeyguardStatusBar = mView.findViewById(R.id.keyguard_header);
mKeyguardStatusView = mView.findViewById(R.id.keyguard_status_view);
- KeyguardClockSwitch keyguardClockSwitch = mView.findViewById(R.id.keyguard_clock_container);
+ KeyguardClockSwitchController keyguardClockSwitchController =
+ mKeyguardClockSwitchControllerProvider.get();
+ keyguardClockSwitchController.attach(mView.findViewById(R.id.keyguard_clock_container));
mBigClockContainer = mView.findViewById(R.id.big_clock_container);
- keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+ keyguardClockSwitchController.setBigClockContainer(mBigClockContainer);
mNotificationContainerParent = mView.findViewById(R.id.notification_container_parent);
mNotificationStackScroller = mView.findViewById(R.id.notification_stack_scroller);
@@ -703,8 +709,10 @@ public class NotificationPanelViewController extends PanelViewController {
// Re-associate the clock container with the keyguard clock switch.
mBigClockContainer.removeAllViews();
- KeyguardClockSwitch keyguardClockSwitch = mView.findViewById(R.id.keyguard_clock_container);
- keyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+ KeyguardClockSwitchController keyguardClockSwitchController =
+ mKeyguardClockSwitchControllerProvider.get();
+ keyguardClockSwitchController.attach(mView.findViewById(R.id.keyguard_clock_container));
+ keyguardClockSwitchController.setBigClockContainer(mBigClockContainer);
// Update keyguard bottom area
index = mView.indexOfChild(mKeyguardBottomArea);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index e942d85790c1..ac329e2598a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -408,7 +408,7 @@ public abstract class PanelViewController {
&& !mKeyguardStateController.isKeyguardFadingAway()) {
long timePassed = SystemClock.uptimeMillis() - mDownTime;
if (timePassed < ViewConfiguration.getLongPressTimeout()) {
- // Lets show the user that he can actually expand the panel
+ // Let's show the user that they can actually expand the panel
runPeekAnimation(
PEEK_ANIMATION_DURATION, getPeekHeight(), true /* collapseWhenFinished */);
} else {
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 c5571e8ceb20..eb626280b494 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3975,7 +3975,8 @@ public class StatusBar extends SystemUI implements DemoMode,
updateScrimController();
mLockscreenLockIconController.onBiometricAuthModeChanged(
mBiometricUnlockController.isWakeAndUnlock(),
- mBiometricUnlockController.isBiometricUnlock());
+ mBiometricUnlockController.isBiometricUnlock(),
+ mBiometricUnlockController.getBiometricType());
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 3ae84ecfc2f0..b89cb210dea1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -79,15 +79,16 @@ public interface StatusBarIconController {
public void removeIcon(String slot, int tag);
public void removeAllIconsForSlot(String slot);
- public static final String ICON_BLACKLIST = "icon_blacklist";
+ // TODO: See if we can rename this tunable name.
+ String ICON_HIDE_LIST = "icon_blacklist";
- /** Reads the default blacklist from config value unless blacklistStr is provided. */
- static ArraySet<String> getIconBlacklist(Context context, String blackListStr) {
+ /** Reads the default hide list from config value unless hideListStr is provided. */
+ static ArraySet<String> getIconHideList(Context context, String hideListStr) {
ArraySet<String> ret = new ArraySet<>();
- String[] blacklist = blackListStr == null
+ String[] hideList = hideListStr == null
? context.getResources().getStringArray(R.array.config_statusBarIconBlackList)
- : blackListStr.split(",");
- for (String slot : blacklist) {
+ : hideListStr.split(",");
+ for (String slot : hideList) {
if (!TextUtils.isEmpty(slot)) {
ret.add(slot);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index d0e806769f14..21e1d319cffa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -59,7 +59,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
private static final String TAG = "StatusBarIconController";
private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
- private final ArraySet<String> mIconBlacklist = new ArraySet<>();
+ private final ArraySet<String> mIconHideList = new ArraySet<>();
// Points to light or dark context depending on the... context?
private Context mContext;
@@ -79,7 +79,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
loadDimens();
commandQueue.addCallback(this);
- Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
+ Dependency.get(TunerService.class).addTunable(this, ICON_HIDE_LIST);
}
@Override
@@ -89,12 +89,12 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
for (int i = 0; i < allSlots.size(); i++) {
Slot slot = allSlots.get(i);
List<StatusBarIconHolder> holders = slot.getHolderListInViewOrder();
- boolean blocked = mIconBlacklist.contains(slot.getName());
+ boolean hidden = mIconHideList.contains(slot.getName());
for (StatusBarIconHolder holder : holders) {
int tag = holder.getTag();
int viewIndex = getViewIndex(getSlotIndex(slot.getName()), holder.getTag());
- group.onIconAdded(viewIndex, slot.getName(), blocked, holder);
+ group.onIconAdded(viewIndex, slot.getName(), hidden, holder);
}
}
}
@@ -107,11 +107,11 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
@Override
public void onTuningChanged(String key, String newValue) {
- if (!ICON_BLACKLIST.equals(key)) {
+ if (!ICON_HIDE_LIST.equals(key)) {
return;
}
- mIconBlacklist.clear();
- mIconBlacklist.addAll(StatusBarIconController.getIconBlacklist(mContext, newValue));
+ mIconHideList.clear();
+ mIconHideList.addAll(StatusBarIconController.getIconHideList(mContext, newValue));
ArrayList<Slot> currentSlots = getSlots();
ArrayMap<Slot, List<StatusBarIconHolder>> slotsToReAdd = new ArrayMap<>();
@@ -142,9 +142,9 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
private void addSystemIcon(int index, StatusBarIconHolder holder) {
String slot = getSlotName(index);
int viewIndex = getViewIndex(index, holder.getTag());
- boolean blocked = mIconBlacklist.contains(slot);
+ boolean hidden = mIconHideList.contains(slot);
- mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, holder));
+ mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, hidden, holder));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 7bcfb466d7d9..4de648402464 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import static android.service.notification.NotificationListenerService.REASON_CLICK;
-import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
import static com.android.systemui.statusbar.phone.StatusBar.getActivityOptions;
@@ -37,7 +36,6 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.dreams.IDreamManager;
-import android.service.notification.NotificationStats;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.EventLog;
@@ -71,11 +69,11 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.OnDismissCallback;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -128,6 +126,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final NotificationPresenter mPresenter;
private final NotificationPanelViewController mNotificationPanel;
private final ActivityLaunchAnimator mActivityLaunchAnimator;
+ private final OnDismissCallback mOnDismissCallback;
private boolean mIsCollapsingToShowActivityOverLockscreen;
@@ -162,6 +161,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
FeatureFlags featureFlags,
MetricsLogger metricsLogger,
StatusBarNotificationActivityStarterLogger logger,
+ OnDismissCallback onDismissCallback,
StatusBar statusBar,
NotificationPresenter presenter,
@@ -197,6 +197,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mFeatureFlags = featureFlags;
mMetricsLogger = metricsLogger;
mLogger = logger;
+ mOnDismissCallback = onDismissCallback;
// TODO: use KeyguardStateController#isOccluded to remove this dependency
mStatusBar = statusBar;
@@ -574,13 +575,14 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private void removeNotification(NotificationEntry entry) {
// We have to post it to the UI thread for synchronization
mMainThreadHandler.post(() -> {
- Runnable removeRunnable = createRemoveRunnable(entry);
if (mPresenter.isCollapsing()) {
// To avoid lags we're only performing the remove
// after the shade was collapsed
- mShadeController.addPostCollapseAction(removeRunnable);
+ mShadeController.addPostCollapseAction(
+ () -> mOnDismissCallback.onDismiss(entry, REASON_CLICK)
+ );
} else {
- removeRunnable.run();
+ mOnDismissCallback.onDismiss(entry, REASON_CLICK);
}
});
}
@@ -595,43 +597,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}
}
- private Runnable createRemoveRunnable(NotificationEntry entry) {
- if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
- return new Runnable() {
- @Override
- public void run() {
- // see NotificationLogger#logNotificationClear
- int dismissalSurface = NotificationStats.DISMISSAL_SHADE;
- if (mHeadsUpManager.isAlerting(entry.getKey())) {
- dismissalSurface = NotificationStats.DISMISSAL_PEEK;
- } else if (mNotificationPanel.hasPulsingNotifications()) {
- dismissalSurface = NotificationStats.DISMISSAL_AOD;
- }
-
- mNotifCollection.dismissNotification(
- entry,
- new DismissedByUserStats(
- dismissalSurface,
- DISMISS_SENTIMENT_NEUTRAL,
- NotificationVisibility.obtain(
- entry.getKey(),
- entry.getRanking().getRank(),
- mNotifPipeline.getShadeListCount(),
- true,
- NotificationLogger.getNotificationLocation(entry))
- ));
- }
- };
- } else {
- return new Runnable() {
- @Override
- public void run() {
- mEntryManager.performRemoveNotification(entry.getSbn(), REASON_CLICK);
- }
- };
- }
- }
-
/**
* Public builder for {@link StatusBarNotificationActivityStarter}.
*/
@@ -667,6 +632,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final FeatureFlags mFeatureFlags;
private final MetricsLogger mMetricsLogger;
private final StatusBarNotificationActivityStarterLogger mLogger;
+ private final OnDismissCallback mOnDismissCallback;
private StatusBar mStatusBar;
private NotificationPresenter mNotificationPresenter;
@@ -704,7 +670,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
FeatureFlags featureFlags,
MetricsLogger metricsLogger,
- StatusBarNotificationActivityStarterLogger logger) {
+ StatusBarNotificationActivityStarterLogger logger,
+ OnDismissCallback onDismissCallback) {
mContext = context;
mCommandQueue = commandQueue;
@@ -736,6 +703,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mFeatureFlags = featureFlags;
mMetricsLogger = metricsLogger;
mLogger = logger;
+ mOnDismissCallback = onDismissCallback;
}
/** Sets the status bar to use as {@link StatusBar}. */
@@ -793,6 +761,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mFeatureFlags,
mMetricsLogger,
mLogger,
+ mOnDismissCallback,
mStatusBar,
mNotificationPresenter,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 690d57345db6..7eefaf28517e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -52,12 +52,12 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
private final SecurityController mSecurityController;
private final Handler mHandler = Handler.getMain();
- private boolean mBlockAirplane;
- private boolean mBlockMobile;
- private boolean mBlockWifi;
- private boolean mBlockEthernet;
+ private boolean mHideAirplane;
+ private boolean mHideMobile;
+ private boolean mHideWifi;
+ private boolean mHideEthernet;
private boolean mActivityEnabled;
- private boolean mForceBlockWifi;
+ private boolean mForceHideWifi;
// Track as little state as possible, and only for padding purposes
private boolean mIsAirplaneMode = false;
@@ -80,7 +80,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
mNetworkController = Dependency.get(NetworkController.class);
mSecurityController = Dependency.get(SecurityController.class);
- Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_HIDE_LIST);
mNetworkController.addCallback(this);
mSecurityController.addCallback(this);
}
@@ -114,21 +114,21 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
@Override
public void onTuningChanged(String key, String newValue) {
- if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
+ if (!StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
return;
}
- ArraySet<String> blockList = StatusBarIconController.getIconBlacklist(mContext, newValue);
- boolean blockAirplane = blockList.contains(mSlotAirplane);
- boolean blockMobile = blockList.contains(mSlotMobile);
- boolean blockWifi = blockList.contains(mSlotWifi);
- boolean blockEthernet = blockList.contains(mSlotEthernet);
-
- if (blockAirplane != mBlockAirplane || blockMobile != mBlockMobile
- || blockEthernet != mBlockEthernet || blockWifi != mBlockWifi) {
- mBlockAirplane = blockAirplane;
- mBlockMobile = blockMobile;
- mBlockEthernet = blockEthernet;
- mBlockWifi = blockWifi || mForceBlockWifi;
+ ArraySet<String> hideList = StatusBarIconController.getIconHideList(mContext, newValue);
+ boolean hideAirplane = hideList.contains(mSlotAirplane);
+ boolean hideMobile = hideList.contains(mSlotMobile);
+ boolean hideWifi = hideList.contains(mSlotWifi);
+ boolean hideEthernet = hideList.contains(mSlotEthernet);
+
+ if (hideAirplane != mHideAirplane || hideMobile != mHideMobile
+ || hideEthernet != mHideEthernet || hideWifi != mHideWifi) {
+ mHideAirplane = hideAirplane;
+ mHideMobile = hideMobile;
+ mHideEthernet = hideEthernet;
+ mHideWifi = hideWifi || mForceHideWifi;
// Re-register to get new callbacks.
mNetworkController.removeCallback(this);
mNetworkController.addCallback(this);
@@ -140,7 +140,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
boolean activityIn, boolean activityOut, String description, boolean isTransient,
String statusLabel) {
- boolean visible = statusIcon.visible && !mBlockWifi;
+ boolean visible = statusIcon.visible && !mHideWifi;
boolean in = activityIn && mActivityEnabled && visible;
boolean out = activityOut && mActivityEnabled && visible;
@@ -189,7 +189,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
// Visibility of the data type indicator changed
boolean typeChanged = statusType != state.typeId && (statusType == 0 || state.typeId == 0);
- state.visible = statusIcon.visible && !mBlockMobile;
+ state.visible = statusIcon.visible && !mHideMobile;
state.strengthId = statusIcon.icon;
state.typeId = statusType;
state.contentDescription = statusIcon.contentDescription;
@@ -270,7 +270,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
@Override
public void setEthernetIndicators(IconState state) {
- boolean visible = state.visible && !mBlockEthernet;
+ boolean visible = state.visible && !mHideEthernet;
int resId = state.icon;
String description = state.contentDescription;
@@ -284,7 +284,7 @@ public class StatusBarSignalPolicy implements NetworkControllerImpl.SignalCallba
@Override
public void setIsAirplaneMode(IconState icon) {
- mIsAirplaneMode = icon.visible && !mBlockAirplane;
+ mIsAirplaneMode = icon.visible && !mHideAirplane;
int resId = icon.icon;
String description = icon.contentDescription;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index d30f01a658f6..88a6263c1dca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -74,7 +74,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
protected boolean mPowerSave;
private boolean mAodPowerSave;
protected boolean mWirelessCharging;
- private boolean mTestmode = false;
+ private boolean mTestMode = false;
@VisibleForTesting
boolean mHasReceivedBattery = false;
private Estimate mEstimate;
@@ -154,7 +154,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
public void onReceive(final Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
- if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
+ if (mTestMode && !intent.getBooleanExtra("testmode", false)) return;
mHasReceivedBattery = true;
mLevel = (int)(100f
* intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
@@ -172,29 +172,29 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
updatePowerSave();
} else if (action.equals(ACTION_LEVEL_TEST)) {
- mTestmode = true;
+ mTestMode = true;
mMainHandler.post(new Runnable() {
int curLevel = 0;
int incr = 1;
int saveLevel = mLevel;
boolean savePlugged = mPluggedIn;
- Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
+ Intent mTestIntent = new Intent(Intent.ACTION_BATTERY_CHANGED);
@Override
public void run() {
if (curLevel < 0) {
- mTestmode = false;
- dummy.putExtra("level", saveLevel);
- dummy.putExtra("plugged", savePlugged);
- dummy.putExtra("testmode", false);
+ mTestMode = false;
+ mTestIntent.putExtra("level", saveLevel);
+ mTestIntent.putExtra("plugged", savePlugged);
+ mTestIntent.putExtra("testmode", false);
} else {
- dummy.putExtra("level", curLevel);
- dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
+ mTestIntent.putExtra("level", curLevel);
+ mTestIntent.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
: 0);
- dummy.putExtra("testmode", true);
+ mTestIntent.putExtra("testmode", true);
}
- context.sendBroadcast(dummy);
+ context.sendBroadcast(mTestIntent);
- if (!mTestmode) return;
+ if (!mTestMode) return;
curLevel += incr;
if (curLevel == 100) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 95601955ec04..120a0e3abba4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -191,7 +191,7 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C
mBroadcastDispatcher.registerReceiverWithHandler(mIntentReceiver, filter,
Dependency.get(Dependency.TIME_TICK_HANDLER), UserHandle.ALL);
Dependency.get(TunerService.class).addTunable(this, CLOCK_SECONDS,
- StatusBarIconController.ICON_BLACKLIST);
+ StatusBarIconController.ICON_HIDE_LIST);
mCommandQueue.addCallback(this);
if (mShowDark) {
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);
@@ -305,8 +305,8 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C
if (CLOCK_SECONDS.equals(key)) {
mShowSeconds = TunerService.parseIntegerSwitch(newValue, false);
updateShowSeconds();
- } else {
- setClockVisibleByUser(!StatusBarIconController.getIconBlacklist(getContext(), newValue)
+ } else if (StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
+ setClockVisibleByUser(!StatusBarIconController.getIconHideList(getContext(), newValue)
.contains("clock"));
updateClockVisibility();
}
@@ -404,7 +404,7 @@ public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.C
mContentDescriptionFormat = new SimpleDateFormat(format);
/*
* Search for an unquoted "a" in the format string, so we can
- * add dummy characters around it to let us find it again after
+ * add marker characters around it to let us find it again after
* formatting and change its size.
*/
if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
index 54502e41ca64..12d0617d90ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeadZone.java
@@ -198,7 +198,7 @@ public class DeadZone {
can.drawARGB((int) (frac * 0xFF), 0xDD, 0xEE, 0xAA);
if (DEBUG && size > mSizeMin)
- // crazy aggressive redrawing here, for debugging only
+ // Very aggressive redrawing here, for debugging only
mNavigationBarView.postInvalidateDelayed(100);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
index 66372c311325..b71aafdf6b96 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
@@ -38,7 +38,7 @@ public class BatteryPreference extends DropDownPreference implements TunerServic
private final String mBattery;
private boolean mBatteryEnabled;
private boolean mHasPercentage;
- private ArraySet<String> mBlacklist;
+ private ArraySet<String> mHideList;
private boolean mHasSetValue;
public BatteryPreference(Context context, AttributeSet attrs) {
@@ -52,7 +52,7 @@ public class BatteryPreference extends DropDownPreference implements TunerServic
super.onAttached();
mHasPercentage = Settings.System.getInt(getContext().getContentResolver(),
SHOW_BATTERY_PERCENT, 0) != 0;
- Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_HIDE_LIST);
}
@Override
@@ -63,9 +63,9 @@ public class BatteryPreference extends DropDownPreference implements TunerServic
@Override
public void onTuningChanged(String key, String newValue) {
- if (StatusBarIconController.ICON_BLACKLIST.equals(key)) {
- mBlacklist = StatusBarIconController.getIconBlacklist(getContext(), newValue);
- mBatteryEnabled = !mBlacklist.contains(mBattery);
+ if (StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
+ mHideList = StatusBarIconController.getIconHideList(getContext(), newValue);
+ mBatteryEnabled = !mHideList.contains(mBattery);
}
if (!mHasSetValue) {
// Because of the complicated tri-state it can end up looping and setting state back to
@@ -88,12 +88,12 @@ public class BatteryPreference extends DropDownPreference implements TunerServic
MetricsLogger.action(getContext(), MetricsEvent.TUNER_BATTERY_PERCENTAGE, v);
Settings.System.putInt(getContext().getContentResolver(), SHOW_BATTERY_PERCENT, v ? 1 : 0);
if (DISABLED.equals(value)) {
- mBlacklist.add(mBattery);
+ mHideList.add(mBattery);
} else {
- mBlacklist.remove(mBattery);
+ mHideList.remove(mBattery);
}
- Dependency.get(TunerService.class).setValue(StatusBarIconController.ICON_BLACKLIST,
- TextUtils.join(",", mBlacklist));
+ Dependency.get(TunerService.class).setValue(StatusBarIconController.ICON_HIDE_LIST,
+ TextUtils.join(",", mHideList));
return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
index f7d0c9fb9d86..c92d7bbfe0b7 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
@@ -33,7 +33,7 @@ public class ClockPreference extends DropDownPreference implements TunerService.
private final String mClock;
private boolean mClockEnabled;
private boolean mHasSeconds;
- private ArraySet<String> mBlacklist;
+ private ArraySet<String> mHideList;
private boolean mHasSetValue;
private boolean mReceivedSeconds;
private boolean mReceivedClock;
@@ -47,7 +47,7 @@ public class ClockPreference extends DropDownPreference implements TunerService.
@Override
public void onAttached() {
super.onAttached();
- Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST,
+ Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_HIDE_LIST,
Clock.CLOCK_SECONDS);
}
@@ -59,10 +59,10 @@ public class ClockPreference extends DropDownPreference implements TunerService.
@Override
public void onTuningChanged(String key, String newValue) {
- if (StatusBarIconController.ICON_BLACKLIST.equals(key)) {
+ if (StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
mReceivedClock = true;
- mBlacklist = StatusBarIconController.getIconBlacklist(getContext(), newValue);
- mClockEnabled = !mBlacklist.contains(mClock);
+ mHideList = StatusBarIconController.getIconHideList(getContext(), newValue);
+ mClockEnabled = !mHideList.contains(mClock);
} else if (Clock.CLOCK_SECONDS.equals(key)) {
mReceivedSeconds = true;
mHasSeconds = newValue != null && Integer.parseInt(newValue) != 0;
@@ -87,12 +87,12 @@ public class ClockPreference extends DropDownPreference implements TunerService.
Dependency.get(TunerService.class).setValue(Clock.CLOCK_SECONDS, SECONDS.equals(value) ? 1
: 0);
if (DISABLED.equals(value)) {
- mBlacklist.add(mClock);
+ mHideList.add(mClock);
} else {
- mBlacklist.remove(mClock);
+ mHideList.remove(mClock);
}
- Dependency.get(TunerService.class).setValue(StatusBarIconController.ICON_BLACKLIST,
- TextUtils.join(",", mBlacklist));
+ Dependency.get(TunerService.class).setValue(StatusBarIconController.ICON_HIDE_LIST,
+ TextUtils.join(",", mHideList));
return true;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index de8ccfa848e3..cc0050b64d60 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -34,7 +34,7 @@ import java.util.Set;
public class StatusBarSwitch extends SwitchPreference implements Tunable {
- private Set<String> mBlacklist;
+ private Set<String> mHideList;
public StatusBarSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -43,7 +43,7 @@ public class StatusBarSwitch extends SwitchPreference implements Tunable {
@Override
public void onAttached() {
super.onAttached();
- Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_HIDE_LIST);
}
@Override
@@ -54,35 +54,35 @@ public class StatusBarSwitch extends SwitchPreference implements Tunable {
@Override
public void onTuningChanged(String key, String newValue) {
- if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
+ if (!StatusBarIconController.ICON_HIDE_LIST.equals(key)) {
return;
}
- mBlacklist = StatusBarIconController.getIconBlacklist(getContext(), newValue);
- setChecked(!mBlacklist.contains(getKey()));
+ mHideList = StatusBarIconController.getIconHideList(getContext(), newValue);
+ setChecked(!mHideList.contains(getKey()));
}
@Override
protected boolean persistBoolean(boolean value) {
if (!value) {
- // If not enabled add to blacklist.
- if (!mBlacklist.contains(getKey())) {
+ // If not enabled add to hideList.
+ if (!mHideList.contains(getKey())) {
MetricsLogger.action(getContext(), MetricsEvent.TUNER_STATUS_BAR_DISABLE,
getKey());
- mBlacklist.add(getKey());
- setList(mBlacklist);
+ mHideList.add(getKey());
+ setList(mHideList);
}
} else {
- if (mBlacklist.remove(getKey())) {
+ if (mHideList.remove(getKey())) {
MetricsLogger.action(getContext(), MetricsEvent.TUNER_STATUS_BAR_ENABLE, getKey());
- setList(mBlacklist);
+ setList(mHideList);
}
}
return true;
}
- private void setList(Set<String> blacklist) {
+ private void setList(Set<String> hideList) {
ContentResolver contentResolver = getContext().getContentResolver();
- Settings.Secure.putStringForUser(contentResolver, StatusBarIconController.ICON_BLACKLIST,
- TextUtils.join(",", blacklist), ActivityManager.getCurrentUser());
+ Settings.Secure.putStringForUser(contentResolver, StatusBarIconController.ICON_HIDE_LIST,
+ TextUtils.join(",", hideList), ActivityManager.getCurrentUser());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 9ad2aa257aa0..644f7582f146 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -60,7 +60,7 @@ public class TunerServiceImpl extends TunerService {
// Things that use the tunable infrastructure but are now real user settings and
// shouldn't be reset with tuner settings.
- private static final String[] RESET_BLACKLIST = new String[] {
+ private static final String[] RESET_EXCEPTION_LIST = new String[] {
QSTileHost.TILES_SETTING,
Settings.Secure.DOZE_ALWAYS_ON,
Settings.Secure.MEDIA_CONTROLS_RESUME
@@ -116,17 +116,17 @@ public class TunerServiceImpl extends TunerService {
private void upgradeTuner(int oldVersion, int newVersion, Handler mainHandler) {
if (oldVersion < 1) {
- String blacklistStr = getValue(StatusBarIconController.ICON_BLACKLIST);
- if (blacklistStr != null) {
- ArraySet<String> iconBlacklist =
- StatusBarIconController.getIconBlacklist(mContext, blacklistStr);
+ String hideListStr = getValue(StatusBarIconController.ICON_HIDE_LIST);
+ if (hideListStr != null) {
+ ArraySet<String> iconHideList =
+ StatusBarIconController.getIconHideList(mContext, hideListStr);
- iconBlacklist.add("rotate");
- iconBlacklist.add("headset");
+ iconHideList.add("rotate");
+ iconHideList.add("headset");
Settings.Secure.putStringForUser(mContentResolver,
- StatusBarIconController.ICON_BLACKLIST,
- TextUtils.join(",", iconBlacklist), mCurrentUser);
+ StatusBarIconController.ICON_HIDE_LIST,
+ TextUtils.join(",", iconHideList), mCurrentUser);
}
}
if (oldVersion < 2) {
@@ -251,7 +251,7 @@ public class TunerServiceImpl extends TunerService {
mContext.sendBroadcast(intent);
for (String key : mTunableLookup.keySet()) {
- if (ArrayUtils.contains(RESET_BLACKLIST, key)) {
+ if (ArrayUtils.contains(RESET_EXCEPTION_LIST, key)) {
continue;
}
Settings.Secure.putStringForUser(mContentResolver, key, null, user);
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index c63712389a80..551b7b41212a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -23,7 +23,6 @@ import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;
-import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardMessageArea;
import com.android.keyguard.KeyguardSliceView;
import com.android.systemui.dagger.SystemUIRootComponent;
@@ -132,11 +131,6 @@ public class InjectionInflationController {
NotificationShelf creatNotificationShelf();
/**
- * Creates the KeyguardClockSwitch.
- */
- KeyguardClockSwitch createKeyguardClockSwitch();
-
- /**
* Creates the KeyguardSliceView.
*/
KeyguardSliceView createKeyguardSliceView();
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
index b25df5f9c07f..5e7280840bb9 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
@@ -104,9 +104,13 @@ public class LeakReporter {
.setContentText(String.format(
"SystemUI has detected %d leaked objects. Tap to send", garbageCount))
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
- .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
+ .setContentIntent(PendingIntent.getActivityAsUser(
+ mContext,
+ 0,
getIntent(hprofFile, dumpFile),
- PendingIntent.FLAG_UPDATE_CURRENT, null, UserHandle.CURRENT));
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+ null,
+ UserHandle.CURRENT));
notiMan.notify(TAG, 0, builder.build());
} catch (IOException e) {
Log.e(TAG, "Couldn't dump heap for leak", e);
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index 9fa03df4229a..06806d0e6ab6 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -338,7 +338,7 @@ public class ProximitySensor implements ThresholdSensor {
@Override
public void run() {
unregister();
- mSensor.alertListeners();
+ onProximityEvent(null);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java
index fbc167683a2a..5b2c39db2eae 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WindowManagerShellModule.java
@@ -59,9 +59,10 @@ public class WindowManagerShellModule {
@Singleton
@Provides
- static DisplayImeController provideDisplayImeController(
- IWindowManager wmService, DisplayController displayController,
- @Main Handler mainHandler, TransactionPool transactionPool) {
- return new DisplayImeController(wmService, displayController, mainHandler, transactionPool);
+ static DisplayImeController provideDisplayImeController(IWindowManager wmService,
+ DisplayController displayController, @Main Handler mainHandler,
+ TransactionPool transactionPool) {
+ return new DisplayImeController.Builder(wmService, displayController, mainHandler,
+ transactionPool).build();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
new file mode 100644
index 000000000000..657e4fbb4633
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.keyguard;
+
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+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.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.internal.colorextraction.ColorExtractor;
+import com.android.keyguard.clock.ClockManager;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.plugins.ClockPlugin;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.verification.VerificationMode;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class KeyguardClockSwitchControllerTest extends SysuiTestCase {
+
+ @Mock
+ private StatusBarStateController mStatusBarStateController;
+ @Mock
+ private SysuiColorExtractor mColorExtractor;
+ @Mock
+ private ClockManager mClockManager;
+ @Mock
+ private KeyguardClockSwitch mView;
+ @Mock
+ private ClockPlugin mClockPlugin;
+ @Mock
+ ColorExtractor.GradientColors mGradientColors;
+
+ private KeyguardClockSwitchController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ mController = new KeyguardClockSwitchController(
+ mStatusBarStateController, mColorExtractor, mClockManager);
+
+ when(mView.isAttachedToWindow()).thenReturn(true);
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
+ when(mColorExtractor.getColors(anyInt())).thenReturn(mGradientColors);
+ }
+
+ @Test
+ public void testAttach_viewAlreadyAttached() {
+ mController.attach(mView);
+
+ verifyAttachment(times(1));
+ }
+
+ @Test
+ public void testAttach_viewNotYetAttached() {
+ ArgumentCaptor<View.OnAttachStateChangeListener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
+
+ when(mView.isAttachedToWindow()).thenReturn(false);
+ mController.attach(mView);
+ verify(mView).addOnAttachStateChangeListener(listenerArgumentCaptor.capture());
+
+ verifyAttachment(never());
+
+ listenerArgumentCaptor.getValue().onViewAttachedToWindow(mView);
+
+ verifyAttachment(times(1));
+ }
+
+
+ @Test
+ public void testAttach_viewDetached() {
+ ArgumentCaptor<View.OnAttachStateChangeListener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
+ mController.attach(mView);
+ verify(mView).addOnAttachStateChangeListener(listenerArgumentCaptor.capture());
+
+ verifyAttachment(times(1));
+
+ listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
+
+ verify(mStatusBarStateController).removeCallback(
+ any(StatusBarStateController.StateListener.class));
+ verify(mColorExtractor).removeOnColorsChangedListener(
+ any(ColorExtractor.OnColorsChangedListener.class));
+ }
+
+ @Test
+ public void testBigClockPassesStatusBarState() {
+ ViewGroup testView = new FrameLayout(mContext);
+
+ mController.attach(mView);
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
+ mController.setBigClockContainer(testView);
+ verify(mView).setBigClockContainer(testView, StatusBarState.SHADE);
+
+
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
+ mController.setBigClockContainer(testView);
+ verify(mView).setBigClockContainer(testView, StatusBarState.KEYGUARD);
+
+
+ when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED);
+ mController.setBigClockContainer(testView);
+ verify(mView).setBigClockContainer(testView, StatusBarState.SHADE_LOCKED);
+ }
+
+ @Test
+ public void testPluginPassesStatusBarState() {
+ ArgumentCaptor<ClockManager.ClockChangedListener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(ClockManager.ClockChangedListener.class);
+
+ mController.attach(mView);
+ verify(mClockManager).addOnClockChangedListener(listenerArgumentCaptor.capture());
+
+ listenerArgumentCaptor.getValue().onClockChanged(mClockPlugin);
+ verify(mView).setClockPlugin(mClockPlugin, StatusBarState.SHADE);
+ }
+
+ private void verifyAttachment(VerificationMode times) {
+ verify(mClockManager, times).addOnClockChangedListener(
+ any(ClockManager.ClockChangedListener.class));
+ verify(mStatusBarStateController, times).addCallback(
+ any(StatusBarStateController.StateListener.class));
+ verify(mColorExtractor, times).addOnColorsChangedListener(
+ any(ColorExtractor.OnColorsChangedListener.class));
+ verify(mView, times).updateColors(mGradientColors);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index 04ceee8b9cea..4c0762e4ea32 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -40,12 +40,10 @@ import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextClock;
-import com.android.keyguard.clock.ClockManager;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.ClockPlugin;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.util.InjectionInflationController;
@@ -66,7 +64,6 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
private FrameLayout mClockContainer;
private FrameLayout mBigClockContainer;
private TextClock mBigClock;
- private StatusBarStateController.StateListener mStateListener;
@Mock
TextClock mClockView;
@@ -108,7 +105,6 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
mBigClock = new TextClock(getContext());
MockitoAnnotations.initMocks(this);
when(mClockView.getPaint()).thenReturn(mock(TextPaint.class));
- mStateListener = mKeyguardClockSwitch.getStateListener();
}
@Test
@@ -117,7 +113,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
TextClock pluginView = new TextClock(getContext());
when(plugin.getView()).thenReturn(pluginView);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
verify(mClockView).setVisibility(GONE);
assertThat(plugin.getView().getParent()).isEqualTo(mClockContainer);
@@ -127,14 +123,14 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void onPluginConnected_showPluginBigClock() {
// GIVEN that the container for the big clock has visibility GONE
mBigClockContainer.setVisibility(GONE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+ mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// AND the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
// AND in the keyguard state
- mStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// THEN the big clock container is visible and it is the parent of the
// big clock view.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
@@ -144,7 +140,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
@Test
public void onPluginConnected_nullView() {
ClockPlugin plugin = mock(ClockPlugin.class);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
verify(mClockView, never()).setVisibility(GONE);
}
@@ -153,11 +149,11 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// GIVEN a plugin has already connected
ClockPlugin plugin1 = mock(ClockPlugin.class);
when(plugin1.getView()).thenReturn(new TextClock(getContext()));
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin1);
+ mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD);
// WHEN a second plugin is connected
ClockPlugin plugin2 = mock(ClockPlugin.class);
when(plugin2.getView()).thenReturn(new TextClock(getContext()));
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin2);
+ mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD);
// THEN only the view from the second plugin should be a child of KeyguardClockSwitch.
assertThat(plugin2.getView().getParent()).isEqualTo(mClockContainer);
assertThat(plugin1.getView().getParent()).isNull();
@@ -169,7 +165,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
mKeyguardClockSwitch.setDarkAmount(0.5f);
// WHEN a plugin is connected
ClockPlugin plugin = mock(ClockPlugin.class);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// THEN dark amount should be initalized on the plugin.
verify(plugin).setDarkAmount(0.5f);
}
@@ -181,8 +177,8 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
when(plugin.getView()).thenReturn(pluginView);
mClockView.setVisibility(GONE);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
verify(mClockView).setVisibility(VISIBLE);
assertThat(plugin.getView().getParent()).isNull();
@@ -193,16 +189,16 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// GIVEN that the big clock container is visible
FrameLayout bigClockContainer = new FrameLayout(getContext());
bigClockContainer.setVisibility(VISIBLE);
- mKeyguardClockSwitch.setBigClockContainer(bigClockContainer);
+ mKeyguardClockSwitch.setBigClockContainer(bigClockContainer, StatusBarState.KEYGUARD);
// AND the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
TextClock pluginView = new TextClock(getContext());
when(plugin.getBigClockView()).thenReturn(pluginView);
// AND in the keyguard state
- mStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected and then disconnected
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
// THEN the big lock container is GONE and the big clock view doesn't have
// a parent.
assertThat(bigClockContainer.getVisibility()).isEqualTo(GONE);
@@ -212,8 +208,8 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
@Test
public void onPluginDisconnected_nullView() {
ClockPlugin plugin = mock(ClockPlugin.class);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(null);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
verify(mClockView, never()).setVisibility(GONE);
}
@@ -222,13 +218,12 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// GIVEN two plugins are connected
ClockPlugin plugin1 = mock(ClockPlugin.class);
when(plugin1.getView()).thenReturn(new TextClock(getContext()));
- ClockManager.ClockChangedListener listener = mKeyguardClockSwitch.getClockChangedListener();
- listener.onClockChanged(plugin1);
+ mKeyguardClockSwitch.setClockPlugin(plugin1, StatusBarState.KEYGUARD);
ClockPlugin plugin2 = mock(ClockPlugin.class);
when(plugin2.getView()).thenReturn(new TextClock(getContext()));
- listener.onClockChanged(plugin2);
+ mKeyguardClockSwitch.setClockPlugin(plugin2, StatusBarState.KEYGUARD);
// WHEN the second plugin is disconnected
- listener.onClockChanged(null);
+ mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
// THEN the default clock should be shown.
verify(mClockView).setVisibility(VISIBLE);
assertThat(plugin1.getView().getParent()).isNull();
@@ -240,10 +235,9 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// GIVEN a plugin is connected
ClockPlugin clockPlugin = mock(ClockPlugin.class);
when(clockPlugin.getView()).thenReturn(new TextClock(getContext()));
- ClockManager.ClockChangedListener listener = mKeyguardClockSwitch.getClockChangedListener();
- listener.onClockChanged(clockPlugin);
+ mKeyguardClockSwitch.setClockPlugin(clockPlugin, StatusBarState.KEYGUARD);
// WHEN the plugin is disconnected
- listener.onClockChanged(null);
+ mKeyguardClockSwitch.setClockPlugin(null, StatusBarState.KEYGUARD);
// THEN onDestroyView is called on the plugin
verify(clockPlugin).onDestroyView();
}
@@ -260,7 +254,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
ClockPlugin plugin = mock(ClockPlugin.class);
TextClock pluginView = new TextClock(getContext());
when(plugin.getView()).thenReturn(pluginView);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
mKeyguardClockSwitch.setTextColor(Color.WHITE);
@@ -284,7 +278,7 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
TextClock pluginView = new TextClock(getContext());
when(plugin.getView()).thenReturn(pluginView);
Style style = mock(Style.class);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
mKeyguardClockSwitch.setStyle(style);
@@ -295,9 +289,9 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void onStateChanged_GoneInShade() {
// GIVEN that the big clock container is visible
mBigClockContainer.setVisibility(View.VISIBLE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+ mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// WHEN transitioned to SHADE state
- mStateListener.onStateChanged(StatusBarState.SHADE);
+ mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.SHADE);
// THEN the container is gone.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.GONE);
}
@@ -306,13 +300,13 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void onStateChanged_VisibleInKeyguard() {
// GIVEN that the big clock container is gone
mBigClockContainer.setVisibility(View.GONE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+ mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// AND GIVEN that a plugin is active.
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// WHEN transitioned to KEYGUARD state
- mStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// THEN the container is visible.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -324,11 +318,11 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// AND GIVEN that a plugin is active.
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// AND in the keyguard state
- mStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the container is associated with the clock switch
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+ mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// THEN the container remains visible.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -340,11 +334,11 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
// AND GIVEN that a plugin is active.
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// AND in the keyguard state
- mStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the container is associated with the clock switch
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+ mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// THEN the container is made visible.
assertThat(mBigClockContainer.getVisibility()).isEqualTo(View.VISIBLE);
}
@@ -353,14 +347,14 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void setKeyguardHidingBigClock_gone() {
// GIVEN that the container for the big clock has visibility GONE
mBigClockContainer.setVisibility(GONE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+ mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// AND the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
// AND in the keyguard state
- mStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// WHEN the container set hiding clock as true
mKeyguardClockSwitch.setKeyguardHidingBigClock(true);
// THEN the container is gone.
@@ -371,14 +365,14 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
public void setKeyguardHidingBigClock_visible() {
// GIVEN that the container for the big clock has visibility GONE
mBigClockContainer.setVisibility(GONE);
- mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer);
+ mKeyguardClockSwitch.setBigClockContainer(mBigClockContainer, StatusBarState.KEYGUARD);
// AND the plugin returns a view for the big clock
ClockPlugin plugin = mock(ClockPlugin.class);
when(plugin.getBigClockView()).thenReturn(mBigClock);
// AND in the keyguard state
- mStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ mKeyguardClockSwitch.updateBigClockVisibility(StatusBarState.KEYGUARD);
// WHEN the plugin is connected
- mKeyguardClockSwitch.getClockChangedListener().onClockChanged(plugin);
+ mKeyguardClockSwitch.setClockPlugin(plugin, StatusBarState.KEYGUARD);
// WHEN the container set hiding clock as false
mKeyguardClockSwitch.setKeyguardHidingBigClock(false);
// THEN the container is made visible.
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 4a8ada09b3d2..a0e5f73b6a4c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -777,7 +777,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
int subscription = simInited
- ? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE;
+ ? 1/* mock subid=1 */ : SubscriptionManager.PLACEHOLDER_SUBSCRIPTION_ID_BASE;
if (data != null) intent.putExtras(data);
intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subscription);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
index 71f3d5bee225..ee151c441b68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -32,6 +32,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.view.View;
@@ -61,6 +62,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
@Mock
private ViewPropertyAnimator mViewPropertyAnimator;
private MagnificationModeSwitch mMagnificationModeSwitch;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -111,6 +113,15 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
}
@Test
+ public void onConfigurationChanged_setImageResource() {
+ mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+ mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
+
+ verify(mMockImageView, times(2)).setImageResource(
+ getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
+ }
+
+ @Test
public void performClick_fullscreenMode_removeViewAndChangeSettingsValue() {
ArgumentCaptor<View.OnClickListener> captor = ArgumentCaptor.forClass(
View.OnClickListener.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java
index 69482791ef23..9fa5b87af3b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/ModeSwitchesControllerTest.java
@@ -16,10 +16,10 @@
package com.android.systemui.accessibility;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import android.content.pm.ActivityInfo;
+import android.hardware.display.DisplayManager;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.view.Display;
@@ -39,8 +39,7 @@ import org.mockito.MockitoAnnotations;
/** Tests the ModeSwitchesController. */
public class ModeSwitchesControllerTest extends SysuiTestCase {
- @Mock
- private ModeSwitchesController.SwitchSupplier mSupplier;
+ private FakeSwitchSupplier mSupplier;
@Mock
private MagnificationModeSwitch mModeSwitch;
private ModeSwitchesController mModeSwitchesController;
@@ -49,7 +48,7 @@ public class ModeSwitchesControllerTest extends SysuiTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mSupplier.get(anyInt())).thenReturn(mModeSwitch);
+ mSupplier = new FakeSwitchSupplier(mContext.getSystemService(DisplayManager.class));
mModeSwitchesController = new ModeSwitchesController(mSupplier);
}
@@ -70,4 +69,25 @@ public class ModeSwitchesControllerTest extends SysuiTestCase {
verify(mModeSwitch).removeButton();
}
+
+ @Test
+ public void testControllerOnConfigurationChanged_notifyShowingButton() {
+ mModeSwitchesController.showButton(Display.DEFAULT_DISPLAY,
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+ mModeSwitchesController.onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
+
+ verify(mModeSwitch).onConfigurationChanged(ActivityInfo.CONFIG_DENSITY);
+ }
+
+ private class FakeSwitchSupplier extends DisplayIdIndexSupplier<MagnificationModeSwitch> {
+
+ FakeSwitchSupplier(DisplayManager displayManager) {
+ super(displayManager);
+ }
+
+ @Override
+ protected MagnificationModeSwitch createInstance(Display display) {
+ return mModeSwitch;
+ }
+ }
}
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 a898c3ce2773..2007fbb8fc6c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -16,13 +16,19 @@
package com.android.systemui.accessibility;
+import static android.view.Choreographer.FrameCallback;
+
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.Instrumentation;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
+import android.view.SurfaceControl;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -49,6 +55,8 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
MirrorWindowControl mMirrorWindowControl;
@Mock
WindowMagnifierCallback mWindowMagnifierCallback;
+ @Mock
+ SurfaceControl.Transaction mTransaction;
private WindowMagnificationController mWindowMagnificationController;
private Instrumentation mInstrumentation;
@@ -56,9 +64,19 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ doAnswer(invocation -> {
+ FrameCallback callback = invocation.getArgument(0);
+ callback.doFrame(0);
+ return null;
+ }).when(mSfVsyncFrameProvider).postFrameCallback(
+ any(FrameCallback.class));
+ when(mTransaction.remove(any())).thenReturn(mTransaction);
+ when(mTransaction.setGeometry(any(), any(), any(),
+ anyInt())).thenReturn(mTransaction);
+
mWindowMagnificationController = new WindowMagnificationController(getContext(),
mHandler, mSfVsyncFrameProvider,
- mMirrorWindowControl, mWindowMagnifierCallback);
+ mMirrorWindowControl, mTransaction, mWindowMagnifierCallback);
verify(mMirrorWindowControl).setWindowDelegate(
any(MirrorWindowControl.MirrorWindowDelegate.class));
}
@@ -71,7 +89,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
}
@Test
- public void createWindowMagnification_showControl() {
+ public void enableWindowMagnification_showControl() {
mInstrumentation.runOnMainSync(() -> {
mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
Float.NaN);
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 61a2c3f519cb..41360130ac65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
@@ -17,10 +17,12 @@
package com.android.systemui.accessibility;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
@@ -96,4 +98,13 @@ public class WindowMagnificationTest extends SysuiTestCase {
verify(connectionCallback).onWindowMagnifierBoundsChanged(Display.DEFAULT_DISPLAY,
testBounds);
}
+
+ @Test
+ public void onConfigurationChanged_updateModeSwitches() {
+ final Configuration config = new Configuration();
+ config.densityDpi = Configuration.DENSITY_DPI_ANY;
+ mWindowMagnification.onConfigurationChanged(config);
+
+ verify(mModeSwitchesController).onConfigurationChanged(anyInt());
+ }
}
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 15828b41cc7c..b7589534a770 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -321,7 +321,7 @@ public class BubbleControllerTest extends SysuiTestCase {
Bubble b = mBubbleData.getOverflowBubbleWithKey(mRow.getEntry().getKey());
assertThat(mBubbleData.getOverflowBubbles()).isEqualTo(ImmutableList.of(b));
verify(mNotificationEntryManager, never()).performRemoveNotification(
- eq(mRow.getEntry().getSbn()), anyInt());
+ eq(mRow.getEntry().getSbn()), any(), anyInt());
assertThat(mRow.getEntry().isBubble()).isFalse();
Bubble b2 = mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey());
@@ -352,7 +352,7 @@ public class BubbleControllerTest extends SysuiTestCase {
mBubbleController.removeBubble(
mRow.getEntry().getKey(), BubbleController.DISMISS_NOTIF_CANCEL);
verify(mNotificationEntryManager, times(1)).performRemoveNotification(
- eq(mRow.getEntry().getSbn()), anyInt());
+ eq(mRow.getEntry().getSbn()), any(), anyInt());
assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
assertFalse(mRow.getEntry().isBubble());
}
@@ -365,7 +365,7 @@ public class BubbleControllerTest extends SysuiTestCase {
mBubbleController.removeBubble(
mRow.getEntry().getKey(), BubbleController.DISMISS_USER_CHANGED);
verify(mNotificationEntryManager, never()).performRemoveNotification(
- eq(mRow.getEntry().getSbn()), anyInt());
+ eq(mRow.getEntry().getSbn()), any(), anyInt());
assertFalse(mBubbleController.hasBubbles());
assertFalse(mSysUiStateBubblesExpanded);
assertTrue(mRow.getEntry().isBubble());
@@ -873,7 +873,7 @@ public class BubbleControllerTest extends SysuiTestCase {
mRow2.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE);
// Overflow max of 1 is reached; mRow is oldest, so it gets removed
verify(mNotificationEntryManager, times(1)).performRemoveNotification(
- mRow.getEntry().getSbn(), REASON_CANCEL);
+ eq(mRow.getEntry().getSbn()), any(), eq(REASON_CANCEL));
assertEquals(mBubbleData.getBubbles().size(), 1);
assertEquals(mBubbleData.getOverflowBubbles().size(), 1);
}
@@ -985,11 +985,13 @@ public class BubbleControllerTest extends SysuiTestCase {
// THEN only the NON-bubble children are dismissed
List<ExpandableNotificationRow> childrenRows = groupSummary.getAttachedChildren();
verify(mNotificationEntryManager, times(1)).performRemoveNotification(
- childrenRows.get(0).getEntry().getSbn(), REASON_GROUP_SUMMARY_CANCELED);
+ eq(childrenRows.get(0).getEntry().getSbn()), any(),
+ eq(REASON_GROUP_SUMMARY_CANCELED));
verify(mNotificationEntryManager, times(1)).performRemoveNotification(
- childrenRows.get(1).getEntry().getSbn(), REASON_GROUP_SUMMARY_CANCELED);
+ eq(childrenRows.get(1).getEntry().getSbn()), any(),
+ eq(REASON_GROUP_SUMMARY_CANCELED));
verify(mNotificationEntryManager, never()).performRemoveNotification(
- eq(groupedBubble.getEntry().getSbn()), anyInt());
+ eq(groupedBubble.getEntry().getSbn()), any(), anyInt());
// THEN the bubble child is suppressed from the shade
assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
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 686a09444ee6..43bf19111049 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -26,6 +26,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -301,7 +302,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
assertTrue(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey()));
// We don't remove the notification since the bubble is still in overflow.
- verify(mNotifCallback, never()).removeNotification(eq(mRow.getEntry()), anyInt());
+ verify(mNotifCallback, never()).removeNotification(eq(mRow.getEntry()), any(), anyInt());
assertFalse(mBubbleController.hasBubbles());
}
@@ -325,7 +326,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
// Since the notif is dismissed and not in overflow, once the bubble is removed,
// removeNotification gets called to really remove the notif
- verify(mNotifCallback, times(1)).removeNotification(eq(mRow.getEntry()), anyInt());
+ verify(mNotifCallback, times(1)).removeNotification(eq(mRow.getEntry()),
+ any(), anyInt());
assertFalse(mBubbleController.hasBubbles());
}
@@ -831,10 +833,11 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
// THEN only the NON-bubble children are dismissed
List<ExpandableNotificationRow> childrenRows = groupSummary.getAttachedChildren();
verify(mNotifCallback, times(1)).removeNotification(
- childrenRows.get(0).getEntry(), REASON_GROUP_SUMMARY_CANCELED);
+ eq(childrenRows.get(0).getEntry()), any(), eq(REASON_GROUP_SUMMARY_CANCELED));
verify(mNotifCallback, times(1)).removeNotification(
- childrenRows.get(1).getEntry(), REASON_GROUP_SUMMARY_CANCELED);
- verify(mNotifCallback, never()).removeNotification(eq(groupedBubble.getEntry()), anyInt());
+ eq(childrenRows.get(1).getEntry()), any(), eq(REASON_GROUP_SUMMARY_CANCELED));
+ verify(mNotifCallback, never()).removeNotification(eq(groupedBubble.getEntry()),
+ any(), anyInt());
// THEN the bubble child still exists as a bubble and is suppressed from the shade
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
index 71554608f04b..7d8728e4acab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
@@ -94,11 +94,11 @@ public class SeekBarObserverTest : SysuiTestCase() {
@Test
fun seekBarProgress() {
- // WHEN seek bar progress is about half
+ // WHEN part of the track has been played
val data = SeekBarViewModel.Progress(true, true, 3000, 120000)
observer.onChanged(data)
- // THEN seek bar is visible
- assertThat(seekBarView.progress).isEqualTo(100)
+ // THEN seek bar shows the progress
+ assertThat(seekBarView.progress).isEqualTo(3000)
assertThat(seekBarView.max).isEqualTo(120000)
assertThat(elapsedTimeView.getText()).isEqualTo("00:03")
assertThat(totalTimeView.getText()).isEqualTo("02:00")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java
index 583d0692565f..73164b520b9d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java
@@ -44,6 +44,7 @@ public class OneHandedAnimationControllerTest extends OneHandedTestCase {
private static final int TEST_BOUNDS_HEIGHT = 1000;
OneHandedAnimationController mOneHandedAnimationController;
+ OneHandedTutorialHandler mTutorialHandler;
@Mock
private SurfaceControl mMockLeash;
@@ -52,6 +53,7 @@ public class OneHandedAnimationControllerTest extends OneHandedTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mTutorialHandler = new OneHandedTutorialHandler(mContext);
mOneHandedAnimationController = new OneHandedAnimationController(
new OneHandedSurfaceTransactionHelper(mContext));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java
index 3231b2852e7c..a989cd1f9c40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java
@@ -61,6 +61,7 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
DisplayAreaInfo mDisplayAreaInfo;
Display mDisplay;
OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
+ OneHandedTutorialHandler mTutorialHandler;
OneHandedAnimationController.OneHandedTransitionAnimator mFakeAnimator;
WindowContainerToken mToken;
SurfaceControl mLeash;
@@ -97,14 +98,15 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
mMockSurfaceTransactionHelper);
when(mMockAnimator.isRunning()).thenReturn(true);
when(mMockAnimator.setDuration(anyInt())).thenReturn(mFakeAnimator);
- when(mMockAnimator.setOneHandedAnimationCallback(any())).thenReturn(mFakeAnimator);
+ when(mMockAnimator.setOneHandedAnimationCallbacks(any())).thenReturn(mFakeAnimator);
when(mMockAnimator.setTransitionDirection(anyInt())).thenReturn(mFakeAnimator);
when(mMockLeash.getWidth()).thenReturn(DISPLAY_WIDTH);
when(mMockLeash.getHeight()).thenReturn(DISPLAY_HEIGHT);
mDisplayAreaOrganizer = new OneHandedDisplayAreaOrganizer(mContext,
mMockDisplayController,
- mMockAnimationController);
+ mMockAnimationController,
+ mTutorialHandler);
mUpdateHandler = mDisplayAreaOrganizer.getUpdateHandler();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
index 3b284b14c36f..694f51be4e30 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java
@@ -48,6 +48,7 @@ import org.mockito.MockitoAnnotations;
public class OneHandedGestureHandlerTest extends OneHandedTestCase {
Instrumentation mInstrumentation;
OneHandedTouchHandler mTouchHandler;
+ OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
OneHandedManagerImpl mOneHandedManagerImpl;
@Mock
@@ -62,13 +63,15 @@ public class OneHandedGestureHandlerTest extends OneHandedTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mInstrumentation = InstrumentationRegistry.getInstrumentation();
- mTouchHandler = Mockito.spy(new OneHandedTouchHandler());
+ mTouchHandler = new OneHandedTouchHandler();
+ mTutorialHandler = new OneHandedTutorialHandler(mContext);
mGestureHandler = Mockito.spy(new OneHandedGestureHandler(
mContext, mMockDisplayController, mMockNavigationModeController));
mOneHandedManagerImpl = new OneHandedManagerImpl(mInstrumentation.getContext(),
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
+ mTutorialHandler,
mGestureHandler,
mMockSysUiState);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java
index 55bec54eacb8..3418ebf75e0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedManagerImplTest.java
@@ -57,6 +57,8 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
@Mock
OneHandedTouchHandler mMockTouchHandler;
@Mock
+ OneHandedTutorialHandler mMockTutorialHandler;
+ @Mock
OneHandedGestureHandler mMockGestureHandler;
@Mock
SysUiState mMockSysUiState;
@@ -69,6 +71,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
mMockDisplayController,
mMockDisplayAreaOrganizer,
mMockTouchHandler,
+ mMockTutorialHandler,
mMockGestureHandler,
mMockSysUiState);
mTimeoutHandler = Mockito.spy(OneHandedTimeoutHandler.get());
@@ -84,7 +87,7 @@ public class OneHandedManagerImplTest extends OneHandedTestCase {
final OneHandedAnimationController animationController = new OneHandedAnimationController(
transactionHelper);
OneHandedDisplayAreaOrganizer displayAreaOrganizer = new OneHandedDisplayAreaOrganizer(
- mContext, mMockDisplayController, animationController);
+ mContext, mMockDisplayController, animationController, mMockTutorialHandler);
assertThat(displayAreaOrganizer.isInOneHanded()).isFalse();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
index 3a4ba6a213dc..fdb28d3d43b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java
@@ -46,6 +46,7 @@ import org.mockito.MockitoAnnotations;
public class OneHandedTouchHandlerTest extends OneHandedTestCase {
Instrumentation mInstrumentation;
OneHandedTouchHandler mTouchHandler;
+ OneHandedTutorialHandler mTutorialHandler;
OneHandedGestureHandler mGestureHandler;
OneHandedManagerImpl mOneHandedManagerImpl;
@Mock
@@ -68,13 +69,15 @@ public class OneHandedTouchHandlerTest extends OneHandedTestCase {
mMockDisplayController,
mMockDisplayAreaOrganizer,
mTouchHandler,
+ mTutorialHandler,
mGestureHandler,
mMockSysUiState);
}
@Test
public void testOneHandedManager_registerForDisplayAreaOrganizer() {
- verify(mMockDisplayAreaOrganizer, times(1)).registerTransitionCallback(mTouchHandler);
+ verify(mMockDisplayAreaOrganizer, times(1))
+ .registerTransitionCallback(mTouchHandler);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
new file mode 100644
index 000000000000..f4aa00eaf02f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.onehanded;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.Instrumentation;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.statusbar.phone.NavigationModeController;
+import com.android.wm.shell.common.DisplayController;
+
+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
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
+ Instrumentation mInstrumentation;
+ OneHandedTouchHandler mTouchHandler;
+ OneHandedTutorialHandler mTutorialHandler;
+ OneHandedGestureHandler mGestureHandler;
+ OneHandedManagerImpl mOneHandedManagerImpl;
+ @Mock
+ DisplayController mMockDisplayController;
+ @Mock
+ NavigationModeController mMockNavigationModeController;
+ @Mock
+ OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
+ @Mock
+ SysUiState mMockSysUiState;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mTouchHandler = new OneHandedTouchHandler();
+ mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext));
+ mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController,
+ mMockNavigationModeController);
+ mOneHandedManagerImpl = new OneHandedManagerImpl(mInstrumentation.getContext(),
+ mMockDisplayController,
+ mMockDisplayAreaOrganizer,
+ mTouchHandler,
+ mTutorialHandler,
+ mGestureHandler,
+ mMockSysUiState);
+ }
+
+ @Test
+ public void testOneHandedManager_registerForDisplayAreaOrganizer() {
+ verify(mMockDisplayAreaOrganizer, times(1))
+ .registerTransitionCallback(mTutorialHandler);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
index c9c111198f4c..f0066ba4f66a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
@@ -16,7 +16,7 @@
package com.android.systemui.pip;
-import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
+import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static org.junit.Assert.assertEquals;
@@ -116,9 +116,9 @@ public class PipAnimationControllerTest extends SysuiTestCase {
animator = mPipAnimationController
.getAnimator(mLeash, new Rect(), 0f, 1f)
- .setTransitionDirection(TRANSITION_DIRECTION_TO_FULLSCREEN);
+ .setTransitionDirection(TRANSITION_DIRECTION_LEAVE_PIP);
assertEquals("Transition to fullscreen mode",
- animator.getTransitionDirection(), TRANSITION_DIRECTION_TO_FULLSCREEN);
+ animator.getTransitionDirection(), TRANSITION_DIRECTION_LEAVE_PIP);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 4fd5d057c003..6f46923cda5e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -55,7 +55,6 @@ import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.notification.stack.NotificationListItem;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -293,15 +292,9 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
public void notifyGroupChildAdded(ExpandableView row) {}
@Override
- public void notifyGroupChildAdded(View v) {}
-
- @Override
public void notifyGroupChildRemoved(ExpandableView row, ViewGroup childrenContainer) {}
@Override
- public void notifyGroupChildRemoved(View v, ViewGroup childrenContainer) {}
-
- @Override
public void generateAddAnimation(ExpandableView child, boolean fromMoreCard) {}
@Override
@@ -327,11 +320,6 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
}
@Override
- public void removeListItem(NotificationListItem li) {
- removeContainerView(li.getView());
- }
-
- @Override
public void setNotificationActivityStarter(
NotificationActivityStarter notificationActivityStarter) {}
@@ -342,8 +330,9 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
}
@Override
- public void addListItem(NotificationListItem li) {
- addContainerView(li.getView());
+ public void addContainerViewAt(View v, int index) {
+ mLayout.addView(v, index);
+ mRows.add(index, v);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
index 619d2444b4dd..fb8c3d9af05c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
@@ -57,8 +57,8 @@ public class AssistantFeedbackControllerTest extends SysuiTestCase {
@Before
public void setUp() {
- switchSetting(ON);
mAssistantFeedbackController = new AssistantFeedbackController(mContext);
+ switchSetting(ON);
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
0, null, TEST_UID, 0, new Notification(),
UserHandle.CURRENT, null, 0);
@@ -72,7 +72,6 @@ public class AssistantFeedbackControllerTest extends SysuiTestCase {
@Test
public void testUserControls_settingEnabled() {
- switchSetting(ON);
assertTrue(mAssistantFeedbackController.isFeedbackEnabled());
}
@@ -113,7 +112,8 @@ public class AssistantFeedbackControllerTest extends SysuiTestCase {
}
private void switchSetting(int setting) {
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.NOTIFICATION_FEEDBACK_ENABLED, setting, UserHandle.USER_CURRENT);
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.NOTIFICATION_FEEDBACK_ENABLED, setting);
+ mAssistantFeedbackController.update(null);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 8a49326add25..d4718e7e55fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -57,11 +57,11 @@ import android.util.ArraySet;
import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -75,6 +75,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -202,8 +203,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
() -> mRemoteInputManager,
mLeakDetector,
mock(ForegroundServiceDismissalFeatureController.class),
- mock(HeadsUpManager.class),
- mock(StatusBarStateController.class)
+ mock(IStatusBarService.class)
);
mEntryManager.setUpWithPresenter(mPresenter);
mEntryManager.addNotificationEntryListener(mEntryListener);
@@ -294,7 +294,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
assertTrue(entriesContainKey(mEntryManager.getAllNotifs(), mSbn.getKey()));
// WHEN the uninflated entry is removed
- mEntryManager.performRemoveNotification(mSbn, UNDEFINED_DISMISS_REASON);
+ mEntryManager.performRemoveNotification(mSbn, mock(DismissedByUserStats.class),
+ UNDEFINED_DISMISS_REASON);
// THEN the entry is still removed from the allNotifications list
assertFalse(entriesContainKey(mEntryManager.getAllNotifs(), mSbn.getKey()));
@@ -470,7 +471,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Test
public void testPerformRemoveNotification_removedEntry() {
mEntryManager.removeNotification(mSbn.getKey(), null, 0);
- mEntryManager.performRemoveNotification(mSbn, REASON_CANCEL);
+ mEntryManager.performRemoveNotification(mSbn, mock(DismissedByUserStats.class),
+ REASON_CANCEL);
}
@Test
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/DismissRunnable.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/EntryUtil.kt
index 433114224289..62667bc5281f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/DismissRunnable.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/EntryUtil.kt
@@ -14,17 +14,19 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.row.dagger;
+package com.android.systemui.statusbar.notification.collection
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface DismissRunnable {
+/**
+ * Modifies a NotificationEntry
+ *
+ * The [modifier] function will be passed an instance of a NotificationEntryBuilder. Any
+ * modifications made to the builder will be applied to the [entry].
+ */
+inline fun modifyEntry(
+ entry: NotificationEntry,
+ crossinline modifier: NotificationEntryBuilder.() -> Unit
+) {
+ val builder = NotificationEntryBuilder(entry)
+ modifier(builder)
+ builder.apply(entry)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java
new file mode 100644
index 000000000000..2971c05487c6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java
@@ -0,0 +1,82 @@
+/*
+ * 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.collection;
+
+import androidx.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Builder to construct instances of {@link GroupEntry} for tests.
+ */
+public class GroupEntryBuilder {
+ private String mKey = "test_group_key";
+ private long mCreationTime = 0;
+ @Nullable private GroupEntry mParent = GroupEntry.ROOT_ENTRY;
+ private NotificationEntry mSummary = null;
+ private List<NotificationEntry> mChildren = new ArrayList<>();
+
+ /** Builds a new instance of GroupEntry */
+ public GroupEntry build() {
+ GroupEntry ge = new GroupEntry(mKey, mCreationTime);
+ ge.setParent(mParent);
+
+ ge.setSummary(mSummary);
+ mSummary.setParent(ge);
+
+ for (NotificationEntry child : mChildren) {
+ ge.addChild(child);
+ child.setParent(ge);
+ }
+ return ge;
+ }
+
+ public GroupEntryBuilder setKey(String key) {
+ mKey = key;
+ return this;
+ }
+
+ public GroupEntryBuilder setCreationTime(long creationTime) {
+ mCreationTime = creationTime;
+ return this;
+ }
+
+ public GroupEntryBuilder setParent(@Nullable GroupEntry entry) {
+ mParent = entry;
+ return this;
+ }
+
+ public GroupEntryBuilder setSummary(
+ NotificationEntry summary) {
+ mSummary = summary;
+ return this;
+ }
+
+ public GroupEntryBuilder setChildren(List<NotificationEntry> children) {
+ mChildren.clear();
+ mChildren.addAll(children);
+ return this;
+ }
+
+ /** Adds a child to the existing list of children */
+ public GroupEntryBuilder addChild(NotificationEntry entry) {
+ mChildren.add(entry);
+ return this;
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryHelper.java
deleted file mode 100644
index 038dd17a9814..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryHelper.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.collection;
-
-import java.util.List;
-
-/**
- * Helper class to provide methods for test classes that need {@link GroupEntry}'s for their tests.
- */
-public class GroupEntryHelper {
- /**
- * Create a group entry for testing purposes.
- * @param groupKey group key for the group and all its entries
- * @param summary summary notification for group
- * @param children group's children notifications
- */
- public static final GroupEntry createGroup(
- String groupKey,
- NotificationEntry summary,
- List<NotificationEntry> children) {
- GroupEntry groupEntry = new GroupEntry(groupKey);
- groupEntry.setSummary(summary);
- for (NotificationEntry child : children) {
- groupEntry.addChild(child);
- }
- return groupEntry;
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
index 2b12c22cae39..386c866cdd03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
@@ -191,9 +191,10 @@ public class HighPriorityProviderTest extends SysuiTestCase {
@Test
public void testIsHighPriority_summaryUpdated() {
// GIVEN a GroupEntry with a lowPrioritySummary and no children
- final GroupEntry parentEntry = new GroupEntry("test_group_key");
final NotificationEntry lowPrioritySummary = createNotifEntry(false);
- setSummary(parentEntry, lowPrioritySummary);
+ final GroupEntry parentEntry = new GroupEntryBuilder()
+ .setSummary(lowPrioritySummary)
+ .build();
assertFalse(mHighPriorityProvider.isHighPriority(parentEntry));
// WHEN the summary changes to high priority
@@ -214,10 +215,11 @@ public class HighPriorityProviderTest extends SysuiTestCase {
// GroupEntry = parentEntry, summary = lowPrioritySummary
// NotificationEntry = lowPriorityChild
// NotificationEntry = highPriorityChild
- final GroupEntry parentEntry = new GroupEntry("test_group_key");
- setSummary(parentEntry, createNotifEntry(false));
- addChild(parentEntry, createNotifEntry(false));
- addChild(parentEntry, createNotifEntry(true));
+ final GroupEntry parentEntry = new GroupEntryBuilder()
+ .setSummary(createNotifEntry(false))
+ .addChild(createNotifEntry(false))
+ .addChild(createNotifEntry(true))
+ .build();
// THEN the GroupEntry parentEntry is high priority since it has a high priority child
assertTrue(mHighPriorityProvider.isHighPriority(parentEntry));
@@ -228,10 +230,11 @@ public class HighPriorityProviderTest extends SysuiTestCase {
// GIVEN:
// GroupEntry = parentEntry, summary = lowPrioritySummary
// NotificationEntry = lowPriorityChild
- final GroupEntry parentEntry = new GroupEntry("test_group_key");
final NotificationEntry lowPriorityChild = createNotifEntry(false);
- setSummary(parentEntry, createNotifEntry(false));
- addChild(parentEntry, lowPriorityChild);
+ final GroupEntry parentEntry = new GroupEntryBuilder()
+ .setSummary(createNotifEntry(false))
+ .addChild(lowPriorityChild)
+ .build();
// WHEN the child entry ranking changes to high priority
lowPriorityChild.setRanking(
@@ -250,14 +253,4 @@ public class HighPriorityProviderTest extends SysuiTestCase {
.setImportance(highPriority ? IMPORTANCE_HIGH : IMPORTANCE_MIN)
.build();
}
-
- private void setSummary(GroupEntry parent, NotificationEntry summary) {
- parent.setSummary(summary);
- summary.setParent(parent);
- }
-
- private void addChild(GroupEntry parent, NotificationEntry child) {
- parent.addChild(child);
- child.setParent(parent);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
index 4a7c6c643118..1523653dec3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
@@ -23,6 +23,7 @@ import android.app.NotificationManager;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.os.UserHandle;
+import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
@@ -33,6 +34,8 @@ import com.android.systemui.util.time.FakeSystemClock;
import java.util.ArrayList;
+import kotlin.Unit;
+
/**
* Combined builder for constructing a NotificationEntry and its associated StatusBarNotification
* and Ranking. Is largely a proxy for the SBN and Ranking builders, but does a little extra magic
@@ -43,8 +46,8 @@ import java.util.ArrayList;
* Only for use in tests.
*/
public class NotificationEntryBuilder {
- private final SbnBuilder mSbnBuilder = new SbnBuilder();
- private final RankingBuilder mRankingBuilder = new RankingBuilder();
+ private final SbnBuilder mSbnBuilder;
+ private final RankingBuilder mRankingBuilder;
private final FakeSystemClock mClock = new FakeSystemClock();
private StatusBarNotification mSbn = null;
@@ -55,12 +58,49 @@ public class NotificationEntryBuilder {
/* If set, use this creation time instead of mClock.uptimeMillis */
private long mCreationTime = -1;
+ public NotificationEntryBuilder() {
+ mSbnBuilder = new SbnBuilder();
+ mRankingBuilder = new RankingBuilder();
+ }
+
+ public NotificationEntryBuilder(NotificationEntry source) {
+ mSbnBuilder = new SbnBuilder(source.getSbn());
+ mRankingBuilder = new RankingBuilder(source.getRanking());
+
+ mParent = source.getParent();
+ mSection = source.getSection();
+ mCreationTime = source.getCreationTime();
+ }
+
+ /** Build a new instance of NotificationEntry */
public NotificationEntry build() {
- StatusBarNotification sbn = mSbn != null ? mSbn : mSbnBuilder.build();
- mRankingBuilder.setKey(sbn.getKey());
- long creationTime = mCreationTime != -1 ? mCreationTime : mClock.uptimeMillis();
- final NotificationEntry entry = new NotificationEntry(
- sbn, mRankingBuilder.build(), mClock.uptimeMillis());
+ return buildOrApply(null);
+ }
+
+ /** Modifies [target] to match the contents of this builder */
+ public void apply(NotificationEntry target) {
+ buildOrApply(target);
+ }
+
+ /** Convenience method for Kotlin callbacks that are passed a builder and need to return Unit */
+ public Unit done() {
+ return Unit.INSTANCE;
+ }
+
+ private NotificationEntry buildOrApply(NotificationEntry target) {
+ final StatusBarNotification sbn = mSbn != null ? mSbn : mSbnBuilder.build();
+ final Ranking ranking = mRankingBuilder.setKey(sbn.getKey()).build();
+ final long creationTime = mCreationTime != -1 ? mCreationTime : mClock.uptimeMillis();
+
+ final NotificationEntry entry;
+ if (target == null) {
+ entry = new NotificationEntry(sbn, ranking, creationTime);
+ } else {
+ entry = target;
+ entry.setSbn(sbn);
+ entry.setRanking(ranking);
+ // Note: we can't modify the creation time as it's immutable
+ }
/* ListEntry properties */
entry.setParent(mParent);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
index f54252effdd3..917c049fd578 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
@@ -21,9 +21,10 @@ import static android.app.Notification.VISIBILITY_SECRET;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
+import static com.android.systemui.statusbar.notification.collection.EntryUtilKt.modifyEntry;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -41,6 +42,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -71,13 +73,12 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
@Mock private NotifPipeline mNotifPipeline;
private NotificationEntry mEntry;
- private KeyguardCoordinator mKeyguardCoordinator;
private NotifFilter mKeyguardFilter;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mKeyguardCoordinator = new KeyguardCoordinator(
+ KeyguardCoordinator keyguardCoordinator = new KeyguardCoordinator(
mContext, mMainHandler, mKeyguardStateController, mLockscreenUserManager,
mBroadcastDispatcher, mStatusBarStateController,
mKeyguardUpdateMonitor, mHighPriorityProvider);
@@ -87,7 +88,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
.build();
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
- mKeyguardCoordinator.attach(mNotifPipeline);
+ keyguardCoordinator.attach(mNotifPipeline);
verify(mNotifPipeline, times(1)).addFinalizeFilter(filterCaptor.capture());
mKeyguardFilter = filterCaptor.getValue();
}
@@ -186,12 +187,18 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
public void summaryExceedsThresholdToShow() {
// GIVEN the notification doesn't exceed the threshold to show on the lockscreen
// but it's part of a group (has a parent)
- final GroupEntry parent = new GroupEntry("test_group_key");
final NotificationEntry entryWithParent = new NotificationEntryBuilder()
- .setParent(parent)
.setUser(new UserHandle(NOTIF_USER_ID))
.build();
+ final GroupEntry parent = new GroupEntryBuilder()
+ .setKey("test_group_key")
+ .setSummary(new NotificationEntryBuilder()
+ .setImportance(IMPORTANCE_HIGH)
+ .build())
+ .addChild(entryWithParent)
+ .build();
+
setupUnfilteredState(entryWithParent);
entryWithParent.setRanking(new RankingBuilder()
.setKey(entryWithParent.getKey())
@@ -200,18 +207,15 @@ public class KeyguardCoordinatorTest extends SysuiTestCase {
// WHEN its parent does exceed threshold tot show on the lockscreen
when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(true);
- parent.setSummary(new NotificationEntryBuilder()
- .setImportance(IMPORTANCE_HIGH)
- .build());
// THEN don't filter out the entry
assertFalse(mKeyguardFilter.shouldFilterOut(entryWithParent, 0));
// WHEN its parent doesn't exceed threshold to show on lockscreen
when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(false);
- parent.setSummary(new NotificationEntryBuilder()
+ modifyEntry(parent.getSummary(), builder -> builder
.setImportance(IMPORTANCE_MIN)
- .build());
+ .done());
// THEN filter out the entry
assertTrue(mKeyguardFilter.shouldFilterOut(entryWithParent, 0));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
index faf9da3aca8b..bec5174aceba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
+import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -25,6 +27,8 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static java.util.Objects.requireNonNull;
+
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -34,15 +38,16 @@ import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
-import com.android.systemui.statusbar.notification.collection.GroupEntryHelper;
-import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
-import com.android.systemui.statusbar.notification.collection.NotifViewBarn;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.render.NotifViewBarn;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
import org.junit.Before;
@@ -52,19 +57,17 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class PreparationCoordinatorTest extends SysuiTestCase {
- private static final String TEST_MESSAGE = "TEST_MESSAGE";
- private static final String TEST_GROUP_KEY = "TEST_GROUP_KEY";
- private static final int TEST_CHILD_BIND_CUTOFF = 9;
-
- private PreparationCoordinator mCoordinator;
private NotifCollectionListener mCollectionListener;
private OnBeforeFinalizeFilterListener mBeforeFilterListener;
private NotifFilter mUninflatedFilter;
@@ -75,30 +78,31 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
@Captor private ArgumentCaptor<NotifCollectionListener> mCollectionListenerCaptor;
@Captor private ArgumentCaptor<OnBeforeFinalizeFilterListener> mBeforeFilterListenerCaptor;
- @Captor private ArgumentCaptor<NotifInflaterImpl.InflationCallback> mCallbackCaptor;
+ @Captor private ArgumentCaptor<NotifInflater.InflationCallback> mCallbackCaptor;
@Mock private NotifPipeline mNotifPipeline;
@Mock private IStatusBarService mService;
- @Mock private NotifInflaterImpl mNotifInflater;
+ @Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater();
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mEntry = new NotificationEntryBuilder().build();
+ mEntry = new NotificationEntryBuilder().setParent(ROOT_ENTRY).build();
mInflationError = new Exception(TEST_MESSAGE);
mErrorManager = new NotifInflationErrorManager();
- mCoordinator = new PreparationCoordinator(
+ PreparationCoordinator coordinator = new PreparationCoordinator(
mock(PreparationCoordinatorLogger.class),
mNotifInflater,
mErrorManager,
mock(NotifViewBarn.class),
mService,
- TEST_CHILD_BIND_CUTOFF);
+ TEST_CHILD_BIND_CUTOFF,
+ TEST_MAX_GROUP_DELAY);
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
- mCoordinator.attach(mNotifPipeline);
+ coordinator.attach(mNotifPipeline);
verify(mNotifPipeline, times(2)).addFinalizeFilter(filterCaptor.capture());
List<NotifFilter> filters = filterCaptor.getAllValues();
mInflationErrorFilter = filters.get(0);
@@ -127,7 +131,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
eq(mEntry.getSbn().getUid()),
eq(mEntry.getSbn().getInitialPid()),
eq(mInflationError.getMessage()),
- eq(mEntry.getSbn().getUserId()));
+ eq(mEntry.getSbn().getUser().getIdentifier()));
}
@Test
@@ -199,7 +203,11 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
.build();
children.add(child);
}
- GroupEntry groupEntry = GroupEntryHelper.createGroup(TEST_GROUP_KEY, summary, children);
+ GroupEntry groupEntry = new GroupEntryBuilder()
+ .setKey(TEST_GROUP_KEY)
+ .setSummary(summary)
+ .setChildren(children)
+ .build();
mCollectionListener.onEntryInit(summary);
for (NotificationEntry entry : children) {
@@ -222,4 +230,139 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
}
}
}
+
+ @Test
+ public void testPartiallyInflatedGroupsAreFilteredOut() {
+ // GIVEN a newly-posted group with a summary and two children
+ final GroupEntry group = new GroupEntryBuilder()
+ .setCreationTime(400)
+ .setSummary(new NotificationEntryBuilder().setId(1).build())
+ .addChild(new NotificationEntryBuilder().setId(2).build())
+ .addChild(new NotificationEntryBuilder().setId(3).build())
+ .build();
+ fireAddEvents(List.of(group));
+ final NotificationEntry child0 = group.getChildren().get(0);
+ mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group));
+
+ // WHEN one of this children finishes inflating
+ mNotifInflater.getInflateCallback(child0).onInflationFinished(child0);
+
+ // THEN the inflated child is still filtered out
+ assertTrue(mUninflatedFilter.shouldFilterOut(child0, 401));
+ }
+
+ @Test
+ public void testPartiallyInflatedGroupsAreFilteredOutSummaryVersion() {
+ // GIVEN a newly-posted group with a summary and two children
+ final GroupEntry group = new GroupEntryBuilder()
+ .setCreationTime(400)
+ .setSummary(new NotificationEntryBuilder().setId(1).build())
+ .addChild(new NotificationEntryBuilder().setId(2).build())
+ .addChild(new NotificationEntryBuilder().setId(3).build())
+ .build();
+ fireAddEvents(List.of(group));
+ final NotificationEntry summary = group.getSummary();
+ final NotificationEntry child0 = group.getChildren().get(0);
+ final NotificationEntry child1 = group.getChildren().get(1);
+ mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group));
+
+ // WHEN all of the children (but not the summary) finish inflating
+ mNotifInflater.getInflateCallback(child0).onInflationFinished(child0);
+ mNotifInflater.getInflateCallback(child1).onInflationFinished(child1);
+
+ // THEN the entire group is still filtered out
+ assertTrue(mUninflatedFilter.shouldFilterOut(summary, 401));
+ assertTrue(mUninflatedFilter.shouldFilterOut(child0, 401));
+ assertTrue(mUninflatedFilter.shouldFilterOut(child1, 401));
+ }
+
+ @Test
+ public void testCompletedInflatedGroupsAreReleased() {
+ // GIVEN a newly-posted group with a summary and two children
+ final GroupEntry group = new GroupEntryBuilder()
+ .setCreationTime(400)
+ .setSummary(new NotificationEntryBuilder().setId(1).build())
+ .addChild(new NotificationEntryBuilder().setId(2).build())
+ .addChild(new NotificationEntryBuilder().setId(3).build())
+ .build();
+ fireAddEvents(List.of(group));
+ final NotificationEntry summary = group.getSummary();
+ final NotificationEntry child0 = group.getChildren().get(0);
+ final NotificationEntry child1 = group.getChildren().get(1);
+ mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group));
+
+ // WHEN all of the children (and the summary) finish inflating
+ mNotifInflater.getInflateCallback(child0).onInflationFinished(child0);
+ mNotifInflater.getInflateCallback(child1).onInflationFinished(child1);
+ mNotifInflater.getInflateCallback(summary).onInflationFinished(summary);
+
+ // THEN the entire group is still filtered out
+ assertFalse(mUninflatedFilter.shouldFilterOut(summary, 401));
+ assertFalse(mUninflatedFilter.shouldFilterOut(child0, 401));
+ assertFalse(mUninflatedFilter.shouldFilterOut(child1, 401));
+ }
+
+ @Test
+ public void testPartiallyInflatedGroupsAreReleasedAfterTimeout() {
+ // GIVEN a newly-posted group with a summary and two children
+ final GroupEntry group = new GroupEntryBuilder()
+ .setCreationTime(400)
+ .setSummary(new NotificationEntryBuilder().setId(1).build())
+ .addChild(new NotificationEntryBuilder().setId(2).build())
+ .addChild(new NotificationEntryBuilder().setId(3).build())
+ .build();
+ fireAddEvents(List.of(group));
+ final NotificationEntry child0 = group.getChildren().get(0);
+ mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group));
+
+ // WHEN one of this children finishes inflating and enough time passes
+ mNotifInflater.getInflateCallback(child0).onInflationFinished(child0);
+
+ // THEN the inflated child is not filtered out even though the rest of the group hasn't
+ // finished inflating yet
+ assertTrue(mUninflatedFilter.shouldFilterOut(child0, TEST_MAX_GROUP_DELAY + 1));
+ }
+
+ private static class FakeNotifInflater implements NotifInflater {
+ private Map<NotificationEntry, InflationCallback> mInflateCallbacks = new HashMap<>();
+
+ @Override
+ public void inflateViews(NotificationEntry entry, InflationCallback callback) {
+ mInflateCallbacks.put(entry, callback);
+ }
+
+ @Override
+ public void rebindViews(NotificationEntry entry, InflationCallback callback) {
+ }
+
+ @Override
+ public void abortInflation(NotificationEntry entry) {
+ }
+
+ public InflationCallback getInflateCallback(NotificationEntry entry) {
+ return requireNonNull(mInflateCallbacks.get(entry));
+ }
+ }
+
+ private void fireAddEvents(List<? extends ListEntry> entries) {
+ for (ListEntry entry : entries) {
+ if (entry instanceof GroupEntry) {
+ GroupEntry ge = (GroupEntry) entry;
+ fireAddEvents(ge.getSummary());
+ fireAddEvents(ge.getChildren());
+ } else {
+ fireAddEvents((NotificationEntry) entry);
+ }
+ }
+ }
+
+ private void fireAddEvents(NotificationEntry entry) {
+ mCollectionListener.onEntryInit(entry);
+ mCollectionListener.onEntryAdded(entry);
+ }
+
+ private static final String TEST_MESSAGE = "TEST_MESSAGE";
+ private static final String TEST_GROUP_KEY = "TEST_GROUP_KEY";
+ private static final int TEST_CHILD_BIND_CUTOFF = 9;
+ private static final int TEST_MAX_GROUP_DELAY = 100;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index 601df2cb4fc7..a90af87064b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -40,6 +40,7 @@ import android.testing.TestableLooper;
import androidx.asynclayoutinflater.view.AsyncLayoutInflater;
import androidx.test.filters.SmallTest;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.NotificationMessagingUtil;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -185,8 +186,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
() -> mRemoteInputManager,
mLeakDetector,
mock(ForegroundServiceDismissalFeatureController.class),
- mock(HeadsUpManager.class),
- mock(StatusBarStateController.class)
+ mock(IStatusBarService.class)
);
NotifRemoteViewCache cache = new NotifRemoteViewCacheImpl(mEntryManager);
@@ -252,7 +252,6 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
mLockscreenUserManager,
pipeline,
mRowContentBindStage,
- mNotificationInterruptionStateProvider,
RowInflaterTask::new,
mExpandableNotificationRowComponentBuilder,
new IconManager(
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 6d411333b220..ddac2ecbd6eb 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
@@ -49,13 +49,13 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.media.KeyguardMediaController;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.EmptyShadeView;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -93,7 +93,6 @@ import com.android.systemui.statusbar.phone.NotificationIconAreaController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.leak.LeakDetector;
@@ -193,8 +192,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
() -> mRemoteInputManager,
mock(LeakDetector.class),
mock(ForegroundServiceDismissalFeatureController.class),
- mock(HeadsUpManager.class),
- mock(StatusBarStateController.class)
+ mock(IStatusBarService.class)
);
mEntryManager.setUpWithPresenter(mock(NotificationPresenter.class));
when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index a927c8011b8f..64907eef2dd0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -136,6 +136,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
anyFloat());
assertThat(mBiometricUnlockController.getMode())
.isEqualTo(BiometricUnlockController.MODE_SHOW_BOUNCER);
+ assertThat(mBiometricUnlockController.getBiometricType())
+ .isEqualTo(BiometricSourceType.FINGERPRINT);
}
@Test
@@ -268,6 +270,8 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
assertThat(mBiometricUnlockController.getMode())
.isEqualTo(BiometricUnlockController.MODE_DISMISS_BOUNCER);
+ assertThat(mBiometricUnlockController.getBiometricType())
+ .isEqualTo(BiometricSourceType.FACE);
}
@Test
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 b0b66b87d421..c7434f6fd95f 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
@@ -51,6 +51,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardClockSwitchController;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -183,6 +184,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private BiometricUnlockController mBiometricUnlockController;
@Mock
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ @Mock
+ private KeyguardClockSwitchController mKeyguardClockSwitchController;
private FlingAnimationUtils.Builder mFlingAnimationUtilsBuilder;
private NotificationPanelViewController mNotificationPanelViewController;
@@ -240,7 +243,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mMetricsLogger, mActivityManager, mZenModeController, mConfigurationController,
mFlingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
mConversationNotificationManager, mMediaHiearchyManager,
- mBiometricUnlockController, mStatusBarKeyguardViewManager);
+ mBiometricUnlockController, mStatusBarKeyguardViewManager,
+ () -> mKeyguardClockSwitchController);
mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager,
mNotificationShelf, mNotificationAreaController, mScrimController);
mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index acdb2c59dc0c..33067343ba40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -73,6 +73,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.OnDismissCallback;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -131,6 +132,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
@Mock
private Intent mContentIntentInner;
@Mock
+ private OnDismissCallback mOnDismissCallback;
+ @Mock
private NotificationActivityStarter mNotificationActivityStarter;
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -207,7 +210,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mFeatureFlags,
mock(MetricsLogger.class),
- mock(StatusBarNotificationActivityStarterLogger.class))
+ mock(StatusBarNotificationActivityStarterLogger.class),
+ mOnDismissCallback)
.setStatusBar(mStatusBar)
.setNotificationPresenter(mock(NotificationPresenter.class))
.setNotificationPanelViewController(mock(NotificationPanelViewController.class))
@@ -266,8 +270,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
verify(mClickNotifier).onNotificationClick(
eq(sbn.getKey()), any(NotificationVisibility.class));
- // Notification is removed due to FLAG_AUTO_CANCEL
- verify(mEntryManager).performRemoveNotification(eq(sbn), eq(REASON_CLICK));
+ // Notification calls dismiss callback to remove notification due to FLAG_AUTO_CANCEL
+ verify(mOnDismissCallback).onDismiss(mNotificationRow.getEntry(), REASON_CLICK);
}
@Test
@@ -296,7 +300,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
verifyZeroInteractions(mContentIntent);
// Notification should not be cancelled.
- verify(mEntryManager, never()).performRemoveNotification(eq(sbn), anyInt());
+ verify(mOnDismissCallback, never()).onDismiss(eq(mNotificationRow.getEntry()), anyInt());
}
@Test
@@ -326,7 +330,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
verifyZeroInteractions(mContentIntent);
// Notification should not be cancelled.
- verify(mEntryManager, never()).performRemoveNotification(eq(sbn), anyInt());
+ verify(mEntryManager, never()).performRemoveNotification(eq(sbn), any(), anyInt());
}
@Test
@@ -358,6 +362,6 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
verifyNoMoreInteractions(mContentIntent);
// Notification should not be cancelled.
- verify(mEntryManager, never()).performRemoveNotification(eq(sbn), anyInt());
+ verify(mEntryManager, never()).performRemoveNotification(eq(sbn), any(), anyInt());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
index 8ba11dae2b5c..c5a197eef2d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/sensors/ProximityCheckTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.util.sensors;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -80,6 +81,8 @@ public class ProximityCheckTest extends SysuiTestCase {
mFakeExecutor.runAllReady();
assertFalse(mFakeProximitySensor.isRegistered());
+ assertEquals(1, mTestableCallback.mNumCalls);
+ assertNull(mTestableCallback.mLastResult);
}
@Test
@@ -110,9 +113,12 @@ public class ProximityCheckTest extends SysuiTestCase {
private static class TestableCallback implements Consumer<Boolean> {
Boolean mLastResult;
+ int mNumCalls = 0;
+
@Override
public void accept(Boolean result) {
mLastResult = result;
+ mNumCalls++;
}
}
}
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index a8cd63d90676..915c2f6087b8 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -32,6 +32,7 @@ java_defaults {
"android.hardware.tetheroffload.config-V1.0-java",
"android.hardware.tetheroffload.control-V1.0-java",
"net-utils-framework-common",
+ "net-utils-device-common",
],
libs: [
"framework-statsd.stubs.module_lib",
diff --git a/packages/Tethering/AndroidManifest.xml b/packages/Tethering/AndroidManifest.xml
index 2b2fe4534c3e..e6444f3ead5c 100644
--- a/packages/Tethering/AndroidManifest.xml
+++ b/packages/Tethering/AndroidManifest.xml
@@ -24,7 +24,7 @@
<!-- Permissions must be defined here, and not in the base manifest, as the tethering
running in the system server process does not need any permission, and having
privileged permissions added would cause crashes on startup unless they are also
- added to the privileged permissions whitelist for that package. -->
+ added to the privileged permissions allowlist for that package. -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
diff --git a/packages/Tethering/proguard.flags b/packages/Tethering/proguard.flags
index 051fbd19fc6c..86b903353cf5 100644
--- a/packages/Tethering/proguard.flags
+++ b/packages/Tethering/proguard.flags
@@ -1,5 +1,5 @@
# Keep class's integer static field for MessageUtils to parsing their name.
--keep class com.android.networkstack.tethering.Tethering$TetherMasterSM {
+-keep class com.android.networkstack.tethering.Tethering$TetherMainSM {
static final int CMD_*;
static final int EVENT_*;
}
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 8af1797a9dd7..673cbf09d259 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -197,15 +197,19 @@ public class IpServer extends StateMachine {
public static final int CMD_TETHER_UNREQUESTED = BASE_IPSERVER + 2;
// notification that this interface is down
public static final int CMD_INTERFACE_DOWN = BASE_IPSERVER + 3;
- // notification from the master SM that it had trouble enabling IP Forwarding
+ // notification from the {@link Tethering.TetherMainSM} that it had trouble enabling IP
+ // Forwarding
public static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IPSERVER + 4;
- // notification from the master SM that it had trouble disabling IP Forwarding
+ // notification from the {@link Tethering.TetherMainSM} SM that it had trouble disabling IP
+ // Forwarding
public static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IPSERVER + 5;
- // notification from the master SM that it had trouble starting tethering
+ // notification from the {@link Tethering.TetherMainSM} SM that it had trouble starting
+ // tethering
public static final int CMD_START_TETHERING_ERROR = BASE_IPSERVER + 6;
- // notification from the master SM that it had trouble stopping tethering
+ // notification from the {@link Tethering.TetherMainSM} that it had trouble stopping tethering
public static final int CMD_STOP_TETHERING_ERROR = BASE_IPSERVER + 7;
- // notification from the master SM that it had trouble setting the DNS forwarders
+ // notification from the {@link Tethering.TetherMainSM} that it had trouble setting the DNS
+ // forwarders
public static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IPSERVER + 8;
// the upstream connection has changed
public static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IPSERVER + 9;
@@ -423,9 +427,13 @@ public class IpServer extends StateMachine {
getHandler().post(() -> {
// We are on the handler thread: mDhcpServerStartIndex can be read safely.
if (mStartIndex != mDhcpServerStartIndex) {
- // This start request is obsolete. When the |server| binder token goes out of
- // scope, the garbage collector will finalize it, which causes the network stack
- // process garbage collector to collect the server itself.
+ // This start request is obsolete. Explicitly stop the DHCP server to shut
+ // down its thread. When the |server| binder token goes out of scope, the
+ // garbage collector will finalize it, which causes the network stack process
+ // garbage collector to collect the server itself.
+ try {
+ server.stop(null);
+ } catch (RemoteException e) { }
return;
}
@@ -1316,7 +1324,7 @@ public class IpServer extends StateMachine {
/**
* This state is terminal for the per interface state machine. At this
- * point, the master state machine should have removed this interface
+ * point, the tethering main state machine should have removed this interface
* specific state machine from its list of possible recipients of
* tethering requests. The state machine itself will hang around until
* the garbage collector finds it.
diff --git a/packages/Tethering/src/android/net/util/TetheringMessageBase.java b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
index 1b763ce920da..29c0a817b6f4 100644
--- a/packages/Tethering/src/android/net/util/TetheringMessageBase.java
+++ b/packages/Tethering/src/android/net/util/TetheringMessageBase.java
@@ -19,7 +19,7 @@ package android.net.util;
* This class defines Message.what base addresses for various state machine.
*/
public class TetheringMessageBase {
- public static final int BASE_MASTER = 0;
+ public static final int BASE_MAIN_SM = 0;
public static final int BASE_IPSERVER = 100;
}
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
index 9dace709d734..bb7322f2a0d2 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/EntitlementManager.java
@@ -296,16 +296,16 @@ public class EntitlementManager {
* Reference TetheringManager.TETHERING_{@code *} for each tether type.
*
* @param config an object that encapsulates the various tethering configuration elements.
- * Note: this method is only called from TetherMaster on the handler thread.
+ * Note: this method is only called from @{link Tethering.TetherMainSM} on the handler thread.
* If there are new callers from different threads, the logic should move to
- * masterHandler to avoid race conditions.
+ * @{link Tethering.TetherMainSM} handler to avoid race conditions.
*/
public void reevaluateSimCardProvisioning(final TetheringConfiguration config) {
if (DBG) mLog.i("reevaluateSimCardProvisioning");
if (!mHandler.getLooper().isCurrentThread()) {
// Except for test, this log should not appear in normal flow.
- mLog.log("reevaluateSimCardProvisioning() don't run in TetherMaster thread");
+ mLog.log("reevaluateSimCardProvisioning() don't run in TetherMainSM thread");
}
mEntitlementCacheValue.clear();
mCurrentEntitlementResults.clear();
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 7508a653599d..cfc657587332 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -50,7 +50,7 @@ import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED;
import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED;
-import static android.net.util.TetheringMessageBase.BASE_MASTER;
+import static android.net.util.TetheringMessageBase.BASE_MAIN_SM;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
@@ -159,7 +159,7 @@ public class Tethering {
private static final boolean VDBG = false;
private static final Class[] sMessageClasses = {
- Tethering.class, TetherMasterSM.class, IpServer.class
+ Tethering.class, TetherMainSM.class, IpServer.class
};
private static final SparseArray<String> sMagicDecoderRing =
MessageUtils.findMessageNames(sMessageClasses);
@@ -216,7 +216,7 @@ public class Tethering {
private final ArrayMap<String, TetherState> mTetherStates;
private final BroadcastReceiver mStateReceiver;
private final Looper mLooper;
- private final StateMachine mTetherMasterSM;
+ private final StateMachine mTetherMainSM;
private final OffloadController mOffloadController;
private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
// TODO: Figure out how to merge this and other downstream-tracking objects
@@ -273,10 +273,10 @@ public class Tethering {
mTetherStates = new ArrayMap<>();
mConnectedClientsTracker = new ConnectedClientsTracker();
- mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps);
- mTetherMasterSM.start();
+ mTetherMainSM = new TetherMainSM("TetherMain", mLooper, deps);
+ mTetherMainSM.start();
- mHandler = mTetherMasterSM.getHandler();
+ mHandler = mTetherMainSM.getHandler();
mOffloadController = mDeps.getOffloadController(mHandler, mLog,
new OffloadController.Dependencies() {
@@ -285,8 +285,8 @@ public class Tethering {
return mConfig;
}
});
- mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
- TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
+ mUpstreamNetworkMonitor = mDeps.getUpstreamNetworkMonitor(mContext, mTetherMainSM, mLog,
+ TetherMainSM.EVENT_UPSTREAM_CALLBACK);
mForwardedDownstreams = new LinkedHashSet<>();
IntentFilter filter = new IntentFilter();
@@ -294,8 +294,8 @@ public class Tethering {
// EntitlementManager will send EVENT_UPSTREAM_PERMISSION_CHANGED when cellular upstream
// permission is changed according to entitlement check result.
mEntitlementMgr = mDeps.getEntitlementManager(mContext, mHandler, mLog,
- () -> mTetherMasterSM.sendMessage(
- TetherMasterSM.EVENT_UPSTREAM_PERMISSION_CHANGED));
+ () -> mTetherMainSM.sendMessage(
+ TetherMainSM.EVENT_UPSTREAM_PERMISSION_CHANGED));
mEntitlementMgr.setOnUiEntitlementFailedListener((int downstream) -> {
mLog.log("OBSERVED UiEnitlementFailed");
stopTethering(downstream);
@@ -945,7 +945,7 @@ public class Tethering {
}
if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString());
- mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
+ mTetherMainSM.sendMessage(TetherMainSM.CMD_UPSTREAM_CHANGED);
}
private void handleUsbAction(Intent intent) {
@@ -1170,7 +1170,7 @@ public class Tethering {
private void disableWifiP2pIpServingLockedIfNeeded(String ifname) {
if (TextUtils.isEmpty(ifname)) return;
- disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* dummy */ 0);
+ disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* fake */ 0);
}
private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
@@ -1381,23 +1381,23 @@ public class Tethering {
return false;
}
- class TetherMasterSM extends StateMachine {
+ class TetherMainSM extends StateMachine {
// an interface SM has requested Tethering/Local Hotspot
- static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MASTER + 1;
+ static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MAIN_SM + 1;
// an interface SM has unrequested Tethering/Local Hotspot
- static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MASTER + 2;
+ static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MAIN_SM + 2;
// upstream connection change - do the right thing
- static final int CMD_UPSTREAM_CHANGED = BASE_MASTER + 3;
+ static final int CMD_UPSTREAM_CHANGED = BASE_MAIN_SM + 3;
// we don't have a valid upstream conn, check again after a delay
- static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4;
- // Events from NetworkCallbacks that we process on the master state
+ static final int CMD_RETRY_UPSTREAM = BASE_MAIN_SM + 4;
+ // Events from NetworkCallbacks that we process on the main state
// machine thread on behalf of the UpstreamNetworkMonitor.
- static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5;
+ static final int EVENT_UPSTREAM_CALLBACK = BASE_MAIN_SM + 5;
// we treated the error and want now to clear it
- static final int CMD_CLEAR_ERROR = BASE_MASTER + 6;
- static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MASTER + 7;
+ static final int CMD_CLEAR_ERROR = BASE_MAIN_SM + 6;
+ static final int EVENT_IFACE_UPDATE_LINKPROPERTIES = BASE_MAIN_SM + 7;
// Events from EntitlementManager to choose upstream again.
- static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MASTER + 8;
+ static final int EVENT_UPSTREAM_PERMISSION_CHANGED = BASE_MAIN_SM + 8;
private final State mInitialState;
private final State mTetherModeAliveState;
@@ -1425,7 +1425,7 @@ public class Tethering {
private static final int UPSTREAM_SETTLE_TIME_MS = 10000;
- TetherMasterSM(String name, Looper looper, TetheringDependencies deps) {
+ TetherMainSM(String name, Looper looper, TetheringDependencies deps) {
super(name, looper);
mInitialState = new InitialState();
@@ -1479,7 +1479,7 @@ public class Tethering {
}
}
- protected boolean turnOnMasterTetherSettings() {
+ protected boolean turnOnMainTetherSettings() {
final TetheringConfiguration cfg = mConfig;
try {
mNetd.ipfwdEnableForwarding(TAG);
@@ -1506,11 +1506,11 @@ public class Tethering {
return false;
}
}
- mLog.log("SET master tether settings: ON");
+ mLog.log("SET main tether settings: ON");
return true;
}
- protected boolean turnOffMasterTetherSettings() {
+ protected boolean turnOffMainTetherSettings() {
try {
mNetd.tetherStop();
} catch (RemoteException | ServiceSpecificException e) {
@@ -1526,7 +1526,7 @@ public class Tethering {
return false;
}
transitionTo(mInitialState);
- mLog.log("SET master tether settings: OFF");
+ mLog.log("SET main tether settings: OFF");
return true;
}
@@ -1730,7 +1730,7 @@ public class Tethering {
// TODO: Re-evaluate possible upstreams. Currently upstream
// reevaluation is triggered via received CONNECTIVITY_ACTION
// broadcasts that result in being passed a
- // TetherMasterSM.CMD_UPSTREAM_CHANGED.
+ // TetherMainSM.CMD_UPSTREAM_CHANGED.
handleNewUpstreamNetworkState(null);
break;
default:
@@ -1745,9 +1745,9 @@ public class Tethering {
@Override
public void enter() {
- // If turning on master tether settings fails, we have already
+ // If turning on main tether settings fails, we have already
// transitioned to an error state; exit early.
- if (!turnOnMasterTetherSettings()) {
+ if (!turnOnMainTetherSettings()) {
return;
}
@@ -1819,7 +1819,7 @@ public class Tethering {
if (mNotifyList.isEmpty()) {
// This transitions us out of TetherModeAliveState,
// either to InitialState or an error state.
- turnOffMasterTetherSettings();
+ turnOffMainTetherSettings();
break;
}
@@ -2329,7 +2329,7 @@ public class Tethering {
};
}
- // TODO: Move into TetherMasterSM.
+ // TODO: Move into TetherMainSM.
private void notifyInterfaceStateChange(IpServer who, int state, int error) {
final String iface = who.interfaceName();
synchronized (mPublicSync) {
@@ -2344,27 +2344,27 @@ public class Tethering {
mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
- // If TetherMasterSM is in ErrorState, TetherMasterSM stays there.
- // Thus we give a chance for TetherMasterSM to recover to InitialState
+ // If TetherMainSM is in ErrorState, TetherMainSM stays there.
+ // Thus we give a chance for TetherMainSM to recover to InitialState
// by sending CMD_CLEAR_ERROR
if (error == TETHER_ERROR_INTERNAL_ERROR) {
- mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who);
+ mTetherMainSM.sendMessage(TetherMainSM.CMD_CLEAR_ERROR, who);
}
int which;
switch (state) {
case IpServer.STATE_UNAVAILABLE:
case IpServer.STATE_AVAILABLE:
- which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
+ which = TetherMainSM.EVENT_IFACE_SERVING_STATE_INACTIVE;
break;
case IpServer.STATE_TETHERED:
case IpServer.STATE_LOCAL_ONLY:
- which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
+ which = TetherMainSM.EVENT_IFACE_SERVING_STATE_ACTIVE;
break;
default:
Log.wtf(TAG, "Unknown interface state: " + state);
return;
}
- mTetherMasterSM.sendMessage(which, state, 0, who);
+ mTetherMainSM.sendMessage(which, state, 0, who);
sendTetherStateChangedBroadcast();
}
@@ -2384,8 +2384,8 @@ public class Tethering {
mLog.log(String.format(
"OBSERVED LinkProperties update iface=%s state=%s lp=%s",
iface, IpServer.getStateString(state), newLp));
- final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
- mTetherMasterSM.sendMessage(which, state, 0, newLp);
+ final int which = TetherMainSM.EVENT_IFACE_UPDATE_LINKPROPERTIES;
+ mTetherMainSM.sendMessage(which, state, 0, newLp);
}
private void maybeTrackNewInterfaceLocked(final String iface) {
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
index 320427c393ac..b17065cb7804 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/UpstreamNetworkMonitor.java
@@ -63,7 +63,7 @@ import java.util.Set;
* Calling #registerMobileNetworkRequest() to bring up mobile DUN/HIPRI network.
*
* The methods and data members of this class are only to be accessed and
- * modified from the tethering master state machine thread. Any other
+ * modified from the tethering main state machine thread. Any other
* access semantics would necessitate the addition of locking.
*
* TODO: Move upstream selection logic here.
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index 30a9d2252ea6..3b72b5b47191 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -50,6 +50,7 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
@@ -73,6 +74,7 @@ import android.net.MacAddress;
import android.net.RouteInfo;
import android.net.TetherOffloadRuleParcel;
import android.net.TetherStatsParcel;
+import android.net.dhcp.DhcpServerCallbacks;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.IDhcpEventCallbacks;
import android.net.dhcp.IDhcpServer;
@@ -163,17 +165,6 @@ public class IpServerTest {
private void initStateMachine(int interfaceType, boolean usingLegacyDhcp,
boolean usingBpfOffload) throws Exception {
- doAnswer(inv -> {
- final IDhcpServerCallbacks cb = inv.getArgument(2);
- new Thread(() -> {
- try {
- cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
- } catch (RemoteException e) {
- fail(e.getMessage());
- }
- }).run();
- return null;
- }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
@@ -225,6 +216,20 @@ public class IpServerTest {
when(mAddressCoordinator.requestDownstreamAddress(any())).thenReturn(mTestAddress);
}
+ private void setUpDhcpServer() throws Exception {
+ doAnswer(inv -> {
+ final IDhcpServerCallbacks cb = inv.getArgument(2);
+ new Thread(() -> {
+ try {
+ cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
+ } catch (RemoteException e) {
+ fail(e.getMessage());
+ }
+ }).run();
+ return null;
+ }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
+ }
+
@Before public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
@@ -258,6 +263,8 @@ public class IpServerTest {
return mTetherConfig;
}
}));
+
+ setUpDhcpServer();
}
@Test
@@ -965,6 +972,31 @@ public class IpServerTest {
reset(mRaDaemon);
}
+ @Test
+ public void testStopObsoleteDhcpServer() throws Exception {
+ final ArgumentCaptor<DhcpServerCallbacks> cbCaptor =
+ ArgumentCaptor.forClass(DhcpServerCallbacks.class);
+ doNothing().when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(),
+ cbCaptor.capture());
+ initStateMachine(TETHERING_WIFI);
+ dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
+ verify(mDhcpServer, never()).startWithCallbacks(any(), any());
+
+ // No stop dhcp server because dhcp server is not created yet.
+ dispatchCommand(IpServer.CMD_TETHER_UNREQUESTED);
+ verify(mDhcpServer, never()).stop(any());
+
+ // Stop obsolete dhcp server.
+ try {
+ final DhcpServerCallbacks cb = cbCaptor.getValue();
+ cb.onDhcpServerCreated(STATUS_SUCCESS, mDhcpServer);
+ mLooper.dispatchAll();
+ } catch (RemoteException e) {
+ fail(e.getMessage());
+ }
+ verify(mDhcpServer).stop(any());
+ }
+
private void assertDhcpServingParams(final DhcpServingParamsParcel params,
final IpPrefix prefix) {
// Last address byte is random
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 1b710d00d0c7..46fe5cf093fd 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -337,11 +337,11 @@ public class TetheringTest {
}
public class MockTetheringDependencies extends TetheringDependencies {
- StateMachine mUpstreamNetworkMonitorMasterSM;
+ StateMachine mUpstreamNetworkMonitorSM;
ArrayList<IpServer> mIpv6CoordinatorNotifyList;
public void reset() {
- mUpstreamNetworkMonitorMasterSM = null;
+ mUpstreamNetworkMonitorSM = null;
mIpv6CoordinatorNotifyList = null;
}
@@ -368,7 +368,7 @@ public class TetheringTest {
@Override
public UpstreamNetworkMonitor getUpstreamNetworkMonitor(Context ctx,
StateMachine target, SharedLog log, int what) {
- mUpstreamNetworkMonitorMasterSM = target;
+ mUpstreamNetworkMonitorSM = target;
return mUpstreamNetworkMonitor;
}
@@ -911,8 +911,8 @@ public class TetheringTest {
initTetheringUpstream(upstreamState);
// Upstream LinkProperties changed: UpstreamNetworkMonitor sends EVENT_ON_LINKPROPERTIES.
- mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage(
- Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
+ mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
+ Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
0,
upstreamState);
@@ -1126,7 +1126,7 @@ public class TetheringTest {
verify(mNetd, times(1)).ipfwdEnableForwarding(TETHERING_NAME);
// This never gets called because of the exception thrown above.
verify(mNetd, times(0)).tetherStartWithConfiguration(any());
- // When the master state machine transitions to an error state it tells
+ // When the main state machine transitions to an error state it tells
// downstream interfaces, which causes us to tell Wi-Fi about the error
// so it can take down AP mode.
verify(mNetd, times(1)).tetherApplyDnsInterfaces();
@@ -1753,8 +1753,8 @@ public class TetheringTest {
@Test
public void testUpstreamNetworkChanged() {
- final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM)
- mTetheringDependencies.mUpstreamNetworkMonitorMasterSM;
+ final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
+ mTetheringDependencies.mUpstreamNetworkMonitorSM;
final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
initTetheringUpstream(upstreamState);
stateMachine.chooseUpstreamType(true);
@@ -1765,8 +1765,8 @@ public class TetheringTest {
@Test
public void testUpstreamCapabilitiesChanged() {
- final Tethering.TetherMasterSM stateMachine = (Tethering.TetherMasterSM)
- mTetheringDependencies.mUpstreamNetworkMonitorMasterSM;
+ final Tethering.TetherMainSM stateMachine = (Tethering.TetherMainSM)
+ mTetheringDependencies.mUpstreamNetworkMonitorSM;
final UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
initTetheringUpstream(upstreamState);
stateMachine.chooseUpstreamType(true);
@@ -1891,8 +1891,8 @@ public class TetheringTest {
any(), any());
reset(mNetd, mUsbManager);
upstreamNetwork = buildV4WifiUpstreamState(ipv4Address, 30, wifiNetwork);
- mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage(
- Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
+ mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
+ Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
0,
upstreamNetwork);
@@ -1929,8 +1929,8 @@ public class TetheringTest {
final UpstreamNetworkState upstreamNetwork = buildV4WifiUpstreamState(
upstreamAddress, 16, wifiNetwork);
- mTetheringDependencies.mUpstreamNetworkMonitorMasterSM.sendMessage(
- Tethering.TetherMasterSM.EVENT_UPSTREAM_CALLBACK,
+ mTetheringDependencies.mUpstreamNetworkMonitorSM.sendMessage(
+ Tethering.TetherMainSM.EVENT_UPSTREAM_CALLBACK,
UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES,
0,
upstreamNetwork);
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index 44c4bf4836a0..b6f2a47dd5e2 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -16,8 +16,10 @@
package com.android.server.accessibility.magnification;
+import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -61,6 +63,8 @@ public class FullScreenMagnificationController {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "FullScreenMagnificationController";
+ private static final Runnable STUB_RUNNABLE = () -> {
+ };
public static final float MIN_SCALE = 1.0f;
public static final float MAX_SCALE = 8.0f;
@@ -292,7 +296,7 @@ public class FullScreenMagnificationController {
// Adjust the current spec's offsets if necessary.
if (updateCurrentSpecWithOffsetsLocked(
mCurrentMagnificationSpec.offsetX, mCurrentMagnificationSpec.offsetY)) {
- sendSpecToAnimation(mCurrentMagnificationSpec, false);
+ sendSpecToAnimation(mCurrentMagnificationSpec, null);
}
onMagnificationChangedLocked();
}
@@ -300,17 +304,18 @@ public class FullScreenMagnificationController {
}
}
- void sendSpecToAnimation(MagnificationSpec spec, boolean animate) {
+ void sendSpecToAnimation(MagnificationSpec spec, Runnable endCallback) {
if (DEBUG) {
Slog.i(LOG_TAG,
- "sendSpecToAnimation(spec = " + spec + ", animate = " + animate + ")");
+ "sendSpecToAnimation(spec = " + spec + ", endCallback = " + endCallback
+ + ")");
}
if (Thread.currentThread().getId() == mMainThreadId) {
- mSpecAnimationBridge.updateSentSpecMainThread(spec, animate);
+ mSpecAnimationBridge.updateSentSpecMainThread(spec, endCallback);
} else {
final Message m = PooledLambda.obtainMessage(
SpecAnimationBridge::updateSentSpecMainThread,
- mSpecAnimationBridge, spec, animate);
+ mSpecAnimationBridge, spec, endCallback);
mControllerCtx.getHandler().sendMessage(m);
}
}
@@ -410,6 +415,11 @@ public class FullScreenMagnificationController {
@GuardedBy("mLock")
boolean reset(boolean animate) {
+ return reset(transformToStubRunnable(animate));
+ }
+
+ @GuardedBy("mLock")
+ boolean reset(Runnable endCallback) {
if (!mRegistered) {
return false;
}
@@ -420,7 +430,7 @@ public class FullScreenMagnificationController {
onMagnificationChangedLocked();
}
mIdOfLastServiceToMagnify = INVALID_ID;
- sendSpecToAnimation(spec, animate);
+ sendSpecToAnimation(spec, endCallback);
return changed;
}
@@ -448,24 +458,24 @@ public class FullScreenMagnificationController {
final float centerX = normPivotX + offsetX;
final float centerY = normPivotY + offsetY;
mIdOfLastServiceToMagnify = id;
- return setScaleAndCenter(scale, centerX, centerY, animate, id);
+ return setScaleAndCenter(scale, centerX, centerY, transformToStubRunnable(animate), id);
}
@GuardedBy("mLock")
boolean setScaleAndCenter(float scale, float centerX, float centerY,
- boolean animate, int id) {
+ Runnable endCallback, int id) {
if (!mRegistered) {
return false;
}
if (DEBUG) {
Slog.i(LOG_TAG,
"setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX
- + ", centerY = " + centerY + ", animate = " + animate
+ + ", centerY = " + centerY + ", endCallback = " + endCallback
+ ", id = " + id
+ ")");
}
final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY);
- sendSpecToAnimation(mCurrentMagnificationSpec, animate);
+ sendSpecToAnimation(mCurrentMagnificationSpec, endCallback);
if (isMagnifying() && (id != INVALID_ID)) {
mIdOfLastServiceToMagnify = id;
}
@@ -531,7 +541,7 @@ public class FullScreenMagnificationController {
if (id != INVALID_ID) {
mIdOfLastServiceToMagnify = id;
}
- sendSpecToAnimation(mCurrentMagnificationSpec, false);
+ sendSpecToAnimation(mCurrentMagnificationSpec, null);
}
boolean updateCurrentSpecWithOffsetsLocked(float nonNormOffsetX, float nonNormOffsetY) {
@@ -865,12 +875,26 @@ public class FullScreenMagnificationController {
* the spec did not change
*/
public boolean reset(int displayId, boolean animate) {
+ return reset(displayId, animate ? STUB_RUNNABLE : null);
+ }
+
+ /**
+ * Resets the magnification scale and center, optionally animating the
+ * transition.
+ *
+ * @param displayId The logical display id.
+ * @param endCallback Called when the animation is ended or the spec did not change.
+ * {@code null} to transition immediately
+ * @return {@code true} if the magnification spec changed, {@code false} if
+ * the spec did not change
+ */
+ public boolean reset(int displayId, Runnable endCallback) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
if (display == null) {
return false;
}
- return display.reset(animate);
+ return display.reset(endCallback);
}
}
@@ -921,7 +945,8 @@ public class FullScreenMagnificationController {
if (display == null) {
return false;
}
- return display.setScaleAndCenter(Float.NaN, centerX, centerY, animate, id);
+ return display.setScaleAndCenter(Float.NaN, centerX, centerY,
+ animate ? STUB_RUNNABLE : null, id);
}
}
@@ -944,12 +969,35 @@ public class FullScreenMagnificationController {
*/
public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
boolean animate, int id) {
+ return setScaleAndCenter(displayId, scale, centerX, centerY,
+ transformToStubRunnable(animate), id);
+ }
+
+ /**
+ * Sets the scale and center of the magnified region, optionally
+ * animating the transition. If animation is disabled, the transition
+ * is immediate.
+ *
+ * @param displayId The logical display id.
+ * @param scale the target scale, or {@link Float#NaN} to leave unchanged
+ * @param centerX the screen-relative X coordinate around which to
+ * center and scale, or {@link Float#NaN} to leave unchanged
+ * @param centerY the screen-relative Y coordinate around which to
+ * center and scale, or {@link Float#NaN} to leave unchanged
+ * @param endCallback called when the transition is finished successfully or the spec did not
+ * change. {@code null} to transition immediately.
+ * @param id the ID of the service requesting the change
+ * @return {@code true} if the magnification spec changed, {@code false} if
+ * the spec did not change
+ */
+ public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
+ Runnable endCallback, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
if (display == null) {
return false;
}
- return display.setScaleAndCenter(scale, centerX, centerY, animate, id);
+ return display.setScaleAndCenter(scale, centerX, centerY, endCallback, id);
}
}
@@ -1160,7 +1208,8 @@ public class FullScreenMagnificationController {
* Class responsible for animating spec on the main thread and sending spec
* updates to the window manager.
*/
- private static class SpecAnimationBridge implements ValueAnimator.AnimatorUpdateListener {
+ private static class SpecAnimationBridge implements ValueAnimator.AnimatorUpdateListener,
+ Animator.AnimatorListener {
private final ControllerContext mControllerCtx;
/**
@@ -1180,6 +1229,8 @@ public class FullScreenMagnificationController {
*/
private final ValueAnimator mValueAnimator;
+ // Called when the callee wants animating and the sent spec matches the target spec.
+ private Runnable mEndCallback;
private final Object mLock;
private final int mDisplayId;
@@ -1197,6 +1248,7 @@ public class FullScreenMagnificationController {
mValueAnimator.setInterpolator(new DecelerateInterpolator(2.5f));
mValueAnimator.setFloatValues(0.0f, 1.0f);
mValueAnimator.addUpdateListener(this);
+ mValueAnimator.addListener(this);
}
/**
@@ -1216,24 +1268,36 @@ public class FullScreenMagnificationController {
}
}
- public void updateSentSpecMainThread(MagnificationSpec spec, boolean animate) {
+ void updateSentSpecMainThread(MagnificationSpec spec, Runnable endCallback) {
if (mValueAnimator.isRunning()) {
+ // Avoid AnimationEnd Callback.
+ mEndCallback = null;
mValueAnimator.cancel();
}
+ mEndCallback = endCallback;
// If the current and sent specs don't match, update the sent spec.
synchronized (mLock) {
final boolean changed = !mSentMagnificationSpec.equals(spec);
if (changed) {
- if (animate) {
+ if (mEndCallback != null) {
animateMagnificationSpecLocked(spec);
} else {
setMagnificationSpecLocked(spec);
}
+ } else {
+ sendEndCallbackMainThread();
}
}
}
+ private void sendEndCallbackMainThread() {
+ if (mEndCallback != null) {
+ mEndCallback.run();
+ mEndCallback = null;
+ }
+ }
+
@GuardedBy("mLock")
private void setMagnificationSpecLocked(MagnificationSpec spec) {
if (mEnabled) {
@@ -1270,6 +1334,26 @@ public class FullScreenMagnificationController {
}
}
}
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ sendEndCallbackMainThread();
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+
+ }
}
private static class ScreenStateObserver extends BroadcastReceiver {
@@ -1395,4 +1479,9 @@ public class FullScreenMagnificationController {
return mAnimationDuration;
}
}
+
+ @Nullable
+ private static Runnable transformToStubRunnable(boolean animate) {
+ return animate ? STUB_RUNNABLE : null;
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
index a08c2dd4292d..ed2b26f24478 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
@@ -384,7 +384,7 @@ public class WindowMagnificationManager implements
synchronized (mLock) {
WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
if (magnifier == null) {
- return;
+ magnifier = createWindowMagnifier(displayId);
}
if (DBG) {
Slog.i(TAG,
@@ -401,6 +401,15 @@ public class WindowMagnificationManager implements
}
@Override
+ public void onSourceBoundsChanged(int displayId, Rect sourceBounds) {
+ WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
+ if (magnifier == null) {
+ magnifier = createWindowMagnifier(displayId);
+ }
+ magnifier.onSourceBoundsChanged(sourceBounds);
+ }
+
+ @Override
public void binderDied() {
synchronized (mLock) {
Slog.w(TAG, "binderDied DeathRecipient :" + mExpiredDeathRecipient);
@@ -427,6 +436,8 @@ public class WindowMagnificationManager implements
private final WindowMagnificationManager mWindowMagnificationManager;
//Records the bounds of window magnifier.
private final Rect mBounds = new Rect();
+ //The magnified bounds on the screen.
+ private final Rect mSourceBounds = new Rect();
WindowMagnifier(int displayId, WindowMagnificationManager windowMagnificationManager) {
mDisplayId = displayId;
mWindowMagnificationManager = windowMagnificationManager;
@@ -502,6 +513,10 @@ public class WindowMagnificationManager implements
void reset() {
mEnabled = false;
}
+
+ public void onSourceBoundsChanged(Rect sourceBounds) {
+ mSourceBounds.set(sourceBounds);
+ }
}
private boolean enableWindowMagnification(int displayId, float scale, float centerX,
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index 103151dcdda5..7ee607c3eab4 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -219,7 +219,7 @@ public class AppPredictionPerUserService extends
if (connected) {
synchronized (mLock) {
if (mZombie) {
- // Sanity check - shouldn't happen
+ // Validation check - shouldn't happen
if (mRemoteService == null) {
Slog.w(TAG, "Cannot resurrect sessions because remote service is null");
return;
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
index b229e9f30180..3562205834b4 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetService.java
@@ -16,11 +16,13 @@
package com.android.server.appwidget;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import com.android.server.AppWidgetBackupBridge;
-import com.android.server.FgThread;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
/**
* SystemService that publishes an IAppWidgetService.
@@ -49,12 +51,12 @@ public class AppWidgetService extends SystemService {
}
@Override
- public void onStopUser(int userHandle) {
- mImpl.onUserStopped(userHandle);
+ public void onUserStopping(@NonNull TargetUser user) {
+ mImpl.onUserStopped(user.getUserIdentifier());
}
@Override
- public void onSwitchUser(int userHandle) {
- mImpl.reloadWidgetsMaskedStateForGroup(userHandle);
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+ mImpl.reloadWidgetsMaskedStateForGroup(to.getUserIdentifier());
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 089861bee479..663fd6259fd4 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -84,6 +84,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.SyncResultReceiver;
import com.android.server.FgThread;
import com.android.server.LocalServices;
+import com.android.server.SystemService.TargetUser;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
@@ -363,7 +364,7 @@ public final class AutofillManagerService
}
@Override // from SystemService
- public void onSwitchUser(int userHandle) {
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
if (sDebug) Slog.d(TAG, "Hiding UI when user switched");
mUi.hideAll(null);
}
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 5a9320f61b38..b0755ac836e0 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -161,8 +161,9 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
@Override
public void onFailure(int requestId, CharSequence message) {
+ String errorMessage = message == null ? "" : String.valueOf(message);
fillRequest.completeExceptionally(
- new RuntimeException(String.valueOf(message)));
+ new RuntimeException(errorMessage));
}
});
return fillRequest;
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 7ab4369b338a..1970b5774bbb 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -1710,7 +1710,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if ((state & ViewState.STATE_AUTOFILLED_ONCE) != 0) {
final String datasetId = viewState.getDatasetId();
if (datasetId == null) {
- // Sanity check - should never happen.
+ // Validation check - should never happen.
Slog.w(TAG, "logContextCommitted(): no dataset id on " + viewState);
continue;
}
@@ -1844,7 +1844,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final ArrayMap<String, String> algorithms = userData.getFieldClassificationAlgorithms();
final ArrayMap<String, Bundle> args = userData.getFieldClassificationArgs();
- // Sanity check
+ // Validation check
if (userValues == null || categoryIds == null || userValues.length != categoryIds.length) {
final int valuesLength = userValues == null ? -1 : userValues.length;
final int idsLength = categoryIds == null ? -1 : categoryIds.length;
@@ -2668,12 +2668,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final String currentUrl = mUrlBar == null ? null
: mUrlBar.getText().toString().trim();
if (currentUrl == null) {
- // Sanity check - shouldn't happen.
+ // Validation check - shouldn't happen.
wtf(null, "URL bar value changed, but current value is null");
return;
}
if (value == null || ! value.isText()) {
- // Sanity check - shouldn't happen.
+ // Validation check - shouldn't happen.
wtf(null, "URL bar value changed to null or non-text: %s", value);
return;
}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index c839ce94bd64..12e6e10d9047 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -19,6 +19,7 @@ package com.android.server.backup;
import static java.util.Collections.emptySet;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
@@ -60,6 +61,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.backup.utils.RandomAccessFileUtils;
import java.io.File;
@@ -1605,13 +1607,13 @@ public class BackupManagerService extends IBackupManager.Stub {
}
@Override
- public void onUnlockUser(int userId) {
- sInstance.onUnlockUser(userId);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ sInstance.onUnlockUser(user.getUserIdentifier());
}
@Override
- public void onStopUser(int userId) {
- sInstance.onStopUser(userId);
+ public void onUserStopping(@NonNull TargetUser user) {
+ sInstance.onStopUser(user.getUserIdentifier());
}
@VisibleForTesting
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 2de26b7c4bd2..3ab81cbb313f 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -2307,7 +2307,7 @@ public class UserBackupManagerService {
public void enqueueFullBackup(String packageName, long lastBackedUp) {
FullBackupEntry newEntry = new FullBackupEntry(packageName, lastBackedUp);
synchronized (mQueueLock) {
- // First, sanity check that we aren't adding a duplicate. Slow but
+ // First, check that we aren't adding a duplicate. Slow but
// straightforward; we'll have at most on the order of a few hundred
// items in this list.
dequeueFullBackupLocked(packageName);
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index a69bd6b62264..0a117746ea3f 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -24,8 +24,6 @@ import static com.android.server.backup.UserBackupManagerService.BACKUP_FILE_HEA
import static com.android.server.backup.UserBackupManagerService.BACKUP_FILE_VERSION;
import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
-import android.app.backup.BackupManager;
-import android.app.backup.BackupManager.OperationType;
import android.app.backup.IFullBackupRestoreObserver;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -143,7 +141,7 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor
private OutputStream emitAesBackupHeader(StringBuilder headerbuf,
OutputStream ofstream) throws Exception {
- // User key will be used to encrypt the master key.
+ // User key will be used to encrypt the encryption key.
byte[] newUserSalt = mUserBackupManagerService
.randomBytes(PasswordUtils.PBKDF2_SALT_SIZE);
SecretKey userKey = PasswordUtils
@@ -151,16 +149,16 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor
newUserSalt,
PasswordUtils.PBKDF2_HASH_ROUNDS);
- // the master key is random for each backup
- byte[] masterPw = new byte[256 / 8];
- mUserBackupManagerService.getRng().nextBytes(masterPw);
+ // the encryption key is random for each backup
+ byte[] encryptionKey = new byte[256 / 8];
+ mUserBackupManagerService.getRng().nextBytes(encryptionKey);
byte[] checksumSalt = mUserBackupManagerService
.randomBytes(PasswordUtils.PBKDF2_SALT_SIZE);
- // primary encryption of the datastream with the random key
+ // primary encryption of the datastream with the encryption key
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
- SecretKeySpec masterKeySpec = new SecretKeySpec(masterPw, "AES");
- c.init(Cipher.ENCRYPT_MODE, masterKeySpec);
+ SecretKeySpec encryptionKeySpec = new SecretKeySpec(encryptionKey, "AES");
+ c.init(Cipher.ENCRYPT_MODE, encryptionKeySpec);
OutputStream finalOutput = new CipherOutputStream(ofstream, c);
// line 4: name of encryption algorithm
@@ -169,7 +167,7 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor
// line 5: user password salt [hex]
headerbuf.append(PasswordUtils.byteArrayToHex(newUserSalt));
headerbuf.append('\n');
- // line 6: master key checksum salt [hex]
+ // line 6: encryption key checksum salt [hex]
headerbuf.append(PasswordUtils.byteArrayToHex(checksumSalt));
headerbuf.append('\n');
// line 7: number of PBKDF2 rounds used [decimal]
@@ -184,21 +182,21 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor
headerbuf.append(PasswordUtils.byteArrayToHex(IV));
headerbuf.append('\n');
- // line 9: master IV + key blob, encrypted by the user key [hex]. Blob format:
+ // line 9: encryption IV + key blob, encrypted by the user key [hex]. Blob format:
// [byte] IV length = Niv
// [array of Niv bytes] IV itself
- // [byte] master key length = Nmk
- // [array of Nmk bytes] master key itself
- // [byte] MK checksum hash length = Nck
- // [array of Nck bytes] master key checksum hash
+ // [byte] encryption key length = Nek
+ // [array of Nek bytes] encryption key itself
+ // [byte] encryption key checksum hash length = Nck
+ // [array of Nck bytes] encryption key checksum hash
//
- // The checksum is the (master key + checksum salt), run through the
+ // The checksum is the (encryption key + checksum salt), run through the
// stated number of PBKDF2 rounds
IV = c.getIV();
- byte[] mk = masterKeySpec.getEncoded();
+ byte[] mk = encryptionKeySpec.getEncoded();
byte[] checksum = PasswordUtils
.makeKeyChecksum(PBKDF_CURRENT,
- masterKeySpec.getEncoded(),
+ encryptionKeySpec.getEncoded(),
checksumSalt, PasswordUtils.PBKDF2_HASH_ROUNDS);
ByteArrayOutputStream blob = new ByteArrayOutputStream(IV.length + mk.length
@@ -347,15 +345,15 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor
// When line 4 is not "none", then additional header data follows:
//
// line 5: user password salt [hex]
- // line 6: master key checksum salt [hex]
- // line 7: number of PBKDF2 rounds to use (same for user & master) [decimal]
+ // line 6: encryption key checksum salt [hex]
+ // line 7: number of PBKDF2 rounds to use (same for user & encryption key) [decimal]
// line 8: IV of the user key [hex]
- // line 9: master key blob [hex]
- // IV of the master key, master key itself, master key checksum hash
+ // line 9: encryption key blob [hex]
+ // IV of the encryption key, encryption key itself, encryption key checksum hash
//
- // The master key checksum is the master key plus its checksum salt, run through
+ // The encryption key checksum is the encryption key plus its checksum salt, run through
// 10k rounds of PBKDF2. This is used to verify that the user has supplied the
- // correct password for decrypting the archive: the master key decrypted from
+ // correct password for decrypting the archive: the encryption key decrypted from
// the archive using the user-supplied password is also run through PBKDF2 in
// this way, and if the result does not match the checksum as stored in the
// archive, then we know that the user-supplied password does not match the
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 82bed3b57f16..e42d3bd0e352 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -379,7 +379,7 @@ public class FullRestoreEngine extends RestoreEngine {
}
}
- // Sanity check: make sure we never give data to the wrong app. This
+ // Make sure we never give data to the wrong app. This
// should never happen but a little paranoia here won't go amiss.
if (okay && !pkg.equals(mAgentPackage)) {
Slog.e(TAG, "Restoring data for " + pkg
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 01b40fbff201..923bb086f914 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -212,10 +212,9 @@ public class PerformAdbRestoreTask implements Runnable {
return buffer.toString();
}
- private static InputStream attemptMasterKeyDecryption(String decryptPassword, String algorithm,
- byte[] userSalt, byte[] ckSalt,
- int rounds, String userIvHex, String masterKeyBlobHex, InputStream rawInStream,
- boolean doLog) {
+ private static InputStream attemptEncryptionKeyDecryption(String decryptPassword,
+ String algorithm, byte[] userSalt, byte[] ckSalt, int rounds, String userIvHex,
+ String encryptionKeyBlobHex, InputStream rawInStream, boolean doLog) {
InputStream result = null;
try {
@@ -228,31 +227,31 @@ public class PerformAdbRestoreTask implements Runnable {
c.init(Cipher.DECRYPT_MODE,
new SecretKeySpec(userKey.getEncoded(), "AES"),
ivSpec);
- byte[] mkCipher = PasswordUtils.hexToByteArray(masterKeyBlobHex);
+ byte[] mkCipher = PasswordUtils.hexToByteArray(encryptionKeyBlobHex);
byte[] mkBlob = c.doFinal(mkCipher);
- // first, the master key IV
+ // first, the encryption key IV
int offset = 0;
int len = mkBlob[offset++];
IV = Arrays.copyOfRange(mkBlob, offset, offset + len);
offset += len;
- // then the master key itself
+ // then the encryption key itself
len = mkBlob[offset++];
- byte[] mk = Arrays.copyOfRange(mkBlob,
+ byte[] encryptionKey = Arrays.copyOfRange(mkBlob,
offset, offset + len);
offset += len;
- // and finally the master key checksum hash
+ // and finally the encryption key checksum hash
len = mkBlob[offset++];
byte[] mkChecksum = Arrays.copyOfRange(mkBlob,
offset, offset + len);
- // now validate the decrypted master key against the checksum
- byte[] calculatedCk = PasswordUtils.makeKeyChecksum(algorithm, mk, ckSalt,
+ // now validate the decrypted encryption key against the checksum
+ byte[] calculatedCk = PasswordUtils.makeKeyChecksum(algorithm, encryptionKey, ckSalt,
rounds);
if (Arrays.equals(calculatedCk, mkChecksum)) {
ivSpec = new IvParameterSpec(IV);
c.init(Cipher.DECRYPT_MODE,
- new SecretKeySpec(mk, "AES"),
+ new SecretKeySpec(encryptionKey, "AES"),
ivSpec);
// Only if all of the above worked properly will 'result' be assigned
result = new CipherInputStream(rawInStream, c);
@@ -265,7 +264,7 @@ public class PerformAdbRestoreTask implements Runnable {
}
} catch (BadPaddingException e) {
// This case frequently occurs when the wrong password is used to decrypt
- // the master key. Use the identical "incorrect password" log text as is
+ // the encryption key. Use the identical "incorrect password" log text as is
// used in the checksum failure log in order to avoid providing additional
// information to an attacker.
if (doLog) {
@@ -273,7 +272,7 @@ public class PerformAdbRestoreTask implements Runnable {
}
} catch (IllegalBlockSizeException e) {
if (doLog) {
- Slog.w(TAG, "Invalid block size in master key");
+ Slog.w(TAG, "Invalid block size in encryption key");
}
} catch (NoSuchAlgorithmException e) {
if (doLog) {
@@ -309,15 +308,15 @@ public class PerformAdbRestoreTask implements Runnable {
int rounds = Integer.parseInt(readHeaderLine(rawInStream)); // 7
String userIvHex = readHeaderLine(rawInStream); // 8
- String masterKeyBlobHex = readHeaderLine(rawInStream); // 9
+ String encryptionKeyBlobHex = readHeaderLine(rawInStream); // 9
- // decrypt the master key blob
- result = attemptMasterKeyDecryption(decryptPassword, PBKDF_CURRENT,
- userSalt, ckSalt, rounds, userIvHex, masterKeyBlobHex, rawInStream, false);
+ // decrypt the encryption key blob
+ result = attemptEncryptionKeyDecryption(decryptPassword, PBKDF_CURRENT, userSalt,
+ ckSalt, rounds, userIvHex, encryptionKeyBlobHex, rawInStream, false);
if (result == null && pbkdf2Fallback) {
- result = attemptMasterKeyDecryption(
+ result = attemptEncryptionKeyDecryption(
decryptPassword, PBKDF_FALLBACK, userSalt, ckSalt,
- rounds, userIvHex, masterKeyBlobHex, rawInStream, true);
+ rounds, userIvHex, encryptionKeyBlobHex, rawInStream, true);
}
} else {
Slog.w(TAG, "Unsupported encryption method: " + encryptionName);
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 162921528e95..ee05c2b9ea3b 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
@@ -37,7 +37,6 @@ import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.util.ArrayUtils;
-import com.android.server.LocalServices;
import com.android.server.backup.transport.TransportClient;
import com.google.android.collect.Sets;
@@ -49,8 +48,8 @@ import java.util.Set;
*/
public class BackupEligibilityRules {
private static final boolean DEBUG = false;
- // Whitelist of system packages that are eligible for backup in non-system users.
- private static final Set<String> systemPackagesWhitelistedForAllUsers =
+ // List of system packages that are eligible for backup in non-system users.
+ private static final Set<String> systemPackagesAllowedForAllUsers =
Sets.newArraySet(PACKAGE_MANAGER_SENTINEL, PLATFORM_PACKAGE_NAME);
private final PackageManager mPackageManager;
@@ -97,9 +96,10 @@ public class BackupEligibilityRules {
// 2. they run as a system-level uid
if (UserHandle.isCore(app.uid)) {
- // and the backup is happening for non-system user on a non-whitelisted package.
+ // and the backup is happening for a non-system user on a package that is not explicitly
+ // allowed.
if (mUserId != UserHandle.USER_SYSTEM
- && !systemPackagesWhitelistedForAllUsers.contains(app.packageName)) {
+ && !systemPackagesAllowedForAllUsers.contains(app.packageName)) {
return false;
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 6d8f9a35bfaa..eb38f5199ce5 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -28,6 +28,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainRunna
import static java.util.concurrent.TimeUnit.MINUTES;
import android.annotation.CheckResult;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -84,6 +85,7 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.wm.ActivityTaskManagerInternal;
import org.xmlpull.v1.XmlPullParser;
@@ -189,7 +191,8 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
}
@Override
- public void onUnlockUser(int userHandle) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ int userHandle = user.getUserIdentifier();
Set<Association> associations = readAllAssociations(userHandle);
if (associations == null || associations.isEmpty()) {
return;
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 64d0e911652e..1093515ac525 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -128,6 +128,7 @@ java_library_static {
"android.hidl.manager-V1.2-java",
"capture_state_listener-aidl-java",
"dnsresolver_aidl_interface-java",
+ "icu4j_calendar_astronomer",
"netd_aidl_interfaces-platform-java",
"overlayable_policy_aidl-java",
"SurfaceFlingerProperties",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index b241bd16d3ee..ad1986a6669f 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -69,6 +69,7 @@ public abstract class PackageManagerInternal {
public static final int PACKAGE_WIFI = 13;
public static final int PACKAGE_COMPANION = 14;
public static final int PACKAGE_RETAIL_DEMO = 15;
+ public static final int PACKAGE_OVERLAY_CONFIG_SIGNATURE = 16;
@IntDef(flag = true, prefix = "RESOLVE_", value = {
RESOLVE_NON_BROWSER_ONLY,
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index f1d74bb08b85..a3c04be02c6f 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -59,16 +59,16 @@ public class BinderCallsStatsService extends Binder {
/** Resolves the work source of an incoming binder transaction. */
static class AuthorizedWorkSourceProvider implements BinderInternal.WorkSourceProvider {
- private ArraySet<Integer> mAppIdWhitelist;
+ private ArraySet<Integer> mAppIdTrustlist;
AuthorizedWorkSourceProvider() {
- mAppIdWhitelist = new ArraySet<>();
+ mAppIdTrustlist = new ArraySet<>();
}
public int resolveWorkSourceUid(int untrustedWorkSourceUid) {
final int callingUid = getCallingUid();
final int appId = UserHandle.getAppId(callingUid);
- if (mAppIdWhitelist.contains(appId)) {
+ if (mAppIdTrustlist.contains(appId)) {
final int workSource = untrustedWorkSourceUid;
final boolean isWorkSourceSet = workSource != Binder.UNSET_WORKSOURCE;
return isWorkSourceSet ? workSource : callingUid;
@@ -77,13 +77,13 @@ public class BinderCallsStatsService extends Binder {
}
public void systemReady(Context context) {
- mAppIdWhitelist = createAppidWhitelist(context);
+ mAppIdTrustlist = createAppidTrustlist(context);
}
public void dump(PrintWriter pw, AppIdToPackageMap packageMap) {
pw.println("AppIds of apps that can set the work source:");
- final ArraySet<Integer> whitelist = mAppIdWhitelist;
- for (Integer appId : whitelist) {
+ final ArraySet<Integer> trustlist = mAppIdTrustlist;
+ for (Integer appId : trustlist) {
pw.println("\t- " + packageMap.mapAppId(appId));
}
}
@@ -92,12 +92,12 @@ public class BinderCallsStatsService extends Binder {
return Binder.getCallingUid();
}
- private ArraySet<Integer> createAppidWhitelist(Context context) {
- // Use a local copy instead of mAppIdWhitelist to prevent concurrent read access.
- final ArraySet<Integer> whitelist = new ArraySet<>();
+ private ArraySet<Integer> createAppidTrustlist(Context context) {
+ // Use a local copy instead of mAppIdTrustlist to prevent concurrent read access.
+ final ArraySet<Integer> trustlist = new ArraySet<>();
// We trust our own process.
- whitelist.add(UserHandle.getAppId(Process.myUid()));
+ trustlist.add(UserHandle.getAppId(Process.myUid()));
// We only need to initialize it once. UPDATE_DEVICE_STATS is a system permission.
final PackageManager pm = context.getPackageManager();
final String[] permissions = { android.Manifest.permission.UPDATE_DEVICE_STATS };
@@ -110,12 +110,12 @@ public class BinderCallsStatsService extends Binder {
try {
final int uid = pm.getPackageUid(pkgInfo.packageName, queryFlags);
final int appId = UserHandle.getAppId(uid);
- whitelist.add(appId);
+ trustlist.add(appId);
} catch (NameNotFoundException e) {
Slog.e(TAG, "Cannot find uid for package name " + pkgInfo.packageName, e);
}
}
- return whitelist;
+ return trustlist;
}
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 2e4d44cef416..f372c6f85ec6 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -96,6 +96,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
+ private static final String BLUETOOTH_PRIVILEGED =
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED;
private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid";
private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address";
@@ -306,6 +308,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
};
public boolean onFactoryReset() {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
+ "Need BLUETOOTH_PRIVILEGED permission");
+
// Wait for stable state if bluetooth is temporary state.
int state = getState();
if (state == BluetoothAdapter.STATE_BLE_TURNING_ON
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
index 0bcd9373c660..1a1eecd0f439 100644
--- a/services/core/java/com/android/server/BluetoothService.java
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -16,10 +16,14 @@
package com.android.server;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.os.UserManager;
+import com.android.server.SystemService.TargetUser;
+
class BluetoothService extends SystemService {
private BluetoothManagerService mBluetoothManagerService;
private boolean mInitialized = false;
@@ -52,16 +56,16 @@ class BluetoothService extends SystemService {
}
@Override
- public void onSwitchUser(int userHandle) {
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
if (!mInitialized) {
initialize();
} else {
- mBluetoothManagerService.handleOnSwitchUser(userHandle);
+ mBluetoothManagerService.handleOnSwitchUser(to.getUserIdentifier());
}
}
@Override
- public void onUnlockUser(int userHandle) {
- mBluetoothManagerService.handleOnUnlockUser(userHandle);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mBluetoothManagerService.handleOnUnlockUser(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index c87dcd7874f8..b3d4085288dd 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -38,6 +38,7 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
+import android.telecom.TelecomManager;
import android.util.MutableBoolean;
import android.util.Slog;
import android.view.KeyEvent;
@@ -457,6 +458,8 @@ public class GestureLauncherService extends SystemService {
}
} else if (launchPanic) {
Slog.i(TAG, "Panic gesture detected, launching panic.");
+ launchPanic = handlePanicButtonGesture();
+ // TODO(b/160006048): Add logging
}
mMetricsLogger.histogram("power_consecutive_short_tap_count",
mPowerButtonSlowConsecutiveTaps);
@@ -501,6 +504,46 @@ public class GestureLauncherService extends SystemService {
}
}
+ /**
+ * @return true if panic ui was launched, false otherwise.
+ */
+ @VisibleForTesting
+ boolean handlePanicButtonGesture() {
+ // TODO(b/160006048): This is the wrong way to launch panic ui. Rewrite this to go
+ // through SysUI
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "GestureLauncher:handlePanicButtonGesture");
+ try {
+ boolean userSetupComplete = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
+ if (!userSetupComplete) {
+ if (DBG) {
+ Slog.d(TAG, String.format(
+ "userSetupComplete = %s, ignoring panic gesture.",
+ userSetupComplete));
+ }
+ return false;
+ }
+ if (DBG) {
+ Slog.d(TAG, String.format(
+ "userSetupComplete = %s, performing panic gesture.",
+ userSetupComplete));
+ }
+ // TODO(b/160006048): Not all devices have telephony. Check system feature first.
+ TelecomManager telecomManager = (TelecomManager) mContext.getSystemService(
+ Context.TELECOM_SERVICE);
+ mContext.startActivity(telecomManager.createLaunchEmergencyDialerIntent(null).addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_SINGLE_TOP).putExtra(
+ "com.android.phone.EmergencyDialer.extra.ENTRY_TYPE",
+ 2)); // 2 maps to power button, forcing into fast emergency dialer experience.
+ return true;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+ }
+
private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 3148a6205871..a3bcbbe25e88 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -20,6 +20,7 @@ import static android.app.ActivityManager.UID_OBSERVER_ACTIVE;
import static android.app.ActivityManager.UID_OBSERVER_GONE;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -60,6 +61,7 @@ import com.android.internal.app.ResolverActivity;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.SystemService.TargetUser;
import com.android.server.wm.ActivityTaskManagerInternal;
import dalvik.system.DexFile;
@@ -236,16 +238,18 @@ public final class PinnerService extends SystemService {
* individual apps. Make sure that user's preference is pinned into memory.
*/
@Override
- public void onSwitchUser(int userHandle) {
- if (!mUserManager.isManagedProfile(userHandle)) {
- sendPinAppsMessage(userHandle);
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+ int userId = to.getUserIdentifier();
+ if (!mUserManager.isManagedProfile(userId)) {
+ sendPinAppsMessage(userId);
}
}
@Override
- public void onUnlockUser(int userHandle) {
- if (!mUserManager.isManagedProfile(userHandle)) {
- sendPinAppsMessage(userHandle);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ int userId = user.getUserIdentifier();
+ if (!mUserManager.isManagedProfile(userId)) {
+ sendPinAppsMessage(userId);
}
}
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index e5d0021a2bdf..0038dc2e8da0 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -80,10 +80,16 @@ public class ServiceWatcher implements ServiceConnection {
default void onError() {}
}
+ /** Function to run on binder interface when first bound. */
+ public interface OnBindRunner {
+ /** Called to run client code with the binder. */
+ void run(IBinder binder, ComponentName service) throws RemoteException;
+ }
+
/**
* Information on the service ServiceWatcher has selected as the best option for binding.
*/
- public static final class ServiceInfo implements Comparable<ServiceInfo> {
+ private static final class ServiceInfo implements Comparable<ServiceInfo> {
public static final ServiceInfo NONE = new ServiceInfo(Integer.MIN_VALUE, null,
UserHandle.USER_NULL, false);
@@ -179,25 +185,25 @@ public class ServiceWatcher implements ServiceConnection {
private final Handler mHandler;
private final Intent mIntent;
- @Nullable private final BinderRunner mOnBind;
+ @Nullable private final OnBindRunner mOnBind;
@Nullable private final Runnable mOnUnbind;
// read/write from handler thread only
private int mCurrentUserId;
// write from handler thread only, read anywhere
- private volatile ServiceInfo mServiceInfo;
+ private volatile ServiceInfo mTargetService;
private volatile IBinder mBinder;
public ServiceWatcher(Context context, String action,
- @Nullable BinderRunner onBind, @Nullable Runnable onUnbind,
+ @Nullable OnBindRunner onBind, @Nullable Runnable onUnbind,
@BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) {
this(context, FgThread.getHandler(), action, onBind, onUnbind, enableOverlayResId,
nonOverlayPackageResId);
}
public ServiceWatcher(Context context, Handler handler, String action,
- @Nullable BinderRunner onBind, @Nullable Runnable onUnbind,
+ @Nullable OnBindRunner onBind, @Nullable Runnable onUnbind,
@BoolRes int enableOverlayResId, @StringRes int nonOverlayPackageResId) {
mContext = context;
mHandler = handler;
@@ -214,7 +220,7 @@ public class ServiceWatcher implements ServiceConnection {
mCurrentUserId = UserHandle.USER_NULL;
- mServiceInfo = ServiceInfo.NONE;
+ mTargetService = ServiceInfo.NONE;
mBinder = null;
}
@@ -304,7 +310,7 @@ public class ServiceWatcher implements ServiceConnection {
}
}
- if (forceRebind || !bestServiceInfo.equals(mServiceInfo)) {
+ if (forceRebind || !bestServiceInfo.equals(mTargetService)) {
rebind(bestServiceInfo);
}
}
@@ -312,32 +318,32 @@ public class ServiceWatcher implements ServiceConnection {
private void rebind(ServiceInfo newServiceInfo) {
Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
- if (!mServiceInfo.equals(ServiceInfo.NONE)) {
+ if (!mTargetService.equals(ServiceInfo.NONE)) {
if (D) {
- Log.i(TAG, "[" + mIntent.getAction() + "] unbinding from " + mServiceInfo);
+ Log.i(TAG, "[" + mIntent.getAction() + "] unbinding from " + mTargetService);
}
mContext.unbindService(this);
- onServiceDisconnected(mServiceInfo.component);
- mServiceInfo = ServiceInfo.NONE;
+ onServiceDisconnected(mTargetService.component);
+ mTargetService = ServiceInfo.NONE;
}
- mServiceInfo = newServiceInfo;
- if (mServiceInfo.equals(ServiceInfo.NONE)) {
+ mTargetService = newServiceInfo;
+ if (mTargetService.equals(ServiceInfo.NONE)) {
return;
}
- Preconditions.checkState(mServiceInfo.component != null);
+ Preconditions.checkState(mTargetService.component != null);
if (D) {
- Log.i(TAG, getLogPrefix() + " binding to " + mServiceInfo);
+ Log.i(TAG, getLogPrefix() + " binding to " + mTargetService);
}
- Intent bindIntent = new Intent(mIntent).setComponent(mServiceInfo.component);
+ Intent bindIntent = new Intent(mIntent).setComponent(mTargetService.component);
if (!mContext.bindServiceAsUser(bindIntent, this,
BIND_AUTO_CREATE | BIND_NOT_FOREGROUND | BIND_NOT_VISIBLE,
- mHandler, UserHandle.of(mServiceInfo.userId))) {
- mServiceInfo = ServiceInfo.NONE;
+ mHandler, UserHandle.of(mTargetService.userId))) {
+ mTargetService = ServiceInfo.NONE;
Log.e(TAG, getLogPrefix() + " unexpected bind failure - retrying later");
mHandler.postDelayed(() -> onBestServiceChanged(false), RETRY_DELAY_MS);
}
@@ -355,11 +361,11 @@ public class ServiceWatcher implements ServiceConnection {
mBinder = binder;
if (mOnBind != null) {
try {
- mOnBind.run(binder);
+ mOnBind.run(binder, component);
} catch (RuntimeException | RemoteException e) {
// binders may propagate some specific non-RemoteExceptions from the other side
// through the binder as well - we cannot allow those to crash the system server
- Log.e(TAG, getLogPrefix() + " exception running on " + mServiceInfo, e);
+ Log.e(TAG, getLogPrefix() + " exception running on " + component, e);
}
}
}
@@ -406,7 +412,7 @@ public class ServiceWatcher implements ServiceConnection {
void onPackageChanged(String packageName) {
// force a rebind if the changed package was the currently connected package
- onBestServiceChanged(packageName.equals(mServiceInfo.getPackageName()));
+ onBestServiceChanged(packageName.equals(mTargetService.getPackageName()));
}
/**
@@ -425,7 +431,7 @@ public class ServiceWatcher implements ServiceConnection {
} catch (RuntimeException | RemoteException e) {
// binders may propagate some specific non-RemoteExceptions from the other side
// through the binder as well - we cannot allow those to crash the system server
- Log.e(TAG, getLogPrefix() + " exception running on " + mServiceInfo, e);
+ Log.e(TAG, getLogPrefix() + " exception running on " + mTargetService, e);
runner.onError();
}
});
@@ -437,14 +443,14 @@ public class ServiceWatcher implements ServiceConnection {
@Override
public String toString() {
- return mServiceInfo.toString();
+ return mTargetService.toString();
}
/**
* Dump for debugging.
*/
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("service=" + mServiceInfo);
+ pw.println("target service=" + mTargetService);
pw.println("connected=" + (mBinder != null));
}
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 1520dd351c97..eca6036ebf8e 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -55,6 +55,7 @@ import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -152,6 +153,7 @@ import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
+import com.android.server.SystemService.TargetUser;
import com.android.server.pm.Installer;
import com.android.server.storage.AppFuseBridge;
import com.android.server.storage.StorageSessionController;
@@ -259,23 +261,23 @@ class StorageManagerService extends IStorageManager.Stub
}
@Override
- public void onSwitchUser(int userHandle) {
- mStorageManagerService.mCurrentUserId = userHandle;
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+ mStorageManagerService.mCurrentUserId = to.getUserIdentifier();
}
@Override
- public void onUnlockUser(int userHandle) {
- mStorageManagerService.onUnlockUser(userHandle);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mStorageManagerService.onUnlockUser(user.getUserIdentifier());
}
@Override
- public void onCleanupUser(int userHandle) {
- mStorageManagerService.onCleanupUser(userHandle);
+ public void onUserStopped(@NonNull TargetUser user) {
+ mStorageManagerService.onCleanupUser(user.getUserIdentifier());
}
@Override
- public void onStopUser(int userHandle) {
- mStorageManagerService.onStopUser(userHandle);
+ public void onUserStopping(@NonNull TargetUser user) {
+ mStorageManagerService.onStopUser(user.getUserIdentifier());
}
@Override
diff --git a/services/core/java/com/android/server/SystemService.java b/services/core/java/com/android/server/SystemService.java
index 45d53a14d1e9..1496e926b95b 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/services/core/java/com/android/server/SystemService.java
@@ -23,7 +23,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
-import android.annotation.UserIdInt;
import android.app.ActivityThread;
import android.content.Context;
import android.content.pm.UserInfo;
@@ -263,26 +262,6 @@ public abstract class SystemService {
}
/**
- * @deprecated subclasses should extend {@link #onUserStarting(TargetUser)} instead
- * (which by default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onStartUser(@UserIdInt int userId) {}
-
- /**
- * @deprecated subclasses should extend {@link #onUserStarting(TargetUser)} instead
- * (which by default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onStartUser(@NonNull UserInfo userInfo) {
- onStartUser(userInfo.id);
- }
-
- /**
* Called when a new user is starting, for system services to initialize any per-user
* state they maintain for running users.
*
@@ -292,27 +271,6 @@ public abstract class SystemService {
* @param user target user
*/
public void onUserStarting(@NonNull TargetUser user) {
- onStartUser(user.getUserInfo());
- }
-
- /**
- * @deprecated subclasses should extend {@link #onUserUnlocking(TargetUser)} instead (which by
- * default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onUnlockUser(@UserIdInt int userId) {}
-
- /**
- * @deprecated subclasses should extend {@link #onUserUnlocking(TargetUser)} instead (which by
- * default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onUnlockUser(@NonNull UserInfo userInfo) {
- onUnlockUser(userInfo.id);
}
/**
@@ -333,7 +291,6 @@ public abstract class SystemService {
* @param user target user
*/
public void onUserUnlocking(@NonNull TargetUser user) {
- onUnlockUser(user.getUserInfo());
}
/**
@@ -348,26 +305,6 @@ public abstract class SystemService {
}
/**
- * @deprecated subclasses should extend {@link #onUserSwitching(TargetUser, TargetUser)} instead
- * (which by default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onSwitchUser(@UserIdInt int toUserId) {}
-
- /**
- * @deprecated subclasses should extend {@link #onUserSwitching(TargetUser, TargetUser)} instead
- * (which by default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onSwitchUser(@Nullable UserInfo from, @NonNull UserInfo to) {
- onSwitchUser(to.id);
- }
-
- /**
* Called when switching to a different foreground user, for system services that have
* special behavior for whichever user is currently in the foreground. This is called
* before any application processes are aware of the new user.
@@ -382,28 +319,6 @@ public abstract class SystemService {
* @param to the user switching to
*/
public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
- onSwitchUser((from == null ? null : from.getUserInfo()), to.getUserInfo());
- }
-
- /**
- * @deprecated subclasses should extend {@link #onUserStopping(TargetUser)} instead
- * (which by default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onStopUser(@UserIdInt int userId) {}
-
- /**
- * @deprecated subclasses should extend {@link #onUserStopping(TargetUser)} instead
- * (which by default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onStopUser(@NonNull UserInfo user) {
- onStopUser(user.id);
-
}
/**
@@ -420,27 +335,6 @@ public abstract class SystemService {
* @param user target user
*/
public void onUserStopping(@NonNull TargetUser user) {
- onStopUser(user.getUserInfo());
- }
-
- /**
- * @deprecated subclasses should extend {@link #onUserStopped(TargetUser)} instead (which by
- * default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onCleanupUser(@UserIdInt int userId) {}
-
- /**
- * @deprecated subclasses should extend {@link #onUserStopped(TargetUser)} instead (which by
- * default calls this method).
- *
- * @hide
- */
- @Deprecated
- public void onCleanupUser(@NonNull UserInfo user) {
- onCleanupUser(user.id);
}
/**
@@ -454,7 +348,6 @@ public abstract class SystemService {
* @param user target user
*/
public void onUserStopped(@NonNull TargetUser user) {
- onCleanupUser(user.getUserInfo());
}
/**
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index a4c6c8751d93..6d71c8e68f77 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -34,7 +34,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.net.LinkProperties;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -46,8 +45,6 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.telephony.Annotation;
-import android.telephony.Annotation.ApnType;
-import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SrvccState;
import android.telephony.BarringInfo;
@@ -80,7 +77,9 @@ import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
+import android.util.ArrayMap;
import android.util.LocalLog;
+import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
@@ -103,6 +102,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Objects;
/**
* Since phone process can be restarted, this class provides a centralized place
@@ -111,11 +111,11 @@ import java.util.NoSuchElementException;
* Change-Id: I450c968bda93767554b5188ee63e10c9f43c5aa4 fixes bugs 16148026
* and 15973975 by saving the phoneId of the registrant and then using the
* phoneId when deciding to to make a callback. This is necessary because
- * a subId changes from to a dummy value when a SIM is removed and thus won't
+ * a subId changes from to a placeholder value when a SIM is removed and thus won't
* compare properly. Because getPhoneIdFromSubId(int subId) handles
- * the dummy value conversion we properly do the callbacks.
+ * the placeholder value conversion we properly do the callbacks.
*
- * Eventually we may want to remove the notion of dummy value but for now this
+ * Eventually we may want to remove the notion of placeholder value but for now this
* looks like the best approach.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@@ -302,13 +302,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
@RadioPowerState
private int mRadioPowerState = TelephonyManager.RADIO_POWER_UNAVAILABLE;
- private final LocalLog mLocalLog = new LocalLog(100);
+ private final LocalLog mLocalLog = new LocalLog(200);
- private final LocalLog mListenLog = new LocalLog(100);
+ private final LocalLog mListenLog = new LocalLog(00);
- // Per-phoneMap of APN Type to DataConnectionState
- private List<Map<Integer, PreciseDataConnectionState>> mPreciseDataConnectionStates =
- new ArrayList<Map<Integer, PreciseDataConnectionState>>();
+ /**
+ * Per-phone map of precise data connection state. The key of the map is the pair of transport
+ * type and APN setting. This is the cache to prevent redundant callbacks to the listeners.
+ * A precise data connection with state {@link TelephonyManager#DATA_DISCONNECTED} removes
+ * its entry from the map.
+ */
+ private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>>
+ mPreciseDataConnectionStates;
static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK =
PhoneStateListener.LISTEN_REGISTRATION_FAILURE
@@ -521,7 +526,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
- mPreciseDataConnectionStates.add(new HashMap<Integer, PreciseDataConnectionState>());
+ mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
}
@@ -610,7 +615,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
- mPreciseDataConnectionStates.add(new HashMap<Integer, PreciseDataConnectionState>());
+ mPreciseDataConnectionStates.add(new ArrayMap<>());
mBarringInfo.add(i, new BarringInfo());
mTelephonyDisplayInfos[i] = null;
}
@@ -1687,38 +1692,25 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
*
* @param phoneId the phoneId carrying the data connection
* @param subId the subscriptionId for the data connection
- * @param apnType the apn type bitmask, defined with {@code ApnSetting#TYPE_*} flags.
* @param preciseState a PreciseDataConnectionState that has info about the data connection
*/
@Override
- public void notifyDataConnectionForSubscriber(
- int phoneId, int subId, @ApnType int apnType, PreciseDataConnectionState preciseState) {
+ public void notifyDataConnectionForSubscriber(int phoneId, int subId,
+ @NonNull PreciseDataConnectionState preciseState) {
if (!checkNotifyPermission("notifyDataConnection()" )) {
return;
}
- String apn = "";
- int state = TelephonyManager.DATA_UNKNOWN;
- int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- LinkProperties linkProps = null;
+ ApnSetting apnSetting = preciseState.getApnSetting();
- if (preciseState != null) {
- apn = preciseState.getDataConnectionApn();
- state = preciseState.getState();
- networkType = preciseState.getNetworkType();
- linkProps = preciseState.getLinkProperties();
- }
- if (VDBG) {
- log("notifyDataConnectionForSubscriber: subId=" + subId
- + " state=" + state + "' apn='" + apn
- + "' apnType=" + apnType + " networkType=" + networkType
- + "' preciseState=" + preciseState);
- }
+ int apnTypes = apnSetting.getApnTypeBitmask();
+ int state = preciseState.getState();
+ int networkType = preciseState.getNetworkType();
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
// We only call the callback when the change is for default APN type.
- if ((ApnSetting.TYPE_DEFAULT & apnType) != 0
+ if ((ApnSetting.TYPE_DEFAULT & apnTypes) != 0
&& (mDataConnectionState[phoneId] != state
|| mDataConnectionNetworkType[phoneId] != networkType)) {
String str = "onDataConnectionStateChanged("
@@ -1747,19 +1739,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mDataConnectionNetworkType[phoneId] = networkType;
}
- boolean needsNotify = false;
- // State has been cleared for this APN Type
- if (preciseState == null) {
- // We try clear the state and check if the state was previously not cleared
- needsNotify = mPreciseDataConnectionStates.get(phoneId).remove(apnType) != null;
- } else {
- // We need to check to see if the state actually changed
- PreciseDataConnectionState oldPreciseState =
- mPreciseDataConnectionStates.get(phoneId).put(apnType, preciseState);
- needsNotify = !preciseState.equals(oldPreciseState);
- }
-
- if (needsNotify) {
+ Pair<Integer, ApnSetting> key = Pair.create(preciseState.getTransportType(),
+ preciseState.getApnSetting());
+ PreciseDataConnectionState oldState = mPreciseDataConnectionStates.get(phoneId)
+ .remove(key);
+ if (!Objects.equals(oldState, preciseState)) {
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
@@ -1771,52 +1755,22 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
}
- }
- }
- handleRemoveListLocked();
- }
+ handleRemoveListLocked();
- broadcastDataConnectionStateChanged(state, apn, apnType, subId);
- }
+ broadcastDataConnectionStateChanged(phoneId, subId, preciseState);
- /**
- * Stub to satisfy the ITelephonyRegistry aidl interface; do not use this function.
- * @see #notifyDataConnectionFailedForSubscriber
- */
- public void notifyDataConnectionFailed(String apnType) {
- loge("This function should not be invoked");
- }
+ String str = "notifyDataConnectionForSubscriber: phoneId=" + phoneId + " subId="
+ + subId + " " + preciseState;
+ log(str);
+ mLocalLog.log(str);
+ }
- private void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, int apnType) {
- if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
- return;
- }
- if (VDBG) {
- log("notifyDataConnectionFailedForSubscriber: subId=" + subId
- + " apnType=" + apnType);
- }
- synchronized (mRecords) {
- if (validatePhoneId(phoneId)) {
- mPreciseDataConnectionStates.get(phoneId).put(
- apnType,
- new PreciseDataConnectionState.Builder()
- .setApnTypes(apnType)
- .build());
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
- && idMatch(r.subId, subId, phoneId)) {
- try {
- r.callback.onPreciseDataConnectionStateChanged(
- mPreciseDataConnectionStates.get(phoneId).get(apnType));
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
- }
- }
+ // If the state is disconnected, it would be the end of life cycle of a data
+ // connection, so remove it from the cache.
+ if (preciseState.getState() != TelephonyManager.DATA_DISCONNECTED) {
+ mPreciseDataConnectionStates.get(phoneId).put(key, preciseState);
}
}
-
- handleRemoveListLocked();
}
}
@@ -1970,41 +1924,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
@Override
- public void notifyPreciseDataConnectionFailed(int phoneId, int subId, @ApnType int apnType,
- String apn, @DataFailureCause int failCause) {
- if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
- return;
- }
-
- // precise notify invokes imprecise notify
- notifyDataConnectionFailedForSubscriber(phoneId, subId, apnType);
-
- synchronized (mRecords) {
- if (validatePhoneId(phoneId)) {
- mPreciseDataConnectionStates.get(phoneId).put(
- apnType,
- new PreciseDataConnectionState.Builder()
- .setApnTypes(apnType)
- .setFailCause(failCause)
- .build());
- for (Record r : mRecords) {
- if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
- && idMatch(r.subId, subId, phoneId)) {
- try {
- r.callback.onPreciseDataConnectionStateChanged(
- mPreciseDataConnectionStates.get(phoneId).get(apnType));
- } catch (RemoteException ex) {
- mRemoveList.add(r.binder);
- }
- }
- }
- }
- handleRemoveListLocked();
- }
- }
-
- @Override
public void notifySrvccStateChanged(int subId, @SrvccState int state) {
if (!checkNotifyPermission("notifySrvccStateChanged()")) {
return;
@@ -2574,16 +2493,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
- private void broadcastDataConnectionStateChanged(int state, String apn,
- int apnType, int subId) {
+ private void broadcastDataConnectionStateChanged(int slotIndex, int subId,
+ @NonNull PreciseDataConnectionState pdcs) {
// Note: not reporting to the battery stats service here, because the
// status bar takes care of that after taking into account all of the
// required info.
Intent intent = new Intent(ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
- intent.putExtra(PHONE_CONSTANTS_STATE_KEY, TelephonyUtils.dataStateToString(state));
- intent.putExtra(PHONE_CONSTANTS_DATA_APN_KEY, apn);
+ intent.putExtra(PHONE_CONSTANTS_STATE_KEY,
+ TelephonyUtils.dataStateToString(pdcs.getState()));
+ intent.putExtra(PHONE_CONSTANTS_DATA_APN_KEY, pdcs.getApnSetting().getApnName());
intent.putExtra(PHONE_CONSTANTS_DATA_APN_TYPE_KEY,
- ApnSetting.getApnTypesStringFromBitmask(apnType));
+ ApnSetting.getApnTypesStringFromBitmask(pdcs.getApnSetting().getApnTypeBitmask()));
+ intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, slotIndex);
intent.putExtra(PHONE_CONSTANTS_SUBSCRIPTION_KEY, subId);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL, Manifest.permission.READ_PHONE_STATE);
}
@@ -2969,7 +2890,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
/**
* Returns a string representation of the radio technology (network type)
* currently in use on the device.
- * @param subId for which network type is returned
+ * @param type for which network type is returned
* @return the name of the radio technology
*
*/
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 915189c085c2..df9dee89f5a2 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -16,7 +16,15 @@
package com.android.server;
+import static android.app.UiModeManager.DEFAULT_PRIORITY;
+import static android.app.UiModeManager.MODE_NIGHT_AUTO;
+import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
+import static android.app.UiModeManager.MODE_NIGHT_YES;
+import static android.os.UserHandle.USER_SYSTEM;
+import static android.util.TimeUtils.isTimeBetween;
+
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
@@ -64,6 +72,7 @@ import com.android.internal.app.DisableCarModeActivity;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.DumpUtils;
+import com.android.server.SystemService.TargetUser;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
@@ -81,13 +90,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import static android.app.UiModeManager.DEFAULT_PRIORITY;
-import static android.app.UiModeManager.MODE_NIGHT_AUTO;
-import static android.app.UiModeManager.MODE_NIGHT_CUSTOM;
-import static android.app.UiModeManager.MODE_NIGHT_YES;
-import static android.os.UserHandle.USER_SYSTEM;
-import static android.util.TimeUtils.isTimeBetween;
-
final class UiModeManagerService extends SystemService {
private static final String TAG = UiModeManager.class.getSimpleName();
private static final boolean LOG = false;
@@ -322,8 +324,7 @@ final class UiModeManagerService extends SystemService {
}
@Override
- public void onSwitchUser(int userHandle) {
- super.onSwitchUser(userHandle);
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
getContext().getContentResolver().unregisterContentObserver(mSetupWizardObserver);
verifySetupWizardCompleted();
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 7dc0b3a8ecd6..35e88eb804cb 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -106,6 +106,7 @@ import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
@@ -161,14 +162,14 @@ public class AccountManagerService
}
@Override
- public void onUnlockUser(int userHandle) {
- mService.onUnlockUser(userHandle);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mService.onUnlockUser(user.getUserIdentifier());
}
@Override
- public void onStopUser(int userHandle) {
- Slog.i(TAG, "onStopUser " + userHandle);
- mService.purgeUserData(userHandle);
+ public void onUserStopping(@NonNull TargetUser user) {
+ Slog.i(TAG, "onStopUser " + user);
+ mService.purgeUserData(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cca2654815ad..c187772df6e4 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -341,6 +341,7 @@ import com.android.server.PackageWatchdog;
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.SystemServiceManager;
import com.android.server.ThreadPriorityBooster;
import com.android.server.UserspaceRebootLogger;
@@ -2333,8 +2334,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
- public void onCleanupUser(int userId) {
- mService.mBatteryStatsService.onCleanupUser(userId);
+ public void onUserStopped(@NonNull TargetUser user) {
+ mService.mBatteryStatsService.onCleanupUser(user.getUserIdentifier());
}
public ActivityManagerService getService() {
@@ -2443,7 +2444,7 @@ public class ActivityManagerService extends IActivityManager.Stub
? Collections.emptyList()
: Arrays.asList(exemptions.split(","));
}
- if (!ZYGOTE_PROCESS.setApiBlacklistExemptions(mExemptions)) {
+ if (!ZYGOTE_PROCESS.setApiDenylistExemptions(mExemptions)) {
Slog.e(TAG, "Failed to set API blacklist exemptions!");
// leave mExemptionsStr as is, so we don't try to send the same list again.
mExemptions = Collections.emptyList();
@@ -13394,7 +13395,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// XXX Commented out for now. Trying to figure out a way to reproduce
// the actual situation to identify what is actually going on.
if (false) {
- mCpHelper.cleanupLaunchingProviders();
+ mCpHelper.cleanupLaunchingProvidersLocked();
}
skipCurrentReceiverLocked(app);
@@ -14286,7 +14287,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType,
- int callingUid, int[] users, int[] broadcastWhitelist) {
+ int callingUid, int[] users, int[] broadcastAllowList) {
// TODO: come back and remove this assumption to triage all broadcasts
int pmFlags = STOCK_PM_FLAGS | MATCH_DEBUG_TRIAGED_MISSING;
@@ -14362,12 +14363,12 @@ public class ActivityManagerService extends IActivityManager.Stub
} catch (RemoteException ex) {
// pm is in same process, this will never happen.
}
- if (receivers != null && broadcastWhitelist != null) {
+ if (receivers != null && broadcastAllowList != null) {
for (int i = receivers.size() - 1; i >= 0; i--) {
final int receiverAppId = UserHandle.getAppId(
receivers.get(i).activityInfo.applicationInfo.uid);
if (receiverAppId >= Process.FIRST_APPLICATION_UID
- && Arrays.binarySearch(broadcastWhitelist, receiverAppId) < 0) {
+ && Arrays.binarySearch(broadcastAllowList, receiverAppId) < 0) {
receivers.remove(i);
}
}
@@ -14477,7 +14478,7 @@ public class ActivityManagerService extends IActivityManager.Stub
boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
@Nullable IBinder backgroundActivityStartsToken,
- @Nullable int[] broadcastWhitelist) {
+ @Nullable int[] broadcastAllowList) {
intent = new Intent(intent);
final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
@@ -14486,10 +14487,10 @@ public class ActivityManagerService extends IActivityManager.Stub
intent.setFlags(intent.getFlags() & ~Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
}
- if (userId == UserHandle.USER_ALL && broadcastWhitelist != null) {
- Slog.e(TAG, "broadcastWhitelist only applies when sending to individual users. "
+ if (userId == UserHandle.USER_ALL && broadcastAllowList != null) {
+ Slog.e(TAG, "broadcastAllowList only applies when sending to individual users. "
+ "Assuming restrictive whitelist.");
- broadcastWhitelist = new int[]{};
+ broadcastAllowList = new int[]{};
}
// By default broadcasts do not go to stopped apps.
@@ -14981,7 +14982,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
== 0) {
receivers = collectReceiverComponents(
- intent, resolvedType, callingUid, users, broadcastWhitelist);
+ intent, resolvedType, callingUid, users, broadcastAllowList);
}
if (intent.getComponent() == null) {
if (userId == UserHandle.USER_ALL && callingUid == SHELL_UID) {
@@ -15011,13 +15012,13 @@ public class ActivityManagerService extends IActivityManager.Stub
if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing broadcast: " + intent.getAction()
+ " replacePending=" + replacePending);
- if (registeredReceivers != null && broadcastWhitelist != null) {
+ if (registeredReceivers != null && broadcastAllowList != null) {
// if a uid whitelist was provided, remove anything in the application space that wasn't
// in it.
for (int i = registeredReceivers.size() - 1; i >= 0; i--) {
final int owningAppId = UserHandle.getAppId(registeredReceivers.get(i).owningUid);
if (owningAppId >= Process.FIRST_APPLICATION_UID
- && Arrays.binarySearch(broadcastWhitelist, owningAppId) < 0) {
+ && Arrays.binarySearch(broadcastAllowList, owningAppId) < 0) {
registeredReceivers.remove(i);
}
}
@@ -17996,7 +17997,7 @@ public class ActivityManagerService extends IActivityManager.Stub
public int broadcastIntent(Intent intent,
IIntentReceiver resultTo,
String[] requiredPermissions,
- boolean serialized, int userId, int[] appIdWhitelist) {
+ boolean serialized, int userId, int[] appIdAllowList) {
synchronized (ActivityManagerService.this) {
intent = verifyBroadcastLocked(intent);
@@ -18011,7 +18012,7 @@ public class ActivityManagerService extends IActivityManager.Stub
null /*options*/, serialized, false /*sticky*/, callingPid, callingUid,
callingUid, callingPid, userId, false /*allowBackgroundStarts*/,
null /*tokenNeededForBackgroundActivityStarts*/,
- appIdWhitelist);
+ appIdAllowList);
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 43e3a04ad032..d9fde0f6728a 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -16,8 +16,6 @@
package com.android.server.am;
-import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
-
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_COMPACTION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FREEZER;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
@@ -256,7 +254,7 @@ public final class CachedAppOptimizer {
ProcessDependencies processDependencies) {
mAm = am;
mCachedAppOptimizerThread = new ServiceThread("CachedAppOptimizerThread",
- THREAD_PRIORITY_FOREGROUND, true);
+ Process.THREAD_GROUP_SYSTEM, true);
mProcStateThrottle = new HashSet<>();
mProcessDependencies = processDependencies;
mTestCallback = callback;
@@ -280,8 +278,6 @@ public final class CachedAppOptimizer {
updateProcStateThrottle();
updateUseFreezer();
}
- Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(),
- Process.THREAD_GROUP_SYSTEM);
}
/**
@@ -411,12 +407,15 @@ public final class CachedAppOptimizer {
mUseCompaction = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_USE_COMPACTION, DEFAULT_USE_COMPACTION);
- if (mUseCompaction) {
+ if (mUseCompaction && mCompactionHandler == null) {
if (!mCachedAppOptimizerThread.isAlive()) {
mCachedAppOptimizerThread.start();
}
mCompactionHandler = new MemCompactionHandler();
+
+ Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(),
+ Process.THREAD_GROUP_SYSTEM);
}
}
@@ -470,13 +469,16 @@ public final class CachedAppOptimizer {
mUseFreezer = isFreezerSupported();
}
- if (mUseFreezer) {
+ if (mUseFreezer && mFreezeHandler == null) {
Slog.d(TAG_AM, "Freezer enabled");
if (!mCachedAppOptimizerThread.isAlive()) {
mCachedAppOptimizerThread.start();
}
mFreezeHandler = new FreezeHandler();
+
+ Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(),
+ Process.THREAD_GROUP_SYSTEM);
}
}
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 1e0c243ff3f5..5cc7aba736e1 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -15,19 +15,15 @@
*/
package com.android.server.am;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Process.PROC_CHAR;
import static android.os.Process.PROC_OUT_LONG;
import static android.os.Process.PROC_PARENS;
import static android.os.Process.PROC_SPACE_TERM;
import static android.os.Process.SYSTEM_UID;
-import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
-import static android.os.Process.readProcFile;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
import static com.android.server.am.ActivityManagerService.TAG_MU;
-import android.Manifest;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -80,11 +76,7 @@ import java.util.Objects;
public class ContentProviderHelper {
private static final String TAG = "ContentProviderHelper";
- private ActivityManagerService mService;
-
- private boolean mSystemProvidersInstalled;
-
- private final ProviderMap mProviderMap;
+ private final ActivityManagerService mService;
/**
* List of content providers who have clients waiting for them. The
@@ -92,6 +84,8 @@ public class ContentProviderHelper {
* removed from this list once it is published.
*/
private final ArrayList<ContentProviderRecord> mLaunchingProviders = new ArrayList<>();
+ private final ProviderMap mProviderMap;
+ private boolean mSystemProvidersInstalled;
ContentProviderHelper(ActivityManagerService service, boolean createProviderMap) {
mService = service;
@@ -102,651 +96,6 @@ public class ContentProviderHelper {
return mProviderMap;
}
- List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
- List<ProviderInfo> providers = null;
- try {
- providers = AppGlobals.getPackageManager().queryContentProviders(
- app.processName, app.uid, ActivityManagerService.STOCK_PM_FLAGS
- | PackageManager.GET_URI_PERMISSION_PATTERNS
- | PackageManager.MATCH_DIRECT_BOOT_AUTO, /*metaDataKey=*/ null)
- .getList();
- } catch (RemoteException ex) {
- }
- if (DEBUG_MU) {
- Slog.v(TAG_MU, "generateApplicationProvidersLocked, app.info.uid = " + app.uid);
- }
- int userId = app.userId;
- if (providers != null) {
- int N = providers.size();
- app.pubProviders.ensureCapacity(N + app.pubProviders.size());
- for (int i = 0; i < N; i++) {
- // TODO: keep logic in sync with installEncryptionUnawareProviders
- ProviderInfo cpi = (ProviderInfo) providers.get(i);
- boolean singleton = mService.isSingleton(cpi.processName, cpi.applicationInfo,
- cpi.name, cpi.flags);
- if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_SYSTEM) {
- // This is a singleton provider, but a user besides the
- // default user is asking to initialize a process it runs
- // in... well, no, it doesn't actually run in this process,
- // it runs in the process of the default user. Get rid of it.
- providers.remove(i);
- N--;
- i--;
- continue;
- }
-
- ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
- ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
- if (cpr == null) {
- cpr = new ContentProviderRecord(mService, cpi, app.info, comp, singleton);
- mProviderMap.putProviderByClass(comp, cpr);
- }
- if (DEBUG_MU) {
- Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
- }
- app.pubProviders.put(cpi.name, cpr);
- if (!cpi.multiprocess || !"android".equals(cpi.packageName)) {
- // Don't add this if it is a platform component that is marked
- // to run in multiple processes, because this is actually
- // part of the framework so doesn't make sense to track as a
- // separate apk in the process.
- app.addPackage(cpi.applicationInfo.packageName,
- cpi.applicationInfo.longVersionCode, mService.mProcessStats);
- }
- mService.notifyPackageUse(cpi.applicationInfo.packageName,
- PackageManager.NOTIFY_PACKAGE_USE_CONTENT_PROVIDER);
- }
- }
- return providers;
- }
-
- @GuardedBy("mService")
- private ContentProviderConnection incProviderCountLocked(ProcessRecord r,
- final ContentProviderRecord cpr, IBinder externalProcessToken, int callingUid,
- String callingPackage, String callingTag, boolean stable, boolean updateLru,
- long startTime, ProcessList processList) {
- if (r != null) {
- for (int i = 0; i < r.conProviders.size(); i++) {
- ContentProviderConnection conn = r.conProviders.get(i);
- if (conn.provider == cpr) {
- conn.incrementCount(stable);
- return conn;
- }
- }
-
- // Create a new ContentProviderConnection. The reference count
- // is known to be 1.
- ContentProviderConnection conn = new ContentProviderConnection(cpr, r, callingPackage);
- conn.startAssociationIfNeeded();
- conn.initializeCount(stable);
- cpr.connections.add(conn);
- r.conProviders.add(conn);
- mService.startAssociationLocked(r.uid, r.processName, r.getCurProcState(),
- cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
- if (updateLru && cpr.proc != null
- && r != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
- // If this is a perceptible app accessing the provider, make
- // sure to count it as being accessed and thus back up on
- // the LRU list. This is good because content providers are
- // often expensive to start. The calls to checkTime() use
- // the "getContentProviderImpl" tag here, because it's part
- // of the checktime log in getContentProviderImpl().
- checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
- processList.updateLruProcessLocked(cpr.proc, false, null);
- checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
- }
- return conn;
- }
- cpr.addExternalProcessHandleLocked(externalProcessToken, callingUid, callingTag);
- return null;
- }
-
- @GuardedBy("mService")
- private boolean decProviderCountLocked(ContentProviderConnection conn,
- ContentProviderRecord cpr,
- IBinder externalProcessToken, boolean stable) {
- if (conn != null) {
- cpr = conn.provider;
- final int referenceCount = conn.decrementCount(stable);
- if (referenceCount == 0) {
- conn.stopAssociation();
- cpr.connections.remove(conn);
- conn.client.conProviders.remove(conn);
- if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
- // The client is more important than last activity -- note the time this
- // is happening, so we keep the old provider process around a bit as last
- // activity to avoid thrashing it.
- if (cpr.proc != null) {
- cpr.proc.lastProviderTime = SystemClock.uptimeMillis();
- }
- }
- mService.stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid,
- cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
- return true;
- }
- return false;
- }
- cpr.removeExternalProcessHandleLocked(externalProcessToken);
- return false;
- }
-
- private static final class StartActivityRunnable implements Runnable {
- private final Context mContext;
- private final Intent mIntent;
- private final UserHandle mUserHandle;
-
- StartActivityRunnable(Context context, Intent intent, UserHandle userHandle) {
- this.mContext = context;
- this.mIntent = intent;
- this.mUserHandle = userHandle;
- }
-
- @Override
- public void run() {
- mContext.startActivityAsUser(mIntent, mUserHandle);
- }
- }
-
- private boolean requestTargetProviderPermissionsReviewIfNeededLocked(ProviderInfo cpi,
- ProcessRecord r, final int userId, Context context) {
- if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
- cpi.packageName, userId)) {
-
- final boolean callerForeground = r == null || r.setSchedGroup
- != ProcessList.SCHED_GROUP_BACKGROUND;
-
- // Show a permission review UI only for starting from a foreground app
- if (!callerForeground) {
- Slog.w(TAG, "u" + userId + " Instantiating a provider in package"
- + cpi.packageName + " requires a permissions review");
- return false;
- }
-
- final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
- intent.addFlags(FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- intent.putExtra(Intent.EXTRA_PACKAGE_NAME, cpi.packageName);
-
- if (ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW) {
- Slog.i(TAG, "u" + userId + " Launching permission review "
- + "for package " + cpi.packageName);
- }
-
- final UserHandle userHandle = new UserHandle(userId);
- mService.mHandler.post(new StartActivityRunnable(context, intent, userHandle));
-
- return false;
- }
-
- return true;
- }
-
- /**
- * Check if the calling UID has a possible chance at accessing the provider
- * at the given authority and user.
- */
- public String checkContentProviderAccess(String authority, int userId) {
- if (userId == UserHandle.USER_ALL) {
- mService.mContext.enforceCallingOrSelfPermission(
- Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
- userId = UserHandle.getCallingUserId();
- }
-
- ProviderInfo cpi = null;
- try {
- cpi = AppGlobals.getPackageManager().resolveContentProvider(authority,
- ActivityManagerService.STOCK_PM_FLAGS
- | PackageManager.GET_URI_PERMISSION_PATTERNS
- | PackageManager.MATCH_DISABLED_COMPONENTS
- | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- userId);
- } catch (RemoteException ignored) {
- }
- if (cpi == null) {
- return "Failed to find provider " + authority + " for user " + userId
- + "; expected to find a valid ContentProvider for this authority";
- }
-
- ProcessRecord r = null;
- synchronized (mService.mPidsSelfLocked) {
- r = mService.mPidsSelfLocked.get(Binder.getCallingPid());
- }
- if (r == null) {
- return "Failed to find PID " + Binder.getCallingPid();
- }
-
- synchronized (mService) {
- return checkContentProviderPermissionLocked(cpi, r, userId, true);
- }
- }
-
- /**
- * Check if {@link ProcessRecord} has a possible chance at accessing the
- * given {@link ProviderInfo}. Final permission checking is always done
- * in {@link ContentProvider}.
- */
- private String checkContentProviderPermissionLocked(
- ProviderInfo cpi, ProcessRecord r, int userId, boolean checkUser) {
- final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
- final int callingUid = (r != null) ? r.uid : Binder.getCallingUid();
- boolean checkedGrants = false;
- if (checkUser) {
- // Looking for cross-user grants before enforcing the typical cross-users permissions
- int tmpTargetUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
- if (tmpTargetUserId != UserHandle.getUserId(callingUid)) {
- if (mService.mUgmInternal.checkAuthorityGrants(
- callingUid, cpi, tmpTargetUserId, checkUser)) {
- return null;
- }
- checkedGrants = true;
- }
- userId = mService.mUserController.handleIncomingUser(callingPid, callingUid, userId,
- false, ActivityManagerInternal.ALLOW_NON_FULL,
- "checkContentProviderPermissionLocked " + cpi.authority, null);
- if (userId != tmpTargetUserId) {
- // When we actually went to determine the final targer user ID, this ended
- // up different than our initial check for the authority. This is because
- // they had asked for USER_CURRENT_OR_SELF and we ended up switching to
- // SELF. So we need to re-check the grants again.
- checkedGrants = false;
- }
- }
- if (ActivityManagerService.checkComponentPermission(cpi.readPermission,
- callingPid, callingUid, cpi.applicationInfo.uid, cpi.exported)
- == PackageManager.PERMISSION_GRANTED) {
- return null;
- }
- if (ActivityManagerService.checkComponentPermission(cpi.writePermission,
- callingPid, callingUid, cpi.applicationInfo.uid, cpi.exported)
- == PackageManager.PERMISSION_GRANTED) {
- return null;
- }
-
- PathPermission[] pps = cpi.pathPermissions;
- if (pps != null) {
- int i = pps.length;
- while (i > 0) {
- i--;
- PathPermission pp = pps[i];
- String pprperm = pp.getReadPermission();
- if (pprperm != null && ActivityManagerService.checkComponentPermission(pprperm,
- callingPid, callingUid, cpi.applicationInfo.uid, cpi.exported)
- == PackageManager.PERMISSION_GRANTED) {
- return null;
- }
- String ppwperm = pp.getWritePermission();
- if (ppwperm != null && ActivityManagerService.checkComponentPermission(ppwperm,
- callingPid, callingUid, cpi.applicationInfo.uid, cpi.exported)
- == PackageManager.PERMISSION_GRANTED) {
- return null;
- }
- }
- }
- if (!checkedGrants
- && mService.mUgmInternal.checkAuthorityGrants(callingUid, cpi, userId, checkUser)) {
- return null;
- }
-
- final String suffix;
- if (!cpi.exported) {
- suffix = " that is not exported from UID " + cpi.applicationInfo.uid;
- } else if (android.Manifest.permission.MANAGE_DOCUMENTS.equals(cpi.readPermission)) {
- suffix = " requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs";
- } else {
- suffix = " requires " + cpi.readPermission + " or " + cpi.writePermission;
- }
- final String msg = "Permission Denial: opening provider " + cpi.name
- + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
- + ", uid=" + callingUid + ")" + suffix;
- Slog.w(TAG, msg);
- return msg;
- }
-
- private String checkContentProviderAssociation(ProcessRecord callingApp, int callingUid,
- ProviderInfo cpi) {
- if (callingApp == null) {
- return mService.validateAssociationAllowedLocked(cpi.packageName,
- cpi.applicationInfo.uid, null, callingUid) ? null : "<null>";
- }
- for (int i = callingApp.pkgList.size() - 1; i >= 0; i--) {
- if (!mService.validateAssociationAllowedLocked(callingApp.pkgList.keyAt(i),
- callingApp.uid, cpi.packageName, cpi.applicationInfo.uid)) {
- return cpi.packageName;
- }
- }
- return null;
- }
-
- void removeContentProviderExternalAsUser(String name, IBinder token, int userId) {
- mService.enforceCallingPermission(
- android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
- "Do not have permission in call removeContentProviderExternal()");
- long ident = Binder.clearCallingIdentity();
- try {
- removeContentProviderExternalUnchecked(name, token, userId);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- void removeContentProviderExternalUnchecked(String name, IBinder token, int userId) {
- synchronized (mService) {
- ContentProviderRecord cpr = mProviderMap.getProviderByName(name, userId);
- if (cpr == null) {
- //remove from mProvidersByClass
- if (ActivityManagerDebugConfig.DEBUG_ALL) {
- Slog.v(TAG, name + " content provider not found in providers list");
- }
- return;
- }
-
- // update content provider record entry info
- ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
- ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp, userId);
- if (localCpr.hasExternalProcessHandles()) {
- if (localCpr.removeExternalProcessHandleLocked(token)) {
- mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER);
- } else {
- Slog.e(TAG, "Attmpt to remove content provider " + localCpr
- + " with no external reference for token: "
- + token + ".");
- }
- } else {
- Slog.e(TAG, "Attmpt to remove content provider: " + localCpr
- + " with no external references.");
- }
- }
- }
-
- public boolean refContentProvider(IBinder connection, int stable, int unstable) {
- ContentProviderConnection conn;
- try {
- conn = (ContentProviderConnection) connection;
- } catch (ClassCastException e) {
- String msg = "refContentProvider: " + connection + " not a ContentProviderConnection";
- Slog.w(TAG, msg);
- throw new IllegalArgumentException(msg);
- }
- if (conn == null) {
- throw new NullPointerException("connection is null");
- }
-
- conn.adjustCounts(stable, unstable);
- return !conn.dead;
- }
-
- public void unstableProviderDied(IBinder connection) {
- ContentProviderConnection conn;
- try {
- conn = (ContentProviderConnection) connection;
- } catch (ClassCastException e) {
- String msg = "refContentProvider: " + connection + " not a ContentProviderConnection";
- Slog.w(TAG, msg);
- throw new IllegalArgumentException(msg);
- }
- if (conn == null) {
- throw new NullPointerException("connection is null");
- }
-
- // Safely retrieve the content provider associated with the connection.
- IContentProvider provider;
- synchronized (mService) {
- provider = conn.provider.provider;
- }
-
- if (provider == null) {
- // Um, yeah, we're way ahead of you.
- return;
- }
-
- // Make sure the caller is being honest with us.
- if (provider.asBinder().pingBinder()) {
- // Er, no, still looks good to us.
- synchronized (mService) {
- Slog.w(TAG, "unstableProviderDied: caller " + Binder.getCallingUid()
- + " says " + conn + " died, but we don't agree");
- return;
- }
- }
-
- // Well look at that! It's dead!
- synchronized (mService) {
- if (conn.provider.provider != provider) {
- // But something changed... good enough.
- return;
- }
-
- ProcessRecord proc = conn.provider.proc;
- if (proc == null || proc.thread == null) {
- // Seems like the process is already cleaned up.
- return;
- }
-
- // As far as we're concerned, this is just like receiving a
- // death notification... just a bit prematurely.
- mService.reportUidInfoMessageLocked(TAG,
- "Process " + proc.processName + " (pid " + proc.pid
- + ") early provider death",
- proc.info.uid);
- final long ident = Binder.clearCallingIdentity();
- try {
- mService.appDiedLocked(proc, "unstable content provider");
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
-
- public void appNotRespondingViaProvider(IBinder connection) {
- mService.enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
- "appNotRespondingViaProvider()");
-
- final ContentProviderConnection conn = (ContentProviderConnection) connection;
- if (conn == null) {
- Slog.w(TAG, "ContentProviderConnection is null");
- return;
- }
-
- final ProcessRecord host = conn.provider.proc;
- if (host == null) {
- Slog.w(TAG, "Failed to find hosting ProcessRecord");
- return;
- }
-
- mService.mAnrHelper.appNotResponding(host, "ContentProvider not responding");
- }
-
- /**
- * Allows apps to retrieve the MIME type of a URI.
- * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
- * users, then it does not need permission to access the ContentProvider.
- * Either, it needs cross-user uri grants.
- *
- * CTS tests for this functionality can be run with "runtest cts-appsecurity".
- *
- * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
- * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
- *
- * @deprecated -- use getProviderMimeTypeAsync.
- */
- @Deprecated
- public String getProviderMimeType(Uri uri, int userId) {
- mService.enforceNotIsolatedCaller("getProviderMimeType");
- final String name = uri.getAuthority();
- int callingUid = Binder.getCallingUid();
- int callingPid = Binder.getCallingPid();
- long ident = 0;
- boolean clearedIdentity = false;
- userId = mService.mUserController.unsafeConvertIncomingUser(userId);
- if (canClearIdentity(callingPid, callingUid, userId)) {
- clearedIdentity = true;
- ident = Binder.clearCallingIdentity();
- }
- ContentProviderHolder holder = null;
- try {
- holder = getContentProviderExternalUnchecked(name, null, callingUid,
- "*getmimetype*", userId);
- if (holder != null) {
- final IBinder providerConnection = holder.connection;
- final ComponentName providerName = holder.info.getComponentName();
- // Note: creating a new Runnable instead of using a lambda here since lambdas in
- // java provide no guarantee that there will be a new instance returned every call.
- // Hence, it's possible that a cached copy is returned and the ANR is executed on
- // the incorrect provider.
- final Runnable providerNotResponding = new Runnable() {
- @Override
- public void run() {
- Log.w(TAG, "Provider " + providerName + " didn't return from getType().");
- appNotRespondingViaProvider(providerConnection);
- }
- };
- mService.mHandler.postDelayed(providerNotResponding, 1000);
- try {
- return holder.provider.getType(uri);
- } finally {
- mService.mHandler.removeCallbacks(providerNotResponding);
- }
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Content provider dead retrieving " + uri, e);
- return null;
- } catch (Exception e) {
- Log.w(TAG, "Exception while determining type of " + uri, e);
- return null;
- } finally {
- // We need to clear the identity to call removeContentProviderExternalUnchecked
- if (!clearedIdentity) {
- ident = Binder.clearCallingIdentity();
- }
- try {
- if (holder != null) {
- removeContentProviderExternalUnchecked(name, null, userId);
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- return null;
- }
-
- /**
- * Allows apps to retrieve the MIME type of a URI.
- * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
- * users, then it does not need permission to access the ContentProvider.
- * Either way, it needs cross-user uri grants.
- */
- public void getProviderMimeTypeAsync(Uri uri, int userId, RemoteCallback resultCallback) {
- mService.enforceNotIsolatedCaller("getProviderMimeTypeAsync");
- final String name = uri.getAuthority();
- final int callingUid = Binder.getCallingUid();
- final int callingPid = Binder.getCallingPid();
- final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
- final long ident = canClearIdentity(callingPid, callingUid, userId)
- ? Binder.clearCallingIdentity() : 0;
- try {
- final ContentProviderHolder holder = getContentProviderExternalUnchecked(name, null,
- callingUid, "*getmimetype*", safeUserId);
- if (holder != null) {
- holder.provider.getTypeAsync(uri, new RemoteCallback(result -> {
- final long identity = Binder.clearCallingIdentity();
- try {
- removeContentProviderExternalUnchecked(name, null, safeUserId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- resultCallback.sendResult(result);
- }));
- } else {
- resultCallback.sendResult(Bundle.EMPTY);
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Content provider dead retrieving " + uri, e);
- resultCallback.sendResult(Bundle.EMPTY);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
- private boolean canClearIdentity(int callingPid, int callingUid, int userId) {
- if (UserHandle.getUserId(callingUid) == userId) {
- return true;
- }
- if (ActivityManagerService.checkComponentPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS, callingPid,
- callingUid, -1, true) == PackageManager.PERMISSION_GRANTED
- || ActivityManagerService.checkComponentPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingPid,
- callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
- return true;
- }
- return false;
- }
-
- int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) {
- if (Thread.holdsLock(mService.mActivityTaskManager.getGlobalLock())) {
- Slog.wtf(TAG, new IllegalStateException("Unable to check Uri permission"
- + " because caller is holding WM lock; assuming permission denied"));
- return PackageManager.PERMISSION_DENIED;
- }
-
- final String name = uri.getAuthority();
- final long ident = Binder.clearCallingIdentity();
- ContentProviderHolder holder = null;
- try {
- holder = getContentProviderExternalUnchecked(name, null, callingUid,
- "*checkContentProviderUriPermission*", userId);
- if (holder != null) {
- return holder.provider.checkUriPermission(null, null, uri, callingUid, modeFlags);
- }
- } catch (RemoteException e) {
- Log.w(TAG, "Content provider dead retrieving " + uri, e);
- return PackageManager.PERMISSION_DENIED;
- } catch (Exception e) {
- Log.w(TAG, "Exception while determining type of " + uri, e);
- return PackageManager.PERMISSION_DENIED;
- } finally {
- try {
- if (holder != null) {
- removeContentProviderExternalUnchecked(name, null, userId);
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- return PackageManager.PERMISSION_DENIED;
- }
-
- /**
- * Drop a content provider from a ProcessRecord's bookkeeping
- */
- void removeContentProvider(IBinder connection, boolean stable) {
- mService.enforceNotIsolatedCaller("removeContentProvider");
- long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mService) {
- ContentProviderConnection conn;
- try {
- conn = (ContentProviderConnection) connection;
- } catch (ClassCastException e) {
- String msg = "removeContentProvider: " + connection
- + " not a ContentProviderConnection";
- Slog.w(TAG, msg);
- throw new IllegalArgumentException(msg);
- }
- if (conn == null) {
- throw new NullPointerException("connection is null");
- }
- if (decProviderCountLocked(conn, null, null, stable)) {
- mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
ContentProviderHolder getContentProvider(IApplicationThread caller, String callingPackage,
String name, int userId, boolean stable) {
mService.enforceNotIsolatedCaller("getContentProvider");
@@ -767,6 +116,24 @@ public class ContentProviderHelper {
null, stable, userId);
}
+ ContentProviderHolder getContentProviderExternal(
+ String name, int userId, IBinder token, String tag) {
+ mService.enforceCallingPermission(
+ android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
+ "Do not have permission in call getContentProviderExternal()");
+ userId = mService.mUserController.handleIncomingUser(
+ Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ false, ActivityManagerInternal.ALLOW_FULL_ONLY, "getContentProvider", null);
+ return getContentProviderExternalUnchecked(name, token, Binder.getCallingUid(),
+ tag != null ? tag : "*external*", userId);
+ }
+
+ ContentProviderHolder getContentProviderExternalUnchecked(String name,
+ IBinder token, int callingUid, String callingTag, int userId) {
+ return getContentProviderImpl(null, name, token, callingUid, null, callingTag,
+ true, userId);
+ }
+
private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
String name, IBinder token, int callingUid, String callingPackage, String callingTag,
boolean stable, int userId) {
@@ -799,10 +166,10 @@ public class ContentProviderHelper {
cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM);
if (cpr != null) {
cpi = cpr.info;
- if (mService.isSingleton(cpi.processName, cpi.applicationInfo,
- cpi.name, cpi.flags)
- && mService.isValidSingletonCall(r == null ? callingUid : r.uid,
- cpi.applicationInfo.uid)) {
+ if (mService.isSingleton(
+ cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags)
+ && mService.isValidSingletonCall(
+ r == null ? callingUid : r.uid, cpi.applicationInfo.uid)) {
userId = UserHandle.USER_SYSTEM;
checkCrossUser = false;
} else {
@@ -852,25 +219,24 @@ public class ContentProviderHelper {
// 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);
- // don't give caller the provider object, it needs
- // to make its own.
+ // don't give caller the provider object, it needs to make its own.
holder.provider = null;
- return holder; //what?
+ return holder;
}
// Don't expose providers between normal apps and instant apps
try {
if (AppGlobals.getPackageManager()
- .resolveContentProvider(name, 0 /*flags*/, userId) == null) {
+ .resolveContentProvider(name, /*flags=*/ 0, userId) == null) {
return null;
}
} catch (RemoteException e) {
}
if ((msg = checkContentProviderAssociation(r, callingUid, cpi)) != null) {
- throw new SecurityException("Content provider lookup "
- + cpr.name.flattenToShortString()
- + " failed: association not allowed with package " + msg);
+ throw new SecurityException(
+ "Content provider lookup " + cpr.name.flattenToShortString()
+ + " failed: association not allowed with package " + msg);
}
checkTime(startTime,
"getContentProviderImpl: before checkContentProviderPermission");
@@ -918,8 +284,7 @@ public class ContentProviderHelper {
// doesn't kill our process.
Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString()
+ " is crashing; detaching " + r);
- boolean lastRef = decProviderCountLocked(conn, cpr,
- token, stable);
+ boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
if (!lastRef) {
// This wasn't the last ref our process had on
// the provider... we will be killed during cleaning up, bail.
@@ -941,7 +306,8 @@ public class ContentProviderHelper {
checkTime(startTime, "getContentProviderImpl: before resolveContentProvider");
cpi = AppGlobals.getPackageManager().resolveContentProvider(name,
ActivityManagerService.STOCK_PM_FLAGS
- | PackageManager.GET_URI_PERMISSION_PATTERNS, userId);
+ | PackageManager.GET_URI_PERMISSION_PATTERNS,
+ userId);
checkTime(startTime, "getContentProviderImpl: after resolveContentProvider");
} catch (RemoteException ex) {
}
@@ -949,13 +315,12 @@ public class ContentProviderHelper {
return null;
}
// If the provider is a singleton AND
- // (it's a call within the same user || the provider is a
- // privileged app)
+ // (it's a call within the same user || the provider is a privileged app)
// Then allow connecting to the singleton provider
- boolean singleton = mService.isSingleton(cpi.processName, cpi.applicationInfo,
- cpi.name, cpi.flags)
- && mService.isValidSingletonCall(r == null ? callingUid : r.uid,
- cpi.applicationInfo.uid);
+ boolean singleton = mService.isSingleton(
+ cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags)
+ && mService.isValidSingletonCall(
+ r == null ? callingUid : r.uid, cpi.applicationInfo.uid);
if (singleton) {
userId = UserHandle.USER_SYSTEM;
}
@@ -976,8 +341,7 @@ public class ContentProviderHelper {
checkTime(startTime,
"getContentProviderImpl: after checkContentProviderPermission");
- if (!mService.mProcessesReady
- && !cpi.processName.equals("system")) {
+ if (!mService.mProcessesReady && !cpi.processName.equals("system")) {
// If this content provider does not run in the system
// process, and the system is not yet ready to run other
// processes, then fail fast instead of hanging.
@@ -997,9 +361,8 @@ public class ContentProviderHelper {
// we don't want to allow it to run.
if (!mService.mUserController.isUserRunning(userId, 0)) {
Slog.w(TAG, "Unable to launch app "
- + cpi.applicationInfo.packageName + "/"
- + cpi.applicationInfo.uid + " for provider "
- + name + ": user " + userId + " is stopped");
+ + cpi.applicationInfo.packageName + "/" + cpi.applicationInfo.uid
+ + " for provider " + name + ": user " + userId + " is stopped");
return null;
}
@@ -1015,7 +378,7 @@ public class ContentProviderHelper {
// we return no provider and launch a review activity if the calling app
// is in the foreground.
if (!requestTargetProviderPermissionsReviewIfNeededLocked(
- cpi, r, userId, mService.mContext)) {
+ cpi, r, userId, mService.mContext)) {
return null;
}
@@ -1062,19 +425,17 @@ public class ContentProviderHelper {
}
// This is single process, and our app is now connecting to it.
- // See if we are already in the process of launching this
- // provider.
- final int N = mLaunchingProviders.size();
+ // See if we are already in the process of launching this provider.
+ final int numLaunchingProviders = mLaunchingProviders.size();
int i;
- for (i = 0; i < N; i++) {
+ for (i = 0; i < numLaunchingProviders; i++) {
if (mLaunchingProviders.get(i) == cpr) {
break;
}
}
- // If the provider is not already being launched, then get it
- // started.
- if (i >= N) {
+ // If the provider is not already being launched, then get it started.
+ if (i >= numLaunchingProviders) {
final long origId = Binder.clearCallingIdentity();
try {
@@ -1109,18 +470,18 @@ public class ContentProviderHelper {
}
} else {
checkTime(startTime, "getContentProviderImpl: before start process");
- proc = mService.startProcessLocked(cpi.processName,
- cpr.appInfo, false, 0,
+ proc = mService.startProcessLocked(
+ cpi.processName, cpr.appInfo, false, 0,
new HostingRecord("content provider",
- new ComponentName(cpi.applicationInfo.packageName,
- cpi.name)),
- ZYGOTE_POLICY_FLAG_EMPTY, false, false, false);
+ new ComponentName(
+ cpi.applicationInfo.packageName, cpi.name)),
+ Process.ZYGOTE_POLICY_FLAG_EMPTY, false, false, false);
checkTime(startTime, "getContentProviderImpl: after start process");
if (proc == null) {
Slog.w(TAG, "Unable to launch app "
+ cpi.applicationInfo.packageName + "/"
- + cpi.applicationInfo.uid + " for provider "
- + name + ": process is bad");
+ + cpi.applicationInfo.uid + " for provider " + name
+ + ": process is bad");
return null;
}
}
@@ -1148,7 +509,7 @@ public class ContentProviderHelper {
}
checkTime(startTime, "getContentProviderImpl: done!");
- mService.grantImplicitAccess(userId, null /*intent*/, callingUid,
+ mService.grantImplicitAccess(userId, null, callingUid,
UserHandle.getAppId(cpi.applicationInfo.uid));
}
@@ -1160,13 +521,11 @@ public class ContentProviderHelper {
while (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");
+ + 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);
+ cpi.applicationInfo.packageName, cpi.applicationInfo.uid, name);
return null;
}
try {
@@ -1205,73 +564,15 @@ public class ContentProviderHelper {
}
Slog.wtf(TAG, "Timeout waiting for provider "
- + cpi.applicationInfo.packageName + "/"
- + cpi.applicationInfo.uid + " for provider " + name
- + " providerRunning=" + providerRunning
+ + cpi.applicationInfo.packageName + "/" + cpi.applicationInfo.uid
+ + " for provider " + name + " providerRunning=" + providerRunning
+ " caller=" + callerName + "/" + Binder.getCallingUid());
return null;
}
return cpr.newHolder(conn);
}
- ContentProviderHolder getContentProviderExternal(
- String name, int userId, IBinder token, String tag) {
- mService.enforceCallingPermission(
- android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
- "Do not have permission in call getContentProviderExternal()");
- userId = mService.mUserController.handleIncomingUser(
- Binder.getCallingPid(), Binder.getCallingUid(), userId,
- false, ActivityManagerInternal.ALLOW_FULL_ONLY, "getContentProvider", null);
- return getContentProviderExternalUnchecked(name, token, Binder.getCallingUid(),
- tag != null ? tag : "*external*", userId);
- }
-
- ContentProviderHolder getContentProviderExternalUnchecked(String name,
- IBinder token, int callingUid, String callingTag, int userId) {
- return getContentProviderImpl(null, name, token, callingUid, null, callingTag,
- true, userId);
- }
-
- private static final int[] PROCESS_STATE_STATS_FORMAT = new int[] {
- PROC_SPACE_TERM,
- PROC_SPACE_TERM | PROC_PARENS,
- PROC_SPACE_TERM | PROC_CHAR | PROC_OUT_LONG, // 3: process state
- };
-
- private final long[] mProcessStateStatsLongs = new long[1];
-
- private boolean isProcessAliveLocked(ProcessRecord proc) {
- if (proc.pid <= 0) {
- if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
- Slog.d(ActivityManagerService.TAG, "Process hasn't started yet: " + proc);
- }
- return false;
- }
- if (proc.procStatFile == null) {
- proc.procStatFile = "/proc/" + proc.pid + "/stat";
- }
- mProcessStateStatsLongs[0] = 0;
- if (!readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
- mProcessStateStatsLongs, null)) {
- if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
- Slog.d(ActivityManagerService.TAG,
- "UNABLE TO RETRIEVE STATE FOR " + proc.procStatFile);
- }
- return false;
- }
- final long state = mProcessStateStatsLongs[0];
- if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
- Slog.d(ActivityManagerService.TAG,
- "RETRIEVED STATE FOR " + proc.procStatFile + ": " + (char) state);
- }
- if (state != 'Z' && state != 'X' && state != 'x' && state != 'K') {
- return Process.getUidForPid(proc.pid) == proc.uid;
- }
- return false;
- }
-
- public final void publishContentProviders(IApplicationThread caller,
- List<ContentProviderHolder> providers) {
+ void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) {
if (providers == null) {
return;
}
@@ -1290,81 +591,493 @@ public class ContentProviderHelper {
final long origId = Binder.clearCallingIdentity();
- final int N = providers.size();
- for (int i = 0; i < N; i++) {
+ for (int i = 0, size = providers.size(); i < size; i++) {
ContentProviderHolder src = providers.get(i);
if (src == null || src.info == null || src.provider == null) {
continue;
}
ContentProviderRecord dst = r.pubProviders.get(src.info.name);
+ if (dst == null) {
+ continue;
+ }
if (DEBUG_MU) {
Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid);
}
- if (dst != null) {
- ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
- mProviderMap.putProviderByClass(comp, dst);
- String[] names = dst.info.authority.split(";");
- for (int j = 0; j < names.length; j++) {
- mProviderMap.putProviderByName(names[j], dst);
- }
- int launchingCount = mLaunchingProviders.size();
- int j;
- boolean wasInLaunchingProviders = false;
- for (j = 0; j < launchingCount; j++) {
- if (mLaunchingProviders.get(j) == dst) {
- mLaunchingProviders.remove(j);
- wasInLaunchingProviders = true;
- j--;
- launchingCount--;
- }
- }
- if (wasInLaunchingProviders) {
- mService.mHandler.removeMessages(
- ActivityManagerService.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
- }
- // Make sure the package is associated with the process.
- // XXX We shouldn't need to do this, since we have added the package
- // when we generated the providers in generateApplicationProvidersLocked().
- // But for some reason in some cases we get here with the package no longer
- // added... for now just patch it in to make things happy.
- r.addPackage(dst.info.applicationInfo.packageName,
- dst.info.applicationInfo.longVersionCode, mService.mProcessStats);
- synchronized (dst) {
- dst.provider = src.provider;
- dst.setProcess(r);
- dst.notifyAll();
+ ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
+ mProviderMap.putProviderByClass(comp, dst);
+ String[] names = dst.info.authority.split(";");
+ for (int j = 0; j < names.length; j++) {
+ mProviderMap.putProviderByName(names[j], dst);
+ }
+
+ boolean wasInLaunchingProviders = false;
+ for (int j = 0, numLaunching = mLaunchingProviders.size(); j < numLaunching; j++) {
+ if (mLaunchingProviders.get(j) == dst) {
+ mLaunchingProviders.remove(j);
+ wasInLaunchingProviders = true;
+ j--;
+ numLaunching--;
}
- dst.mRestartCount = 0;
- mService.updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
- maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
- src.info.authority);
}
+ if (wasInLaunchingProviders) {
+ mService.mHandler.removeMessages(
+ ActivityManagerService.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
+ }
+ // Make sure the package is associated with the process.
+ // XXX We shouldn't need to do this, since we have added the package
+ // when we generated the providers in generateApplicationProvidersLocked().
+ // But for some reason in some cases we get here with the package no longer
+ // added... for now just patch it in to make things happy.
+ r.addPackage(dst.info.applicationInfo.packageName,
+ dst.info.applicationInfo.longVersionCode, mService.mProcessStats);
+ synchronized (dst) {
+ dst.provider = src.provider;
+ dst.setProcess(r);
+ dst.notifyAll();
+ }
+ dst.mRestartCount = 0;
+ mService.updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER);
+ maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority);
}
Binder.restoreCallingIdentity(origId);
}
}
- private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName,
- String authority) {
- if (app == null) return;
- if (app.getCurProcState() <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- UserState userState = mService.mUserController.getStartedUserState(app.userId);
- if (userState == null) return;
- final long now = SystemClock.elapsedRealtime();
- Long lastReported = userState.mProviderLastReportedFg.get(authority);
- if (lastReported == null || lastReported < now - 60 * 1000L) {
- if (mService.mSystemReady) {
- // Cannot touch the user stats if not system ready
- mService.mUsageStatsService.reportContentProviderUsage(
- authority, providerPkgName, app.userId);
+ /**
+ * Drop a content provider from a ProcessRecord's bookkeeping
+ */
+ void removeContentProvider(IBinder connection, boolean stable) {
+ mService.enforceNotIsolatedCaller("removeContentProvider");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mService) {
+ ContentProviderConnection conn;
+ try {
+ conn = (ContentProviderConnection) connection;
+ } catch (ClassCastException e) {
+ String msg = "removeContentProvider: " + connection
+ + " not a ContentProviderConnection";
+ Slog.w(TAG, msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (conn == null) {
+ throw new NullPointerException("connection is null");
+ }
+ if (decProviderCountLocked(conn, null, null, stable)) {
+ mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ void removeContentProviderExternalAsUser(String name, IBinder token, int userId) {
+ mService.enforceCallingPermission(
+ android.Manifest.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY,
+ "Do not have permission in call removeContentProviderExternal()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ removeContentProviderExternalUnchecked(name, token, userId);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ void removeContentProviderExternalUnchecked(String name, IBinder token, int userId) {
+ synchronized (mService) {
+ ContentProviderRecord cpr = mProviderMap.getProviderByName(name, userId);
+ if (cpr == null) {
+ //remove from mProvidersByClass
+ if (ActivityManagerDebugConfig.DEBUG_ALL) {
+ Slog.v(TAG, name + " content provider not found in providers list");
+ }
+ return;
+ }
+
+ // update content provider record entry info
+ ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
+ ContentProviderRecord localCpr = mProviderMap.getProviderByClass(comp, userId);
+ if (localCpr.hasExternalProcessHandles()) {
+ if (localCpr.removeExternalProcessHandleLocked(token)) {
+ mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER);
+ } else {
+ Slog.e(TAG, "Attempt to remove content provider " + localCpr
+ + " with no external reference for token: " + token + ".");
+ }
+ } else {
+ Slog.e(TAG, "Attempt to remove content provider: " + localCpr
+ + " with no external references.");
+ }
+ }
+ }
+
+ boolean refContentProvider(IBinder connection, int stable, int unstable) {
+ ContentProviderConnection conn;
+ try {
+ conn = (ContentProviderConnection) connection;
+ } catch (ClassCastException e) {
+ String msg = "refContentProvider: " + connection + " not a ContentProviderConnection";
+ Slog.w(TAG, msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (conn == null) {
+ throw new NullPointerException("connection is null");
+ }
+
+ conn.adjustCounts(stable, unstable);
+ return !conn.dead;
+ }
+
+ void unstableProviderDied(IBinder connection) {
+ ContentProviderConnection conn;
+ try {
+ conn = (ContentProviderConnection) connection;
+ } catch (ClassCastException e) {
+ String msg = "refContentProvider: " + connection + " not a ContentProviderConnection";
+ Slog.w(TAG, msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (conn == null) {
+ throw new NullPointerException("connection is null");
+ }
+
+ // Safely retrieve the content provider associated with the connection.
+ IContentProvider provider;
+ synchronized (mService) {
+ provider = conn.provider.provider;
+ }
+
+ if (provider == null) {
+ // Um, yeah, we're way ahead of you.
+ return;
+ }
+
+ // Make sure the caller is being honest with us.
+ if (provider.asBinder().pingBinder()) {
+ // Er, no, still looks good to us.
+ synchronized (mService) {
+ Slog.w(TAG, "unstableProviderDied: caller " + Binder.getCallingUid()
+ + " says " + conn + " died, but we don't agree");
+ return;
+ }
+ }
+
+ // Well look at that! It's dead!
+ synchronized (mService) {
+ if (conn.provider.provider != provider) {
+ // But something changed... good enough.
+ return;
+ }
+
+ ProcessRecord proc = conn.provider.proc;
+ if (proc == null || proc.thread == null) {
+ // Seems like the process is already cleaned up.
+ return;
+ }
+
+ // As far as we're concerned, this is just like receiving a
+ // death notification... just a bit prematurely.
+ mService.reportUidInfoMessageLocked(TAG, "Process " + proc.processName
+ + " (pid " + proc.pid + ") early provider death", proc.info.uid);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mService.appDiedLocked(proc, "unstable content provider");
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
+ void appNotRespondingViaProvider(IBinder connection) {
+ mService.enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS,
+ "appNotRespondingViaProvider()");
+
+ final ContentProviderConnection conn = (ContentProviderConnection) connection;
+ if (conn == null) {
+ Slog.w(TAG, "ContentProviderConnection is null");
+ return;
+ }
+
+ final ProcessRecord host = conn.provider.proc;
+ if (host == null) {
+ Slog.w(TAG, "Failed to find hosting ProcessRecord");
+ return;
+ }
+
+ mService.mAnrHelper.appNotResponding(host, "ContentProvider not responding");
+ }
+
+ /**
+ * Allows apps to retrieve the MIME type of a URI.
+ * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
+ * users, then it does not need permission to access the ContentProvider.
+ * Either, it needs cross-user uri grants.
+ *
+ * CTS tests for this functionality can be run with "runtest cts-appsecurity".
+ *
+ * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
+ * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+ *
+ * @deprecated -- use getProviderMimeTypeAsync.
+ */
+ @Deprecated
+ String getProviderMimeType(Uri uri, int userId) {
+ mService.enforceNotIsolatedCaller("getProviderMimeType");
+ final String name = uri.getAuthority();
+ int callingUid = Binder.getCallingUid();
+ int callingPid = Binder.getCallingPid();
+ long ident = 0;
+ boolean clearedIdentity = false;
+ userId = mService.mUserController.unsafeConvertIncomingUser(userId);
+ if (canClearIdentity(callingPid, callingUid, userId)) {
+ clearedIdentity = true;
+ ident = Binder.clearCallingIdentity();
+ }
+ ContentProviderHolder holder = null;
+ try {
+ holder = getContentProviderExternalUnchecked(name, null, callingUid,
+ "*getmimetype*", userId);
+ if (holder != null) {
+ final IBinder providerConnection = holder.connection;
+ final ComponentName providerName = holder.info.getComponentName();
+ // Note: creating a new Runnable instead of using a lambda here since lambdas in
+ // java provide no guarantee that there will be a new instance returned every call.
+ // Hence, it's possible that a cached copy is returned and the ANR is executed on
+ // the incorrect provider.
+ final Runnable providerNotResponding = new Runnable() {
+ @Override
+ public void run() {
+ Log.w(TAG, "Provider " + providerName + " didn't return from getType().");
+ appNotRespondingViaProvider(providerConnection);
+ }
+ };
+ mService.mHandler.postDelayed(providerNotResponding, 1000);
+ try {
+ return holder.provider.getType(uri);
+ } finally {
+ mService.mHandler.removeCallbacks(providerNotResponding);
+ }
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Content provider dead retrieving " + uri, e);
+ return null;
+ } catch (Exception e) {
+ Log.w(TAG, "Exception while determining type of " + uri, e);
+ return null;
+ } finally {
+ // We need to clear the identity to call removeContentProviderExternalUnchecked
+ if (!clearedIdentity) {
+ ident = Binder.clearCallingIdentity();
+ }
+ try {
+ if (holder != null) {
+ removeContentProviderExternalUnchecked(name, null, userId);
}
- userState.mProviderLastReportedFg.put(authority, now);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Allows apps to retrieve the MIME type of a URI.
+ * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
+ * users, then it does not need permission to access the ContentProvider.
+ * Either way, it needs cross-user uri grants.
+ */
+ void getProviderMimeTypeAsync(Uri uri, int userId, RemoteCallback resultCallback) {
+ mService.enforceNotIsolatedCaller("getProviderMimeTypeAsync");
+ final String name = uri.getAuthority();
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
+ final long ident = canClearIdentity(callingPid, callingUid, userId)
+ ? Binder.clearCallingIdentity() : 0;
+ try {
+ final ContentProviderHolder holder = getContentProviderExternalUnchecked(name, null,
+ callingUid, "*getmimetype*", safeUserId);
+ if (holder != null) {
+ holder.provider.getTypeAsync(uri, new RemoteCallback(result -> {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ removeContentProviderExternalUnchecked(name, null, safeUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ resultCallback.sendResult(result);
+ }));
+ } else {
+ resultCallback.sendResult(Bundle.EMPTY);
}
+ } catch (RemoteException e) {
+ Log.w(TAG, "Content provider dead retrieving " + uri, e);
+ resultCallback.sendResult(Bundle.EMPTY);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private boolean canClearIdentity(int callingPid, int callingUid, int userId) {
+ if (UserHandle.getUserId(callingUid) == userId) {
+ return true;
+ }
+ return ActivityManagerService.checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS, callingPid,
+ callingUid, -1, true) == PackageManager.PERMISSION_GRANTED
+ || ActivityManagerService.checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingPid,
+ callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
+ }
+
+ /**
+ * Check if the calling UID has a possible chance at accessing the provider
+ * at the given authority and user.
+ */
+ String checkContentProviderAccess(String authority, int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ mService.mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG);
+ userId = UserHandle.getCallingUserId();
+ }
+
+ ProviderInfo cpi = null;
+ try {
+ cpi = AppGlobals.getPackageManager().resolveContentProvider(authority,
+ ActivityManagerService.STOCK_PM_FLAGS
+ | PackageManager.GET_URI_PERMISSION_PATTERNS
+ | PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+ userId);
+ } catch (RemoteException ignored) {
+ }
+ if (cpi == null) {
+ return "Failed to find provider " + authority + " for user " + userId
+ + "; expected to find a valid ContentProvider for this authority";
+ }
+
+ ProcessRecord r;
+ synchronized (mService.mPidsSelfLocked) {
+ r = mService.mPidsSelfLocked.get(Binder.getCallingPid());
+ }
+ if (r == null) {
+ return "Failed to find PID " + Binder.getCallingPid();
+ }
+
+ synchronized (mService) {
+ return checkContentProviderPermissionLocked(cpi, r, userId, true);
}
}
+ int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) {
+ if (Thread.holdsLock(mService.mActivityTaskManager.getGlobalLock())) {
+ Slog.wtf(TAG, new IllegalStateException("Unable to check Uri permission"
+ + " because caller is holding WM lock; assuming permission denied"));
+ return PackageManager.PERMISSION_DENIED;
+ }
+
+ final String name = uri.getAuthority();
+ final long ident = Binder.clearCallingIdentity();
+ ContentProviderHolder holder = null;
+ try {
+ holder = getContentProviderExternalUnchecked(name, null, callingUid,
+ "*checkContentProviderUriPermission*", userId);
+ if (holder != null) {
+ return holder.provider.checkUriPermission(null, null, uri, callingUid, modeFlags);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Content provider dead retrieving " + uri, e);
+ return PackageManager.PERMISSION_DENIED;
+ } catch (Exception e) {
+ Log.w(TAG, "Exception while determining type of " + uri, e);
+ return PackageManager.PERMISSION_DENIED;
+ } finally {
+ try {
+ if (holder != null) {
+ removeContentProviderExternalUnchecked(name, null, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ return PackageManager.PERMISSION_DENIED;
+ }
+
+ @GuardedBy("mService")
+ void processContentProviderPublishTimedOutLocked(ProcessRecord app) {
+ cleanupAppInLaunchingProvidersLocked(app, true);
+ mService.mProcessList.removeProcessLocked(app, false, true,
+ ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
+ ApplicationExitInfo.SUBREASON_UNKNOWN,
+ "timeout publishing content providers");
+ }
+
+ List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
+ final List<ProviderInfo> providers;
+ try {
+ providers = AppGlobals.getPackageManager().queryContentProviders(
+ app.processName, app.uid, ActivityManagerService.STOCK_PM_FLAGS
+ | PackageManager.GET_URI_PERMISSION_PATTERNS
+ | PackageManager.MATCH_DIRECT_BOOT_AUTO, /*metaDataKey=*/ null)
+ .getList();
+ } catch (RemoteException ex) {
+ return null;
+ }
+ if (providers == null) {
+ return null;
+ }
+
+ if (DEBUG_MU) {
+ Slog.v(TAG_MU, "generateApplicationProvidersLocked, app.info.uid = " + app.uid);
+ }
+
+ int numProviders = providers.size();
+ app.pubProviders.ensureCapacity(numProviders + app.pubProviders.size());
+ for (int i = 0; i < numProviders; i++) {
+ // NOTE: keep logic in sync with installEncryptionUnawareProviders
+ ProviderInfo cpi = providers.get(i);
+ boolean singleton = mService.isSingleton(cpi.processName, cpi.applicationInfo,
+ cpi.name, cpi.flags);
+ if (singleton && app.userId != UserHandle.USER_SYSTEM) {
+ // This is a singleton provider, but a user besides the
+ // default user is asking to initialize a process it runs
+ // in... well, no, it doesn't actually run in this process,
+ // it runs in the process of the default user. Get rid of it.
+ providers.remove(i);
+ numProviders--;
+ i--;
+ continue;
+ }
+
+ ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
+ ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, app.userId);
+ if (cpr == null) {
+ cpr = new ContentProviderRecord(mService, cpi, app.info, comp, singleton);
+ mProviderMap.putProviderByClass(comp, cpr);
+ }
+ if (DEBUG_MU) {
+ Slog.v(TAG_MU, "generateApplicationProvidersLocked, cpi.uid = " + cpr.uid);
+ }
+ app.pubProviders.put(cpi.name, cpr);
+ if (!cpi.multiprocess || !"android".equals(cpi.packageName)) {
+ // Don't add this if it is a platform component that is marked
+ // to run in multiple processes, because this is actually
+ // part of the framework so doesn't make sense to track as a
+ // separate apk in the process.
+ app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.longVersionCode,
+ mService.mProcessStats);
+ }
+ mService.notifyPackageUse(cpi.applicationInfo.packageName,
+ PackageManager.NOTIFY_PACKAGE_USE_CONTENT_PROVIDER);
+ }
+ return providers;
+ }
+
private final class DevelopmentSettingsObserver extends ContentObserver {
private final Uri mUri = Settings.Global.getUriFor(
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED);
@@ -1428,11 +1141,8 @@ public class ContentProviderHelper {
SettingsToPropertiesMapper.start(mService.mContext.getContentResolver());
mService.mOomAdjuster.initSettings();
- // Now that the settings provider is published we can consider sending
- // in a rescue party.
+ // Now that the settings provider is published we can consider sending in a rescue party.
RescueParty.onSettingsProviderPublished(mService.mContext);
-
- //mUsageStatsService.monitorPackages();
}
/**
@@ -1447,29 +1157,28 @@ public class ContentProviderHelper {
PackageManager.GET_PROVIDERS | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
synchronized (mService) {
- final int NP = mService.mProcessList.mProcessNames.getMap().size();
- for (int ip = 0; ip < NP; ip++) {
+ final int numProc = mService.mProcessList.mProcessNames.getMap().size();
+ for (int iProc = 0; iProc < numProc; iProc++) {
final SparseArray<ProcessRecord> apps =
- mService.mProcessList.mProcessNames.getMap().valueAt(ip);
- final int NA = apps.size();
- for (int ia = 0; ia < NA; ia++) {
- final ProcessRecord app = apps.valueAt(ia);
+ mService.mProcessList.mProcessNames.getMap().valueAt(iProc);
+ for (int iApp = 0, numApps = apps.size(); iApp < numApps; iApp++) {
+ final ProcessRecord app = apps.valueAt(iApp);
if (app.userId != userId || app.thread == null || app.unlocked) continue;
- final int NG = app.pkgList.size();
- for (int ig = 0; ig < NG; ig++) {
+ for (int iPkg = 0, numPkgs = app.pkgList.size(); iPkg < numPkgs; iPkg++) {
try {
- final String pkgName = app.pkgList.keyAt(ig);
+ final String pkgName = app.pkgList.keyAt(iPkg);
final PackageInfo pkgInfo = AppGlobals.getPackageManager()
.getPackageInfo(pkgName, matchFlags, userId);
if (pkgInfo != null && !ArrayUtils.isEmpty(pkgInfo.providers)) {
for (ProviderInfo pi : pkgInfo.providers) {
- // TODO: keep in sync with generateApplicationProvidersLocked
- final boolean processMatch = Objects.equals(pi.processName,
- app.processName) || pi.multiprocess;
- final boolean userMatch = mService.isSingleton(pi.processName,
- pi.applicationInfo, pi.name, pi.flags)
- ? (app.userId == UserHandle.USER_SYSTEM) : true;
+ // NOTE: keep in sync with generateApplicationProvidersLocked
+ final boolean processMatch =
+ Objects.equals(pi.processName, app.processName)
+ || pi.multiprocess;
+ final boolean userMatch = !mService.isSingleton(
+ pi.processName, pi.applicationInfo, pi.name, pi.flags)
+ || app.userId == UserHandle.USER_SYSTEM;
if (processMatch && userMatch) {
Log.v(TAG, "Installing " + pi);
app.thread.scheduleInstallProvider(pi);
@@ -1486,6 +1195,296 @@ public class ContentProviderHelper {
}
}
+ @GuardedBy("mService")
+ private ContentProviderConnection incProviderCountLocked(ProcessRecord r,
+ final ContentProviderRecord cpr, IBinder externalProcessToken, int callingUid,
+ String callingPackage, String callingTag, boolean stable, boolean updateLru,
+ long startTime, ProcessList processList) {
+ if (r == null) {
+ cpr.addExternalProcessHandleLocked(externalProcessToken, callingUid, callingTag);
+ return null;
+ }
+
+
+ for (int i = 0, size = r.conProviders.size(); i < size; i++) {
+ ContentProviderConnection conn = r.conProviders.get(i);
+ if (conn.provider == cpr) {
+ conn.incrementCount(stable);
+ return conn;
+ }
+ }
+
+ // Create a new ContentProviderConnection. The reference count is known to be 1.
+ ContentProviderConnection conn = new ContentProviderConnection(cpr, r, callingPackage);
+ conn.startAssociationIfNeeded();
+ conn.initializeCount(stable);
+ cpr.connections.add(conn);
+ r.conProviders.add(conn);
+ mService.startAssociationLocked(r.uid, r.processName, r.getCurProcState(),
+ cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
+ if (updateLru && cpr.proc != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) {
+ // If this is a perceptible app accessing the provider, make
+ // sure to count it as being accessed and thus back up on
+ // the LRU list. This is good because content providers are
+ // often expensive to start. The calls to checkTime() use
+ // the "getContentProviderImpl" tag here, because it's part
+ // of the checktime log in getContentProviderImpl().
+ checkTime(startTime, "getContentProviderImpl: before updateLruProcess");
+ processList.updateLruProcessLocked(cpr.proc, false, null);
+ checkTime(startTime, "getContentProviderImpl: after updateLruProcess");
+ }
+ return conn;
+ }
+
+ @GuardedBy("mService")
+ private boolean decProviderCountLocked(ContentProviderConnection conn,
+ ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
+ if (conn == null) {
+ cpr.removeExternalProcessHandleLocked(externalProcessToken);
+ return false;
+ }
+ if (conn.decrementCount(stable) != 0) {
+ return false;
+ }
+
+ cpr = conn.provider;
+ conn.stopAssociation();
+ cpr.connections.remove(conn);
+ conn.client.conProviders.remove(conn);
+ if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
+ // The client is more important than last activity -- note the time this
+ // is happening, so we keep the old provider process around a bit as last
+ // activity to avoid thrashing it.
+ if (cpr.proc != null) {
+ cpr.proc.lastProviderTime = SystemClock.uptimeMillis();
+ }
+ }
+ mService.stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid,
+ cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
+ return true;
+ }
+
+ /**
+ * Check if {@link ProcessRecord} has a possible chance at accessing the
+ * given {@link ProviderInfo}. Final permission checking is always done
+ * in {@link ContentProvider}.
+ */
+ private String checkContentProviderPermissionLocked(ProviderInfo cpi, ProcessRecord r,
+ int userId, boolean checkUser) {
+ final int callingPid = (r != null) ? r.pid : Binder.getCallingPid();
+ final int callingUid = (r != null) ? r.uid : Binder.getCallingUid();
+ boolean checkedGrants = false;
+ if (checkUser) {
+ // Looking for cross-user grants before enforcing the typical cross-users permissions
+ int tmpTargetUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
+ if (tmpTargetUserId != UserHandle.getUserId(callingUid)) {
+ if (mService.mUgmInternal.checkAuthorityGrants(
+ callingUid, cpi, tmpTargetUserId, checkUser)) {
+ return null;
+ }
+ checkedGrants = true;
+ }
+ userId = mService.mUserController.handleIncomingUser(callingPid, callingUid, userId,
+ false, ActivityManagerInternal.ALLOW_NON_FULL,
+ "checkContentProviderPermissionLocked " + cpi.authority, null);
+ if (userId != tmpTargetUserId) {
+ // When we actually went to determine the final target user ID, this ended
+ // up different than our initial check for the authority. This is because
+ // they had asked for USER_CURRENT_OR_SELF and we ended up switching to
+ // SELF. So we need to re-check the grants again.
+ checkedGrants = false;
+ }
+ }
+ if (ActivityManagerService.checkComponentPermission(cpi.readPermission,
+ callingPid, callingUid, cpi.applicationInfo.uid, cpi.exported)
+ == PackageManager.PERMISSION_GRANTED) {
+ return null;
+ }
+ if (ActivityManagerService.checkComponentPermission(cpi.writePermission,
+ callingPid, callingUid, cpi.applicationInfo.uid, cpi.exported)
+ == PackageManager.PERMISSION_GRANTED) {
+ return null;
+ }
+
+ PathPermission[] pps = cpi.pathPermissions;
+ if (pps != null) {
+ int i = pps.length;
+ while (i > 0) {
+ i--;
+ PathPermission pp = pps[i];
+ String pprperm = pp.getReadPermission();
+ if (pprperm != null && ActivityManagerService.checkComponentPermission(pprperm,
+ callingPid, callingUid, cpi.applicationInfo.uid, cpi.exported)
+ == PackageManager.PERMISSION_GRANTED) {
+ return null;
+ }
+ String ppwperm = pp.getWritePermission();
+ if (ppwperm != null && ActivityManagerService.checkComponentPermission(ppwperm,
+ callingPid, callingUid, cpi.applicationInfo.uid, cpi.exported)
+ == PackageManager.PERMISSION_GRANTED) {
+ return null;
+ }
+ }
+ }
+ if (!checkedGrants
+ && mService.mUgmInternal.checkAuthorityGrants(callingUid, cpi, userId, checkUser)) {
+ return null;
+ }
+
+ final String suffix;
+ if (!cpi.exported) {
+ suffix = " that is not exported from UID " + cpi.applicationInfo.uid;
+ } else if (android.Manifest.permission.MANAGE_DOCUMENTS.equals(cpi.readPermission)) {
+ suffix = " requires that you obtain access using ACTION_OPEN_DOCUMENT or related APIs";
+ } else {
+ suffix = " requires " + cpi.readPermission + " or " + cpi.writePermission;
+ }
+ final String msg = "Permission Denial: opening provider " + cpi.name
+ + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")" + suffix;
+ Slog.w(TAG, msg);
+ return msg;
+ }
+
+ private String checkContentProviderAssociation(ProcessRecord callingApp, int callingUid,
+ ProviderInfo cpi) {
+ if (callingApp == null) {
+ return mService.validateAssociationAllowedLocked(cpi.packageName,
+ cpi.applicationInfo.uid, null, callingUid) ? null : "<null>";
+ }
+ for (int i = callingApp.pkgList.size() - 1; i >= 0; i--) {
+ if (!mService.validateAssociationAllowedLocked(callingApp.pkgList.keyAt(i),
+ callingApp.uid, cpi.packageName, cpi.applicationInfo.uid)) {
+ return cpi.packageName;
+ }
+ }
+ return null;
+ }
+
+ ProviderInfo getProviderInfoLocked(String authority, @UserIdInt int userId, int pmFlags) {
+ ProviderInfo pi = null;
+ ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userId);
+ if (cpr != null) {
+ pi = cpr.info;
+ } else {
+ try {
+ pi = AppGlobals.getPackageManager().resolveContentProvider(
+ authority, PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userId);
+ } catch (RemoteException ex) {
+ }
+ }
+ return pi;
+ }
+
+ private void maybeUpdateProviderUsageStatsLocked(ProcessRecord app, String providerPkgName,
+ String authority) {
+ if (app == null
+ || app.getCurProcState() > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+ return;
+ }
+
+
+ UserState userState = mService.mUserController.getStartedUserState(app.userId);
+ if (userState == null) return;
+ final long now = SystemClock.elapsedRealtime();
+ Long lastReported = userState.mProviderLastReportedFg.get(authority);
+ if (lastReported == null || lastReported < now - 60 * 1000L) {
+ if (mService.mSystemReady) {
+ // Cannot touch the user stats if not system ready
+ mService.mUsageStatsService.reportContentProviderUsage(
+ authority, providerPkgName, app.userId);
+ }
+ userState.mProviderLastReportedFg.put(authority, now);
+ }
+ }
+
+ private static final int[] PROCESS_STATE_STATS_FORMAT = new int[] {
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM | PROC_PARENS,
+ PROC_SPACE_TERM | PROC_CHAR | PROC_OUT_LONG, // 3: process state
+ };
+
+ private final long[] mProcessStateStatsLongs = new long[1];
+
+ private boolean isProcessAliveLocked(ProcessRecord proc) {
+ if (proc.pid <= 0) {
+ if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
+ Slog.d(ActivityManagerService.TAG, "Process hasn't started yet: " + proc);
+ }
+ return false;
+ }
+ if (proc.procStatFile == null) {
+ proc.procStatFile = "/proc/" + proc.pid + "/stat";
+ }
+ mProcessStateStatsLongs[0] = 0;
+ if (!Process.readProcFile(proc.procStatFile, PROCESS_STATE_STATS_FORMAT, null,
+ mProcessStateStatsLongs, null)) {
+ if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
+ Slog.d(ActivityManagerService.TAG,
+ "UNABLE TO RETRIEVE STATE FOR " + proc.procStatFile);
+ }
+ return false;
+ }
+ final long state = mProcessStateStatsLongs[0];
+ if (ActivityManagerDebugConfig.DEBUG_OOM_ADJ) {
+ Slog.d(ActivityManagerService.TAG,
+ "RETRIEVED STATE FOR " + proc.procStatFile + ": " + (char) state);
+ }
+ if (state != 'Z' && state != 'X' && state != 'x' && state != 'K') {
+ return Process.getUidForPid(proc.pid) == proc.uid;
+ }
+ return false;
+ }
+
+ private static final class StartActivityRunnable implements Runnable {
+ private final Context mContext;
+ private final Intent mIntent;
+ private final UserHandle mUserHandle;
+
+ StartActivityRunnable(Context context, Intent intent, UserHandle userHandle) {
+ this.mContext = context;
+ this.mIntent = intent;
+ this.mUserHandle = userHandle;
+ }
+
+ @Override
+ public void run() {
+ mContext.startActivityAsUser(mIntent, mUserHandle);
+ }
+ }
+
+ private boolean requestTargetProviderPermissionsReviewIfNeededLocked(ProviderInfo cpi,
+ ProcessRecord r, final int userId, Context context) {
+ if (!mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
+ cpi.packageName, userId)) {
+ return true;
+ }
+
+ final boolean callerForeground = r == null
+ || r.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
+
+ // Show a permission review UI only for starting from a foreground app
+ if (!callerForeground) {
+ Slog.w(TAG, "u" + userId + " Instantiating a provider in package "
+ + cpi.packageName + " requires a permissions review");
+ return false;
+ }
+
+ final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, cpi.packageName);
+
+ if (ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW) {
+ Slog.i(TAG, "u" + userId + " Launching permission review "
+ + "for package " + cpi.packageName);
+ }
+
+ final UserHandle userHandle = new UserHandle(userId);
+ mService.mHandler.post(new StartActivityRunnable(context, intent, userHandle));
+
+ return false;
+ }
+
/**
* Remove the dying provider from known provider map and launching provider map.
* @param proc The dying process recoder
@@ -1493,8 +1492,8 @@ public class ContentProviderHelper {
* @param always If true, remove the provider from launching map always, no more restart attempt
* @return true if the given provider is in launching
*/
- boolean removeDyingProviderLocked(ProcessRecord proc,
- ContentProviderRecord cpr, boolean always) {
+ boolean removeDyingProviderLocked(ProcessRecord proc, ContentProviderRecord cpr,
+ boolean always) {
boolean inLaunching = mLaunchingProviders.contains(cpr);
if (inLaunching && !always && ++cpr.mRestartCount > ContentProviderRecord.MAX_RETRY_COUNT) {
// It's being launched but we've reached maximum attempts, force the removal
@@ -1536,10 +1535,8 @@ public class ContentProviderHelper {
conn.dead = true;
if (conn.stableCount() > 0) {
if (!capp.isPersistent() && capp.thread != null
- && capp.pid != 0
- && capp.pid != ActivityManagerService.MY_PID) {
- capp.kill("depends on provider "
- + cpr.name.flattenToShortString()
+ && capp.pid != 0 && capp.pid != ActivityManagerService.MY_PID) {
+ capp.kill("depends on provider " + cpr.name.flattenToShortString()
+ " in dying proc " + (proc != null ? proc.processName : "??")
+ " (adj " + (proc != null ? proc.setAdj : "??") + ")",
ApplicationExitInfo.REASON_DEPENDENCY_DIED,
@@ -1555,8 +1552,8 @@ public class ContentProviderHelper {
// clean up this connection, we'll just remove it.
cpr.connections.remove(i);
if (conn.client.conProviders.remove(conn)) {
- mService.stopAssociationLocked(capp.uid, capp.processName, cpr.uid,
- cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
+ mService.stopAssociationLocked(capp.uid, capp.processName,
+ cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
}
}
}
@@ -1587,22 +1584,24 @@ public class ContentProviderHelper {
boolean restart = false;
for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
ContentProviderRecord cpr = mLaunchingProviders.get(i);
- if (cpr.launchingApp == app) {
- if (++cpr.mRestartCount > ContentProviderRecord.MAX_RETRY_COUNT) {
- // It's being launched but we've reached maximum attempts, mark it as bad
- alwaysBad = true;
- }
- if (!alwaysBad && !app.bad && cpr.hasConnectionOrHandle()) {
- restart = true;
- } else {
- removeDyingProviderLocked(app, cpr, true);
- }
+ if (cpr.launchingApp != app) {
+ continue;
+ }
+
+ if (++cpr.mRestartCount > ContentProviderRecord.MAX_RETRY_COUNT) {
+ // It's being launched but we've reached maximum attempts, mark it as bad
+ alwaysBad = true;
+ }
+ if (!alwaysBad && !app.bad && cpr.hasConnectionOrHandle()) {
+ restart = true;
+ } else {
+ removeDyingProviderLocked(app, cpr, true);
}
}
return restart;
}
- void cleanupLaunchingProviders() {
+ void cleanupLaunchingProvidersLocked() {
for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
ContentProviderRecord cpr = mLaunchingProviders.get(i);
if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles()) {
@@ -1614,31 +1613,6 @@ public class ContentProviderHelper {
}
}
- ProviderInfo getProviderInfoLocked(String authority, @UserIdInt int userId,
- int pmFlags) {
- ProviderInfo pi = null;
- ContentProviderRecord cpr = mProviderMap.getProviderByName(authority, userId);
- if (cpr != null) {
- pi = cpr.info;
- } else {
- try {
- pi = AppGlobals.getPackageManager().resolveContentProvider(
- authority, PackageManager.GET_URI_PERMISSION_PATTERNS | pmFlags, userId);
- } catch (RemoteException ex) {
- }
- }
- return pi;
- }
-
- @GuardedBy("mService")
- void processContentProviderPublishTimedOutLocked(ProcessRecord app) {
- cleanupAppInLaunchingProvidersLocked(app, true);
- mService.mProcessList.removeProcessLocked(app, false, true,
- ApplicationExitInfo.REASON_INITIALIZATION_FAILURE,
- ApplicationExitInfo.SUBREASON_UNKNOWN,
- "timeout publishing content providers");
- }
-
private void checkTime(long startTime, String where) {
long now = SystemClock.uptimeMillis();
if ((now - startTime) > 50) {
@@ -1649,16 +1623,13 @@ public class ContentProviderHelper {
void dumpProvidersLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
- boolean needSep;
- boolean printedAnything = false;
-
ActivityManagerService.ItemMatcher matcher = new ActivityManagerService.ItemMatcher();
matcher.build(args, opti);
pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
- needSep = mProviderMap.dumpProvidersLocked(pw, dumpAll, dumpPackage);
- printedAnything |= needSep;
+ boolean needSep = mProviderMap.dumpProvidersLocked(pw, dumpAll, dumpPackage);
+ boolean printedAnything = needSep;
if (mLaunchingProviders.size() > 0) {
boolean printed = false;
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index ca61788d1918..8970ec4c7bb7 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -92,7 +92,7 @@ final class CoreSettingsObserver extends ContentObserver {
sGlobalSettingToTypeMap.put(
Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, String.class);
sGlobalSettingToTypeMap.put(
- Settings.Global.GLOBAL_SETTINGS_ANGLE_WHITELIST, String.class);
+ Settings.Global.GLOBAL_SETTINGS_ANGLE_ALLOWLIST, String.class);
sGlobalSettingToTypeMap.put(
Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, int.class);
@@ -105,9 +105,9 @@ final class CoreSettingsObserver extends ContentObserver {
sGlobalSettingToTypeMap.put(
Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.class);
- sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class);
- sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class);
- sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_DENYLIST, String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_ALLOWLIST, String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_DENYLISTS, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class);
// add other global settings here...
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 1038069f5d11..5721fb7f5128 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2951,25 +2951,26 @@ public final class ProcessList {
if ((expecting == null) || (old == expecting)) {
mProcessNames.remove(name, uid);
}
- if (old != null && old.uidRecord != null) {
- old.uidRecord.numProcs--;
- old.uidRecord.procRecords.remove(old);
- if (old.uidRecord.numProcs == 0) {
+ final ProcessRecord record = expecting != null ? expecting : old;
+ if (record != null && record.uidRecord != null) {
+ final UidRecord uidRecord = record.uidRecord;
+ uidRecord.numProcs--;
+ uidRecord.procRecords.remove(record);
+ if (uidRecord.numProcs == 0) {
// No more processes using this uid, tell clients it is gone.
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
- "No more processes in " + old.uidRecord);
- mService.enqueueUidChangeLocked(old.uidRecord, -1, UidRecord.CHANGE_GONE);
+ "No more processes in " + uidRecord);
+ mService.enqueueUidChangeLocked(uidRecord, -1, UidRecord.CHANGE_GONE);
EventLogTags.writeAmUidStopped(uid);
mActiveUids.remove(uid);
mService.noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT,
ActivityManager.PROCESS_CAPABILITY_NONE);
}
- old.uidRecord = null;
+ record.uidRecord = null;
}
mIsolatedProcesses.remove(uid);
mGlobalIsolatedUids.freeIsolatedUidLocked(uid);
// Remove the (expected) ProcessRecord from the app zygote
- final ProcessRecord record = expecting != null ? expecting : old;
if (record != null && record.appZygote) {
removeProcessFromAppZygoteLocked(record);
}
diff --git a/services/core/java/com/android/server/appbinding/AppBindingService.java b/services/core/java/com/android/server/appbinding/AppBindingService.java
index 7e63e728701e..5db6dc7ccc15 100644
--- a/services/core/java/com/android/server/appbinding/AppBindingService.java
+++ b/services/core/java/com/android/server/appbinding/AppBindingService.java
@@ -45,6 +45,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.am.PersistentConnection;
import com.android.server.appbinding.finders.AppServiceFinder;
import com.android.server.appbinding.finders.CarrierMessagingClientServiceFinder;
@@ -125,18 +126,18 @@ public class AppBindingService extends Binder {
}
@Override
- public void onStartUser(int userHandle) {
- mService.onStartUser(userHandle);
+ public void onUserStarting(@NonNull TargetUser user) {
+ mService.onStartUser(user.getUserIdentifier());
}
@Override
- public void onUnlockUser(int userId) {
- mService.onUnlockUser(userId);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mService.onUnlockUser(user.getUserIdentifier());
}
@Override
- public void onStopUser(int userHandle) {
- mService.onStopUser(userHandle);
+ public void onUserStopping(@NonNull TargetUser user) {
+ mService.onStopUser(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 7051e4a294e2..e128d993ab63 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -108,7 +108,8 @@ public class AttentionManagerService extends SystemService {
private final PowerManager mPowerManager;
private final Object mLock;
@GuardedBy("mLock")
- private IAttentionService mService;
+ @VisibleForTesting
+ protected IAttentionService mService;
@GuardedBy("mLock")
private AttentionCheckCacheBuffer mAttentionCheckCacheBuffer;
@GuardedBy("mLock")
@@ -158,7 +159,8 @@ public class AttentionManagerService extends SystemService {
}
/** Resolves and sets up the attention service if it had not been done yet. */
- private boolean isServiceAvailable() {
+ @VisibleForTesting
+ protected boolean isServiceAvailable() {
if (mComponentName == null) {
mComponentName = resolveAttentionService(mContext);
}
@@ -168,12 +170,12 @@ public class AttentionManagerService extends SystemService {
/**
* Returns {@code true} if attention service is supported on this device.
*/
- private boolean isAttentionServiceSupported() {
+ @VisibleForTesting
+ protected boolean isAttentionServiceSupported() {
return isServiceEnabled() && isServiceConfigured(mContext);
}
- @VisibleForTesting
- protected boolean isServiceEnabled() {
+ private boolean isServiceEnabled() {
return DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE, KEY_SERVICE_ENABLED,
DEFAULT_SERVICE_ENABLED);
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 2d77d6f8add8..32be03fb4ef8 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -5855,11 +5855,13 @@ public class AudioService extends IAudioService.Stub
caller);
}
// fire changed intents for all streams
- mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
- mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
- mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
- mStreamVolumeAlias[mStreamType]);
- sendBroadcastToAll(mVolumeChanged);
+ if (index != oldIndex) {
+ mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, index);
+ mVolumeChanged.putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, oldIndex);
+ mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE_ALIAS,
+ mStreamVolumeAlias[mStreamType]);
+ sendBroadcastToAll(mVolumeChanged);
+ }
}
return changed;
}
@@ -7497,6 +7499,7 @@ public class AudioService extends IAudioService.Stub
pw.print(" mIsSingleVolume="); pw.println(mIsSingleVolume);
pw.print(" mUseFixedVolume="); pw.println(mUseFixedVolume);
pw.print(" mFixedVolumeDevices="); pw.println(dumpDeviceTypes(mFixedVolumeDevices));
+ pw.print(" mFullVolumeDevices="); pw.println(dumpDeviceTypes(mFullVolumeDevices));
pw.print(" mExtVolumeController="); pw.println(mExtVolumeController);
pw.print(" mHdmiCecSink="); pw.println(mHdmiCecSink);
pw.print(" mHdmiAudioSystemClient="); pw.println(mHdmiAudioSystemClient);
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index b4c41b274dbe..5e8f1ef0db85 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -632,21 +632,28 @@ public class BtHelper {
return result;
}
+ // Return `(null)` if given BluetoothDevice is null. Otherwise, return the anonymized address.
+ private String getAnonymizedAddress(BluetoothDevice btDevice) {
+ return btDevice == null ? "(null)" : btDevice.getAnonymizedAddress();
+ }
+
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
//@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
private void setBtScoActiveDevice(BluetoothDevice btDevice) {
- Log.i(TAG, "setBtScoActiveDevice: " + mBluetoothHeadsetDevice + " -> " + btDevice);
+ Log.i(TAG, "setBtScoActiveDevice: " + getAnonymizedAddress(mBluetoothHeadsetDevice)
+ + " -> " + getAnonymizedAddress(btDevice));
final BluetoothDevice previousActiveDevice = mBluetoothHeadsetDevice;
if (Objects.equals(btDevice, previousActiveDevice)) {
return;
}
if (!handleBtScoActiveDeviceChange(previousActiveDevice, false)) {
Log.w(TAG, "setBtScoActiveDevice() failed to remove previous device "
- + previousActiveDevice);
+ + getAnonymizedAddress(previousActiveDevice));
}
if (!handleBtScoActiveDeviceChange(btDevice, true)) {
- Log.e(TAG, "setBtScoActiveDevice() failed to add new device " + btDevice);
+ Log.e(TAG, "setBtScoActiveDevice() failed to add new device "
+ + getAnonymizedAddress(btDevice));
// set mBluetoothHeadsetDevice to null when failing to add new device
btDevice = null;
}
@@ -826,7 +833,8 @@ public class BtHelper {
mBluetoothHeadsetDevice, mScoAudioMode)) {
mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
} else {
- Log.w(TAG, "requestScoState: connect to " + mBluetoothHeadsetDevice
+ Log.w(TAG, "requestScoState: connect to "
+ + getAnonymizedAddress(mBluetoothHeadsetDevice)
+ " failed, mScoAudioMode=" + mScoAudioMode);
broadcastScoConnectionState(
AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index 0aeb7abe706e..4f37dccea42e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -194,19 +194,19 @@ public class BiometricScheduler {
return;
}
+ if (clientMonitor != mCurrentOperation.clientMonitor) {
+ Slog.e(getTag(), "[Ignoring Finish] " + clientMonitor + " does not match"
+ + " current: " + mCurrentOperation.clientMonitor);
+ return;
+ }
+
+ Slog.d(getTag(), "[Finishing] " + clientMonitor + ", success: " + success);
mCurrentOperation.state = Operation.STATE_FINISHED;
if (mCurrentOperation.clientFinishCallback != null) {
mCurrentOperation.clientFinishCallback.onClientFinished(clientMonitor, success);
}
- if (clientMonitor != mCurrentOperation.clientMonitor) {
- throw new IllegalStateException("Mismatched operation, "
- + " current: " + mCurrentOperation.clientMonitor
- + " received: " + clientMonitor);
- }
-
- Slog.d(getTag(), "[Finished] " + clientMonitor + ", success: " + success);
if (mGestureAvailabilityDispatcher != null) {
mGestureAvailabilityDispatcher.markSensorActive(
mCurrentOperation.clientMonitor.getSensorId(), false /* active */);
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 61c99b88d113..88867fcfc46f 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -15,6 +15,8 @@
*/
package com.android.server.camera;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -43,6 +45,7 @@ import com.android.internal.util.FrameworkStatsLog;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.wm.WindowManagerInternal;
import java.util.ArrayList;
@@ -252,20 +255,20 @@ public class CameraServiceProxy extends SystemService
}
@Override
- public void onStartUser(int userHandle) {
+ public void onUserStarting(@NonNull TargetUser user) {
synchronized(mLock) {
if (mEnabledCameraUsers == null) {
// Initialize cameraserver, or update cameraserver if we are recovering
// from a crash.
- switchUserLocked(userHandle);
+ switchUserLocked(user.getUserIdentifier());
}
}
}
@Override
- public void onSwitchUser(int userHandle) {
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
synchronized(mLock) {
- switchUserLocked(userHandle);
+ switchUserLocked(to.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index ed3a223b5dd7..a0bc7d8954fb 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -19,6 +19,7 @@ package com.android.server.clipboard;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
@@ -59,6 +60,7 @@ import android.view.autofill.AutofillManagerInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.contentcapture.ContentCaptureManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.WindowManagerInternal;
@@ -218,9 +220,9 @@ public class ClipboardService extends SystemService {
}
@Override
- public void onCleanupUser(int userId) {
+ public void onUserStopped(@NonNull TargetUser user) {
synchronized (mClipboards) {
- mClipboards.remove(userId);
+ mClipboards.remove(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index a75a80a606eb..7202f0f401f9 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -21,14 +21,23 @@ import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.INTERNET;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
-import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
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_NETWORK;
+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.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
+import static com.android.internal.util.ArrayUtils.convertToIntArray;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -51,7 +60,6 @@ import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
@@ -65,7 +73,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
-
/**
* A utility class to inform Netd of UID permisisons.
* Does a mass update at boot and then monitors for app install/remove.
@@ -114,6 +121,13 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
public int getDeviceFirstSdkInt() {
return Build.VERSION.FIRST_SDK_INT;
}
+
+ /**
+ * Check whether given uid has specific permission.
+ */
+ public int uidPermission(@NonNull final String permission, final int uid) {
+ return ActivityManager.checkUidPermission(permission, uid);
+ }
}
public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) {
@@ -156,8 +170,9 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
}
mAllApps.add(UserHandle.getAppId(uid));
- boolean isNetwork = hasNetworkPermission(app);
- boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
+ final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid);
+ final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(uid)
+ || isCarryoverPackage(app.applicationInfo);
if (isNetwork || hasRestrictedPermission) {
Boolean permission = mApps.get(uid);
@@ -169,8 +184,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
}
//TODO: unify the management of the permissions into one codepath.
- int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions,
- app.requestedPermissionsFlags);
+ final int otherNetdPerms = getNetdPermissionMask(uid);
netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
}
@@ -186,13 +200,12 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
for (int i = 0; i < systemPermission.size(); i++) {
ArraySet<String> perms = systemPermission.valueAt(i);
int uid = systemPermission.keyAt(i);
- int netdPermission = 0;
+ int netdPermission = PERMISSION_NONE;
// Get the uids of native services that have UPDATE_DEVICE_STATS or INTERNET permission.
if (perms != null) {
netdPermission |= perms.contains(UPDATE_DEVICE_STATS)
- ? INetd.PERMISSION_UPDATE_DEVICE_STATS : 0;
- netdPermission |= perms.contains(INTERNET)
- ? INetd.PERMISSION_INTERNET : 0;
+ ? PERMISSION_UPDATE_DEVICE_STATS : 0;
+ netdPermission |= perms.contains(INTERNET) ? PERMISSION_INTERNET : 0;
}
netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission);
}
@@ -207,48 +220,34 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
}
@VisibleForTesting
- boolean hasPermission(@NonNull final PackageInfo app, @NonNull final String permission) {
- if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) {
- return false;
- }
- final int index = ArrayUtils.indexOf(app.requestedPermissions, permission);
- if (index < 0 || index >= app.requestedPermissionsFlags.length) return false;
- return (app.requestedPermissionsFlags[index] & REQUESTED_PERMISSION_GRANTED) != 0;
+ boolean hasPermission(@NonNull final String permission, final int uid) {
+ return mDeps.uidPermission(permission, uid) == PackageManager.PERMISSION_GRANTED;
}
@VisibleForTesting
- boolean hasNetworkPermission(@NonNull final PackageInfo app) {
- return hasPermission(app, CHANGE_NETWORK_STATE);
+ // TODO : remove this check in the future(b/162295056). All apps should just request the
+ // appropriate permission for their use case since android Q.
+ boolean isCarryoverPackage(@Nullable final ApplicationInfo appInfo) {
+ if (appInfo == null) return false;
+ return (appInfo.targetSdkVersion < VERSION_Q && isVendorApp(appInfo))
+ // Backward compatibility for b/114245686, on devices that launched before Q daemons
+ // and apps running as the system UID are exempted from this check.
+ || (appInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q);
}
@VisibleForTesting
- boolean hasRestrictedNetworkPermission(@NonNull final PackageInfo app) {
- // TODO : remove this check in the future(b/31479477). All apps should just
- // request the appropriate permission for their use case since android Q.
- if (app.applicationInfo != null) {
- // Backward compatibility for b/114245686, on devices that launched before Q daemons
- // and apps running as the system UID are exempted from this check.
- if (app.applicationInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q) {
- return true;
- }
-
- if (app.applicationInfo.targetSdkVersion < VERSION_Q
- && isVendorApp(app.applicationInfo)) {
- return true;
- }
- }
-
- return hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK)
- || hasPermission(app, NETWORK_STACK)
- || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
+ boolean hasRestrictedNetworkPermission(final int uid) {
+ return hasPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, uid)
+ || hasPermission(PERMISSION_MAINLINE_NETWORK_STACK, uid)
+ || hasPermission(NETWORK_STACK, uid);
}
/** Returns whether the given uid has using background network permission. */
public synchronized boolean hasUseBackgroundNetworksPermission(final int uid) {
// Apps with any of the CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_INTERNAL or
// CONNECTIVITY_USE_RESTRICTED_NETWORKS permission has the permission to use background
- // networks. mApps contains the result of checks for both hasNetworkPermission and
- // hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of
+ // networks. mApps contains the result of checks for both CHANGE_NETWORK_STATE permission
+ // and hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of
// permissions at least.
return mApps.containsKey(uid);
}
@@ -273,11 +272,11 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
}
try {
if (add) {
- mNetd.networkSetPermissionForUser(INetd.PERMISSION_NETWORK, toIntArray(network));
- mNetd.networkSetPermissionForUser(INetd.PERMISSION_SYSTEM, toIntArray(system));
+ mNetd.networkSetPermissionForUser(PERMISSION_NETWORK, convertToIntArray(network));
+ mNetd.networkSetPermissionForUser(PERMISSION_SYSTEM, convertToIntArray(system));
} else {
- mNetd.networkClearPermissionForUser(toIntArray(network));
- mNetd.networkClearPermissionForUser(toIntArray(system));
+ mNetd.networkClearPermissionForUser(convertToIntArray(network));
+ mNetd.networkClearPermissionForUser(convertToIntArray(system));
}
} catch (RemoteException e) {
loge("Exception when updating permissions: " + e);
@@ -323,14 +322,15 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
}
@VisibleForTesting
- protected Boolean highestPermissionForUid(Boolean currentPermission, String name) {
+ protected Boolean highestPermissionForUid(Boolean currentPermission, String name, int uid) {
if (currentPermission == SYSTEM) {
return currentPermission;
}
try {
final PackageInfo app = mPackageManager.getPackageInfo(name, GET_PERMISSIONS);
- final boolean isNetwork = hasNetworkPermission(app);
- final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
+ final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid);
+ final boolean hasRestrictedPermission = hasRestrictedNetworkPermission(uid)
+ || isCarryoverPackage(app.applicationInfo);
if (isNetwork || hasRestrictedPermission) {
currentPermission = hasRestrictedPermission;
}
@@ -342,23 +342,14 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
}
private int getPermissionForUid(final int uid) {
- int permission = INetd.PERMISSION_NONE;
// 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) {
- for (String name : packages) {
- final PackageInfo app = getPackageInfo(name);
- if (app != null && app.requestedPermissions != null) {
- permission |= getNetdPermissionMask(app.requestedPermissions,
- app.requestedPermissionsFlags);
- }
- }
- } else {
+ if (packages == null || packages.length <= 0) {
// The last package of this uid is removed from device. Clean the package up.
- permission = INetd.PERMISSION_UNINSTALLED;
+ return PERMISSION_UNINSTALLED;
}
- return permission;
+ return getNetdPermissionMask(uid);
}
/**
@@ -375,7 +366,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
// If multiple packages share a UID (cf: android:sharedUserId) and ask for different
// permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
- final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName);
+ final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName, uid);
if (permission != mApps.get(uid)) {
mApps.put(uid, permission);
@@ -431,7 +422,7 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
String[] packages = mPackageManager.getPackagesForUid(uid);
if (packages != null && packages.length > 0) {
for (String name : packages) {
- permission = highestPermissionForUid(permission, name);
+ permission = highestPermissionForUid(permission, name, uid);
if (permission == SYSTEM) {
// An app with this UID still has the SYSTEM permission.
// Therefore, this UID must already have the SYSTEM permission.
@@ -467,19 +458,13 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
sendPackagePermissionsForUid(uid, getPermissionForUid(uid));
}
- private static int getNetdPermissionMask(String[] requestedPermissions,
- int[] requestedPermissionsFlags) {
- int permissions = 0;
- if (requestedPermissions == null || requestedPermissionsFlags == null) return permissions;
- for (int i = 0; i < requestedPermissions.length; i++) {
- if (requestedPermissions[i].equals(INTERNET)
- && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) {
- permissions |= INetd.PERMISSION_INTERNET;
- }
- if (requestedPermissions[i].equals(UPDATE_DEVICE_STATS)
- && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) {
- permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS;
- }
+ private int getNetdPermissionMask(final int uid) {
+ int permissions = PERMISSION_NONE;
+ if (hasPermission(INTERNET, uid)) {
+ permissions |= PERMISSION_INTERNET;
+ }
+ if (hasPermission(UPDATE_DEVICE_STATS, uid)) {
+ permissions |= PERMISSION_UPDATE_DEVICE_STATS;
}
return permissions;
}
@@ -648,19 +633,19 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
for (int i = 0; i < netdPermissionsAppIds.size(); i++) {
int permissions = netdPermissionsAppIds.valueAt(i);
switch(permissions) {
- case (INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS):
+ case (PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS):
allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
break;
- case INetd.PERMISSION_INTERNET:
+ case PERMISSION_INTERNET:
internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
break;
- case INetd.PERMISSION_UPDATE_DEVICE_STATS:
+ case PERMISSION_UPDATE_DEVICE_STATS:
updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
break;
- case INetd.PERMISSION_NONE:
+ case PERMISSION_NONE:
noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
break;
- case INetd.PERMISSION_UNINSTALLED:
+ case PERMISSION_UNINSTALLED:
uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i));
default:
Log.e(TAG, "unknown permission type: " + permissions + "for uid: "
@@ -671,24 +656,24 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse
// TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids()
if (allPermissionAppIds.size() != 0) {
mNetd.trafficSetNetPermForUids(
- INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS,
- ArrayUtils.convertToIntArray(allPermissionAppIds));
+ PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS,
+ convertToIntArray(allPermissionAppIds));
}
if (internetPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(INetd.PERMISSION_INTERNET,
- ArrayUtils.convertToIntArray(internetPermissionAppIds));
+ mNetd.trafficSetNetPermForUids(PERMISSION_INTERNET,
+ convertToIntArray(internetPermissionAppIds));
}
if (updateStatsPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UPDATE_DEVICE_STATS,
- ArrayUtils.convertToIntArray(updateStatsPermissionAppIds));
+ mNetd.trafficSetNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS,
+ convertToIntArray(updateStatsPermissionAppIds));
}
if (noPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(INetd.PERMISSION_NONE,
- ArrayUtils.convertToIntArray(noPermissionAppIds));
+ mNetd.trafficSetNetPermForUids(PERMISSION_NONE,
+ convertToIntArray(noPermissionAppIds));
}
if (uninstalledAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(INetd.PERMISSION_UNINSTALLED,
- ArrayUtils.convertToIntArray(uninstalledAppIds));
+ mNetd.trafficSetNetPermForUids(PERMISSION_UNINSTALLED,
+ convertToIntArray(uninstalledAppIds));
}
} catch (RemoteException e) {
Log.e(TAG, "Pass appId list of special permission failed." + e);
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 9a910bf5e859..1294e9030f62 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -20,6 +20,7 @@ import static android.content.PermissionChecker.PERMISSION_GRANTED;
import android.Manifest;
import android.accounts.Account;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.ActivityManager;
@@ -75,6 +76,7 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import java.io.FileDescriptor;
@@ -124,26 +126,25 @@ public final class ContentService extends IContentService.Stub {
mService.onBootPhase(phase);
}
-
@Override
- public void onStartUser(int userHandle) {
- mService.onStartUser(userHandle);
+ public void onUserStarting(@NonNull TargetUser user) {
+ mService.onStartUser(user.getUserIdentifier());
}
@Override
- public void onUnlockUser(int userHandle) {
- mService.onUnlockUser(userHandle);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mService.onUnlockUser(user.getUserIdentifier());
}
@Override
- public void onStopUser(int userHandle) {
- mService.onStopUser(userHandle);
+ public void onUserStopping(@NonNull TargetUser user) {
+ mService.onStopUser(user.getUserIdentifier());
}
@Override
- public void onCleanupUser(int userHandle) {
+ public void onUserStopped(@NonNull TargetUser user) {
synchronized (mService.mCache) {
- mService.mCache.remove(userHandle);
+ mService.mCache.remove(user.getUserIdentifier());
}
}
}
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index ec2b0c0a6830..ad3cd67ad65b 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -491,7 +491,14 @@ final class ColorFade {
mIsWideColor = SurfaceControl.getActiveColorMode(token)
== Display.COLOR_MODE_DISPLAY_P3;
- SurfaceControl.screenshot(token, s);
+ SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
+ mDisplayManagerInternal.systemScreenshot(mDisplayId);
+ s.attachAndQueueBufferWithColorSpace(screenshotBuffer.getHardwareBuffer(),
+ screenshotBuffer.getColorSpace());
+
+ if (screenshotBuffer.containsSecureLayers()) {
+ mTransaction.setSecure(mSurfaceControl, true).apply();
+ }
st.updateTexImage();
st.getTransformMatrix(mTexMatrix);
} finally {
@@ -586,7 +593,6 @@ final class ColorFade {
}
if (mSurfaceControl == null) {
- Transaction t = new Transaction();
try {
final SurfaceControl.Builder builder = new SurfaceControl.Builder(mSurfaceSession)
.setName("ColorFade")
@@ -602,15 +608,16 @@ final class ColorFade {
return false;
}
- t.setLayerStack(mSurfaceControl, mDisplayLayerStack);
- t.setWindowCrop(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+ mTransaction.setLayerStack(mSurfaceControl, mDisplayLayerStack);
+ mTransaction.setWindowCrop(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+ mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
+ mDisplayId, mSurfaceControl);
+ mSurfaceLayout.onDisplayTransaction(mTransaction);
+ mTransaction.apply();
+
mSurface = new Surface();
mSurface.copyFrom(mSurfaceControl);
- mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
- mDisplayId, mSurfaceControl);
- mSurfaceLayout.onDisplayTransaction(t);
- t.apply();
}
return true;
}
@@ -652,7 +659,7 @@ final class ColorFade {
if (mSurfaceControl != null) {
mSurfaceLayout.dispose();
mSurfaceLayout = null;
- new Transaction().remove(mSurfaceControl).apply();
+ mTransaction.remove(mSurfaceControl).apply();
mSurface.release();
mSurfaceControl = null;
mSurfaceVisible = false;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index a00c22a409e9..0979ad67a8cd 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -104,6 +104,7 @@ 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;
@@ -417,7 +418,8 @@ public final class DisplayManagerService extends SystemService {
}
@Override
- public void onSwitchUser(@UserIdInt int newUserId) {
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+ final int newUserId = to.getUserIdentifier();
final int userSerial = getUserManager().getUserSerialNumber(newUserId);
synchronized (mSyncRoot) {
if (mCurrentUserId != newUserId) {
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 95a98f1e9494..92a3ccfc9dd9 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -58,6 +58,7 @@ import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings.Secure;
@@ -76,6 +77,7 @@ import com.android.internal.util.DumpUtils;
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.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
@@ -205,30 +207,24 @@ public final class ColorDisplayService extends SystemService {
}
@Override
- public void onStartUser(int userHandle) {
- super.onStartUser(userHandle);
-
+ public void onUserStarting(@NonNull TargetUser user) {
if (mCurrentUser == UserHandle.USER_NULL) {
final Message message = mHandler.obtainMessage(MSG_USER_CHANGED);
- message.arg1 = userHandle;
+ message.arg1 = user.getUserIdentifier();
mHandler.sendMessage(message);
}
}
@Override
- public void onSwitchUser(int userHandle) {
- super.onSwitchUser(userHandle);
-
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
final Message message = mHandler.obtainMessage(MSG_USER_CHANGED);
- message.arg1 = userHandle;
+ message.arg1 = to.getUserIdentifier();
mHandler.sendMessage(message);
}
@Override
- public void onStopUser(int userHandle) {
- super.onStopUser(userHandle);
-
- if (mCurrentUser == userHandle) {
+ public void onUserStopping(@NonNull TargetUser user) {
+ if (mCurrentUser == user.getUserIdentifier()) {
final Message message = mHandler.obtainMessage(MSG_USER_CHANGED);
message.arg1 = UserHandle.USER_NULL;
mHandler.sendMessage(message);
@@ -819,7 +815,13 @@ public final class ColorDisplayService extends SystemService {
return LocalDateTime.MIN;
}
- private boolean setAppSaturationLevelInternal(String callingPackageName,
+ void setSaturationLevelInternal(int saturationLevel) {
+ final Message message = mHandler.obtainMessage(MSG_APPLY_GLOBAL_SATURATION);
+ message.arg1 = saturationLevel;
+ mHandler.sendMessage(message);
+ }
+
+ boolean setAppSaturationLevelInternal(String callingPackageName,
String affectedPackageName, int saturationLevel) {
return mAppSaturationController
.setSaturationLevel(callingPackageName, affectedPackageName, mCurrentUser,
@@ -1509,9 +1511,7 @@ public final class ColorDisplayService extends SystemService {
}
final long token = Binder.clearCallingIdentity();
try {
- final Message message = mHandler.obtainMessage(MSG_APPLY_GLOBAL_SATURATION);
- message.arg1 = level;
- mHandler.sendMessage(message);
+ setSaturationLevelInternal(level);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1724,5 +1724,22 @@ public final class ColorDisplayService extends SystemService {
Binder.restoreCallingIdentity(token);
}
}
+
+ @Override
+ public int handleShellCommand(ParcelFileDescriptor in,
+ ParcelFileDescriptor out, ParcelFileDescriptor err, String[] args) {
+ getContext().enforceCallingOrSelfPermission(
+ Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
+ "Permission required to use ADB color transform commands");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return new ColorDisplayShellCommand(ColorDisplayService.this)
+ .exec(this, in.getFileDescriptor(), out.getFileDescriptor(),
+ err.getFileDescriptor(),
+ args);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java b/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java
new file mode 100644
index 000000000000..b4555f851d4d
--- /dev/null
+++ b/services/core/java/com/android/server/display/color/ColorDisplayShellCommand.java
@@ -0,0 +1,119 @@
+/*
+ * 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.display.color;
+
+import android.content.pm.PackageManagerInternal;
+import android.os.ShellCommand;
+
+import com.android.server.LocalServices;
+
+class ColorDisplayShellCommand extends ShellCommand {
+
+ private static final String USAGE = "usage: cmd color_display SUBCOMMAND [ARGS]\n"
+ + " help\n"
+ + " Shows this message.\n"
+ + " set-saturation LEVEL\n"
+ + " Sets the device saturation to the given LEVEL, 0-100 inclusive.\n"
+ + " set-layer-saturation CALLER_PACKAGE TARGET_PACKAGE LEVEL\n"
+ + " Sets the saturation LEVEL for all layers of the TARGET_PACKAGE, attributed\n"
+ + " to the CALLER_PACKAGE. The lowest LEVEL from any CALLER_PACKAGE is applied.\n";
+
+ private static final int ERROR = -1;
+ private static final int SUCCESS = 0;
+
+ private final ColorDisplayService mService;
+
+ ColorDisplayShellCommand(ColorDisplayService service) {
+ mService = service;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+ switch (cmd) {
+ case "set-saturation":
+ return setSaturation();
+ case "set-layer-saturation":
+ return setLayerSaturation();
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ }
+
+ private int setSaturation() {
+ final int level = getLevel();
+ if (level == ERROR) {
+ return ERROR;
+ }
+ mService.setSaturationLevelInternal(level);
+ return SUCCESS;
+ }
+
+ private int setLayerSaturation() {
+ final int level = getLevel();
+ if (level == ERROR) {
+ return ERROR;
+ }
+ final String callerPackageName = getPackageName();
+ if (callerPackageName == null) {
+ getErrPrintWriter().println("Error: CALLER_PACKAGE must be an installed package name");
+ return ERROR;
+ }
+ final String targetPackageName = getPackageName();
+ if (targetPackageName == null) {
+ getErrPrintWriter().println("Error: TARGET_PACKAGE must be an installed package name");
+ return ERROR;
+ }
+ mService.setAppSaturationLevelInternal(callerPackageName, targetPackageName, level);
+ return SUCCESS;
+ }
+
+ private String getPackageName() {
+ final String packageNameArg = getNextArg();
+ return LocalServices.getService(PackageManagerInternal.class).getPackage(packageNameArg)
+ == null
+ ? null : packageNameArg;
+ }
+
+ private int getLevel() {
+ final String levelArg = getNextArg();
+ if (levelArg == null) {
+ getErrPrintWriter().println("Error: Required argument LEVEL is unspecified");
+ return ERROR;
+ }
+ final int level;
+ try {
+ level = Integer.parseInt(levelArg);
+ } catch (NumberFormatException e) {
+ getErrPrintWriter().println("Error: LEVEL argument is not an integer");
+ return ERROR;
+ }
+ if (level < 0 || level > 100) {
+ getErrPrintWriter()
+ .println("Error: LEVEL argument must be an integer between 0 and 100");
+ return ERROR;
+ }
+ return level;
+ }
+
+ @Override
+ public void onHelp() {
+ getOutPrintWriter().print(USAGE);
+ }
+}
diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java
index 8a3c963f4805..c0617ca95f9f 100644
--- a/services/core/java/com/android/server/gpu/GpuService.java
+++ b/services/core/java/com/android/server/gpu/GpuService.java
@@ -29,8 +29,6 @@ import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
-import android.gamedriver.GameDriverProto.Blacklist;
-import android.gamedriver.GameDriverProto.Blacklists;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
@@ -40,6 +38,8 @@ import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.provider.Settings;
import android.text.TextUtils;
+import android.updatabledriver.UpdatableDriverProto.Denylist;
+import android.updatabledriver.UpdatableDriverProto.Denylists;
import android.util.Base64;
import android.util.Slog;
@@ -65,7 +65,7 @@ public class GpuService extends SystemService {
private static final String PROD_DRIVER_PROPERTY = "ro.gfx.driver.0";
private static final String DEV_DRIVER_PROPERTY = "ro.gfx.driver.1";
- private static final String GAME_DRIVER_WHITELIST_FILENAME = "whitelist.txt";
+ private static final String GAME_DRIVER_ALLOWLIST_FILENAME = "allowlist.txt";
private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP;
private final Context mContext;
@@ -81,7 +81,7 @@ public class GpuService extends SystemService {
private SettingsObserver mSettingsObserver;
private DeviceConfigListener mDeviceConfigListener;
@GuardedBy("mLock")
- private Blacklists mBlacklists;
+ private Denylists mDenylists;
public GpuService(Context context) {
super(context);
@@ -118,19 +118,19 @@ public class GpuService extends SystemService {
mSettingsObserver = new SettingsObserver();
mDeviceConfigListener = new DeviceConfigListener();
fetchGameDriverPackageProperties();
- processBlacklists();
- setBlacklist();
+ processDenylists();
+ setDenylist();
fetchDeveloperDriverPackageProperties();
}
}
private final class SettingsObserver extends ContentObserver {
- private final Uri mGameDriverBlackUri =
- Settings.Global.getUriFor(Settings.Global.GAME_DRIVER_BLACKLISTS);
+ private final Uri mGameDriverDenylistsUri =
+ Settings.Global.getUriFor(Settings.Global.GAME_DRIVER_DENYLISTS);
SettingsObserver() {
super(new Handler());
- mContentResolver.registerContentObserver(mGameDriverBlackUri, false, this,
+ mContentResolver.registerContentObserver(mGameDriverDenylistsUri, false, this,
UserHandle.USER_ALL);
}
@@ -140,9 +140,9 @@ public class GpuService extends SystemService {
return;
}
- if (mGameDriverBlackUri.equals(uri)) {
- processBlacklists();
- setBlacklist();
+ if (mGameDriverDenylistsUri.equals(uri)) {
+ processDenylists();
+ setDenylist();
}
}
}
@@ -157,10 +157,10 @@ public class GpuService extends SystemService {
@Override
public void onPropertiesChanged(Properties properties) {
synchronized (mDeviceConfigLock) {
- if (properties.getKeyset().contains(Settings.Global.GAME_DRIVER_BLACKLISTS)) {
- parseBlacklists(
- properties.getString(Settings.Global.GAME_DRIVER_BLACKLISTS, ""));
- setBlacklist();
+ if (properties.getKeyset().contains(Settings.Global.GAME_DRIVER_DENYLISTS)) {
+ parseDenylists(
+ properties.getString(Settings.Global.GAME_DRIVER_DENYLISTS, ""));
+ setDenylist();
}
}
}
@@ -187,7 +187,7 @@ public class GpuService extends SystemService {
case ACTION_PACKAGE_REMOVED:
if (isProdDriver) {
fetchGameDriverPackageProperties();
- setBlacklist();
+ setDenylist();
} else if (isDevDriver) {
fetchDeveloperDriverPackageProperties();
}
@@ -239,17 +239,17 @@ public class GpuService extends SystemService {
return;
}
- // Reset the whitelist.
+ // Reset the allowlist.
Settings.Global.putString(mContentResolver,
- Settings.Global.GAME_DRIVER_WHITELIST, "");
+ Settings.Global.GAME_DRIVER_ALLOWLIST, "");
mGameDriverVersionCode = driverInfo.longVersionCode;
try {
final Context driverContext = mContext.createPackageContext(mProdDriverPackageName,
Context.CONTEXT_RESTRICTED);
- assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_WHITELIST_FILENAME,
- Settings.Global.GAME_DRIVER_WHITELIST, ",");
+ assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_ALLOWLIST_FILENAME,
+ Settings.Global.GAME_DRIVER_ALLOWLIST, ",");
} catch (PackageManager.NameNotFoundException e) {
if (DEBUG) {
Slog.w(TAG, "driver package '" + mProdDriverPackageName + "' not installed");
@@ -257,48 +257,48 @@ public class GpuService extends SystemService {
}
}
- private void processBlacklists() {
+ private void processDenylists() {
String base64String = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_GAME_DRIVER,
- Settings.Global.GAME_DRIVER_BLACKLISTS);
+ Settings.Global.GAME_DRIVER_DENYLISTS);
if (base64String == null) {
base64String =
Settings.Global.getString(mContentResolver,
- Settings.Global.GAME_DRIVER_BLACKLISTS);
+ Settings.Global.GAME_DRIVER_DENYLISTS);
}
- parseBlacklists(base64String != null ? base64String : "");
+ parseDenylists(base64String != null ? base64String : "");
}
- private void parseBlacklists(String base64String) {
+ private void parseDenylists(String base64String) {
synchronized (mLock) {
- // Reset all blacklists
- mBlacklists = null;
+ // Reset all denylists
+ mDenylists = null;
try {
- mBlacklists = Blacklists.parseFrom(Base64.decode(base64String, BASE64_FLAGS));
+ mDenylists = Denylists.parseFrom(Base64.decode(base64String, BASE64_FLAGS));
} catch (IllegalArgumentException e) {
if (DEBUG) {
- Slog.w(TAG, "Can't parse blacklist, skip and continue...");
+ Slog.w(TAG, "Can't parse denylist, skip and continue...");
}
} catch (InvalidProtocolBufferException e) {
if (DEBUG) {
- Slog.w(TAG, "Can't parse blacklist, skip and continue...");
+ Slog.w(TAG, "Can't parse denylist, skip and continue...");
}
}
}
}
- private void setBlacklist() {
+ private void setDenylist() {
Settings.Global.putString(mContentResolver,
- Settings.Global.GAME_DRIVER_BLACKLIST, "");
+ Settings.Global.GAME_DRIVER_DENYLIST, "");
synchronized (mLock) {
- if (mBlacklists == null) {
+ if (mDenylists == null) {
return;
}
- List<Blacklist> blacklists = mBlacklists.getBlacklistsList();
- for (Blacklist blacklist : blacklists) {
- if (blacklist.getVersionCode() == mGameDriverVersionCode) {
+ List<Denylist> denylists = mDenylists.getDenylistsList();
+ for (Denylist denylist : denylists) {
+ if (denylist.getVersionCode() == mGameDriverVersionCode) {
Settings.Global.putString(mContentResolver,
- Settings.Global.GAME_DRIVER_BLACKLIST,
- String.join(",", blacklist.getPackageNamesList()));
+ Settings.Global.GAME_DRIVER_DENYLIST,
+ String.join(",", denylist.getPackageNamesList()));
return;
}
}
diff --git a/services/core/java/com/android/server/hdmi/ActiveSourceAction.java b/services/core/java/com/android/server/hdmi/ActiveSourceAction.java
index 3c4dae0f6467..c90f297e1485 100644
--- a/services/core/java/com/android/server/hdmi/ActiveSourceAction.java
+++ b/services/core/java/com/android/server/hdmi/ActiveSourceAction.java
@@ -39,15 +39,19 @@ public class ActiveSourceAction extends HdmiCecFeatureAction {
@Override
boolean start() {
mState = STATE_STARTED;
- sendCommand(HdmiCecMessageBuilder.buildActiveSource(getSourceAddress(),
- source().mService.getPhysicalAddress()));
+ int logicalAddress = getSourceAddress();
+ int physicalAddress = getSourcePath();
+
+ sendCommand(HdmiCecMessageBuilder.buildActiveSource(logicalAddress, physicalAddress));
if (source().getType() == HdmiDeviceInfo.DEVICE_PLAYBACK) {
// Reports menu-status active to receive <User Control Pressed>.
sendCommand(
- HdmiCecMessageBuilder.buildReportMenuStatus(getSourceAddress(), mDestination,
+ HdmiCecMessageBuilder.buildReportMenuStatus(logicalAddress, mDestination,
Constants.MENU_STATE_ACTIVATED));
}
+
+ source().setActiveSource(logicalAddress, physicalAddress);
mState = STATE_FINISHED;
finish();
return true;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 64d70d6601f6..596c1eccfabe 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -85,6 +85,14 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
// The option is false by default. Update settings db as well to have the right
// initial setting on UI.
mService.writeBooleanSetting(Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED, mAutoTvOff);
+
+ // Initialize settings database with System Property value. This will be the initial
+ // setting on the UI. If no System Property is set, the option is set to to_tv by default.
+ mService.writeStringSetting(Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ mService.readStringSetting(Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ HdmiProperties.send_standby_on_sleep().orElse(
+ HdmiProperties.send_standby_on_sleep_values.TO_TV).name()
+ .toLowerCase()));
}
@Override
@@ -188,8 +196,26 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource {
}
switch (standbyAction) {
case HdmiControlService.STANDBY_SCREEN_OFF:
- mService.sendCecCommand(
- HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
+ // Get latest setting value
+ @HdmiControlManager.StandbyBehavior
+ String sendStandbyOnSleep = mService.readStringSetting(
+ Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ HdmiProperties.send_standby_on_sleep().orElse(
+ HdmiProperties.send_standby_on_sleep_values.TO_TV).name()
+ .toLowerCase());
+ switch (sendStandbyOnSleep) {
+ case HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV:
+ mService.sendCecCommand(
+ HdmiCecMessageBuilder.buildStandby(mAddress, Constants.ADDR_TV));
+ break;
+ case HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST:
+ mService.sendCecCommand(
+ HdmiCecMessageBuilder.buildStandby(mAddress,
+ Constants.ADDR_BROADCAST));
+ break;
+ case HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE:
+ break;
+ }
break;
case HdmiControlService.STANDBY_SHUTDOWN:
// ACTION_SHUTDOWN is taken as a signal to power off all the devices.
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index a8a9a368cc71..0576e91b79eb 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -772,6 +772,11 @@ public class HdmiControlService extends SystemService {
return content;
}
+ void writeStringSetting(String key, String value) {
+ ContentResolver cr = getContext().getContentResolver();
+ Global.putString(cr, key, value);
+ }
+
private void initializeCec(int initiatedBy) {
mAddressAllocated = false;
mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true);
@@ -3244,7 +3249,6 @@ public class HdmiControlService extends SystemService {
playback.setIsActiveSource(true);
playback.wakeUpIfActiveSource();
playback.maySendActiveSource(source);
- setActiveSource(playback.mAddress, physicalAddress);
}
if (deviceType == HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) {
@@ -3255,7 +3259,6 @@ public class HdmiControlService extends SystemService {
audioSystem.setIsActiveSource(true);
audioSystem.wakeUpIfActiveSource();
audioSystem.maySendActiveSource(source);
- setActiveSource(audioSystem.mAddress, physicalAddress);
}
}
}
@@ -3278,13 +3281,11 @@ public class HdmiControlService extends SystemService {
if (audioSystem != null) {
audioSystem.setIsActiveSource(false);
}
- setActiveSource(playback.mAddress, physicalAddress);
} else {
if (audioSystem != null) {
audioSystem.setIsActiveSource(true);
audioSystem.wakeUpIfActiveSource();
audioSystem.maySendActiveSource(sourceAddress);
- setActiveSource(audioSystem.mAddress, physicalAddress);
}
}
}
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index 2672f848f192..7bbcdaa2d473 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -43,6 +43,7 @@ import com.android.internal.infra.AbstractRemoteService;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -299,16 +300,16 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
}
@Override // from SystemService
- public void onUnlockUser(int userId) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
synchronized (mLock) {
- updateCachedServiceLocked(userId);
+ updateCachedServiceLocked(user.getUserIdentifier());
}
}
@Override // from SystemService
- public void onCleanupUser(int userId) {
+ public void onUserStopped(@NonNull TargetUser user) {
synchronized (mLock) {
- removeCachedServiceLocked(userId);
+ removeCachedServiceLocked(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 254285dfbd41..3cd70fecbf3d 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -159,6 +159,7 @@ import com.android.internal.view.InputBindResult;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.inputmethod.InputMethodManagerInternal.InputMethodListListener;
import com.android.server.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
import com.android.server.inputmethod.InputMethodUtils.InputMethodSettings;
@@ -1596,10 +1597,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
@Override
- public void onSwitchUser(@UserIdInt int userHandle) {
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
// Called on ActivityManager thread.
synchronized (mService.mMethodMap) {
- mService.scheduleSwitchUserTaskLocked(userHandle, null /* clientToBeReset */);
+ mService.scheduleSwitchUserTaskLocked(to.getUserIdentifier(),
+ /* clientToBeReset= */ null);
}
}
@@ -1615,10 +1617,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
@Override
- public void onUnlockUser(final @UserIdInt int userHandle) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
// Called on ActivityManager thread.
mService.mHandler.sendMessage(mService.mHandler.obtainMessage(MSG_SYSTEM_UNLOCK_USER,
- userHandle /* arg1 */, 0 /* arg2 */));
+ /* arg1= */ user.getUserIdentifier(), /* arg2= */ 0));
}
}
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 2516e289f099..937514ca9139 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -94,6 +94,7 @@ import com.android.internal.view.InlineSuggestionsRequestInfo;
import com.android.internal.view.InputBindResult;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.wm.WindowManagerInternal;
import java.io.FileDescriptor;
@@ -249,23 +250,26 @@ public final class MultiClientInputMethodManagerService {
@MainThread
@Override
- public void onStartUser(@UserIdInt int userId) {
+ public void onUserStarting(@NonNull TargetUser user) {
mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
- OnWorkerThreadCallback::onStartUser, mOnWorkerThreadCallback, userId));
+ OnWorkerThreadCallback::onStartUser, mOnWorkerThreadCallback,
+ user.getUserIdentifier()));
}
@MainThread
@Override
- public void onUnlockUser(@UserIdInt int userId) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
- OnWorkerThreadCallback::onUnlockUser, mOnWorkerThreadCallback, userId));
+ OnWorkerThreadCallback::onUnlockUser, mOnWorkerThreadCallback,
+ user.getUserIdentifier()));
}
@MainThread
@Override
- public void onStopUser(@UserIdInt int userId) {
+ public void onUserStopping(@NonNull TargetUser user) {
mOnWorkerThreadCallback.getHandler().sendMessage(PooledLambda.obtainMessage(
- OnWorkerThreadCallback::onStopUser, mOnWorkerThreadCallback, userId));
+ OnWorkerThreadCallback::onStopUser, mOnWorkerThreadCallback,
+ user.getUserIdentifier()));
}
}
diff --git a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
index e29471bdfd6b..eed1aac79166 100644
--- a/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
+++ b/services/core/java/com/android/server/location/HardwareActivityRecognitionProxy.java
@@ -17,6 +17,7 @@
package com.android.server.location;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
import android.hardware.location.ActivityRecognitionHardware;
import android.hardware.location.IActivityRecognitionHardwareClient;
@@ -77,7 +78,7 @@ public class HardwareActivityRecognitionProxy {
return mServiceWatcher.register();
}
- private void onBind(IBinder binder) throws RemoteException {
+ private void onBind(IBinder binder, ComponentName service) throws RemoteException {
String descriptor = binder.getInterfaceDescriptor();
if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals(descriptor)) {
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 2bcee2faa813..d778d242f571 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -19,6 +19,7 @@ package com.android.server.location;
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
import android.location.Location;
import android.location.util.identity.CallerIdentity;
@@ -32,10 +33,12 @@ import com.android.internal.location.ILocationProvider;
import com.android.internal.location.ILocationProviderManager;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
+import com.android.internal.util.ArrayUtils;
import com.android.server.ServiceWatcher;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Objects;
/**
* Proxy for ILocationProvider implementations.
@@ -65,6 +68,8 @@ public class LocationProviderProxy extends AbstractLocationProvider {
@GuardedBy("mLock")
Proxy mProxy;
+ @GuardedBy("mLock")
+ @Nullable ComponentName mService;
private volatile ProviderRequest mRequest;
@@ -86,11 +91,12 @@ public class LocationProviderProxy extends AbstractLocationProvider {
return mServiceWatcher.register();
}
- private void onBind(IBinder binder) throws RemoteException {
+ private void onBind(IBinder binder, ComponentName service) throws RemoteException {
ILocationProvider provider = ILocationProvider.Stub.asInterface(binder);
synchronized (mLock) {
mProxy = new Proxy();
+ mService = service;
provider.setLocationProviderManager(mProxy);
ProviderRequest request = mRequest;
@@ -103,6 +109,7 @@ public class LocationProviderProxy extends AbstractLocationProvider {
private void onUnbind() {
synchronized (mLock) {
mProxy = null;
+ mService = null;
setState(State.EMPTY_STATE);
}
}
@@ -111,16 +118,16 @@ public class LocationProviderProxy extends AbstractLocationProvider {
public void onSetRequest(ProviderRequest request) {
mRequest = request;
mServiceWatcher.runOnBinder(binder -> {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- service.setRequest(request, request.workSource);
+ ILocationProvider provider = ILocationProvider.Stub.asInterface(binder);
+ provider.setRequest(request, request.workSource);
});
}
@Override
public void onExtraCommand(int uid, int pid, String command, Bundle extras) {
mServiceWatcher.runOnBinder(binder -> {
- ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
- service.sendExtraCommand(command, extras);
+ ILocationProvider provider = ILocationProvider.Stub.asInterface(binder);
+ provider.sendExtraCommand(command, extras);
});
}
@@ -129,12 +136,14 @@ public class LocationProviderProxy extends AbstractLocationProvider {
mServiceWatcher.dump(fd, pw, args);
}
- private static String guessPackageName(Context context, int uid) {
+ private static String guessPackageName(Context context, int uid, String packageName) {
String[] packageNames = context.getPackageManager().getPackagesForUid(uid);
if (packageNames == null || packageNames.length == 0) {
// illegal state exception will propagate back through binders
throw new IllegalStateException(
"location provider from uid " + uid + " has no package information");
+ } else if (ArrayUtils.contains(packageNames, packageName)) {
+ return packageName;
} else {
return packageNames[0];
}
@@ -154,7 +163,8 @@ public class LocationProviderProxy extends AbstractLocationProvider {
CallerIdentity identity;
if (packageName == null) {
- packageName = guessPackageName(mContext, Binder.getCallingUid());
+ packageName = guessPackageName(mContext, Binder.getCallingUid(),
+ Objects.requireNonNull(mService).getPackageName());
// unsafe is ok since the package is coming direct from the package manager here
identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag);
} else {
@@ -175,7 +185,8 @@ public class LocationProviderProxy extends AbstractLocationProvider {
// if no identity is set yet, set it now
if (getIdentity() == null) {
- String packageName = guessPackageName(mContext, Binder.getCallingUid());
+ String packageName = guessPackageName(mContext, Binder.getCallingUid(),
+ Objects.requireNonNull(mService).getPackageName());
// unsafe is ok since the package is coming direct from the package manager here
setIdentity(CallerIdentity.fromBinderUnsafe(packageName, null));
}
diff --git a/services/core/java/com/android/server/location/geofence/GeofenceProxy.java b/services/core/java/com/android/server/location/geofence/GeofenceProxy.java
index 2218079c7889..686a66bb4d97 100644
--- a/services/core/java/com/android/server/location/geofence/GeofenceProxy.java
+++ b/services/core/java/com/android/server/location/geofence/GeofenceProxy.java
@@ -63,7 +63,7 @@ public final class GeofenceProxy {
private GeofenceProxy(Context context, IGpsGeofenceHardware gpsGeofence) {
mGpsGeofenceHardware = Objects.requireNonNull(gpsGeofence);
mServiceWatcher = new ServiceWatcher(context, SERVICE_ACTION,
- this::updateGeofenceHardware, null,
+ (binder, service) -> updateGeofenceHardware(binder), null,
com.android.internal.R.bool.config_enableGeofenceOverlay,
com.android.internal.R.string.config_geofenceProviderPackageName);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index e56884832f0f..f1b89c7a433c 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -123,6 +123,7 @@ import com.android.internal.widget.VerifyCredentialResponse;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.locksettings.LockSettingsStorage.CredentialHash;
import com.android.server.locksettings.LockSettingsStorage.PersistentData;
import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
@@ -275,18 +276,18 @@ public class LockSettingsService extends ILockSettings.Stub {
}
@Override
- public void onStartUser(int userHandle) {
- mLockSettingsService.onStartUser(userHandle);
+ public void onUserStarting(@NonNull TargetUser user) {
+ mLockSettingsService.onStartUser(user.getUserIdentifier());
}
@Override
- public void onUnlockUser(int userHandle) {
- mLockSettingsService.onUnlockUser(userHandle);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mLockSettingsService.onUnlockUser(user.getUserIdentifier());
}
@Override
- public void onCleanupUser(int userHandle) {
- mLockSettingsService.onCleanupUser(userHandle);
+ public void onUserStopped(@NonNull TargetUser user) {
+ mLockSettingsService.onCleanupUser(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
index 9dae1b44117b..b9997e0c2ec8 100644
--- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
+++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
@@ -221,8 +221,8 @@ final class MediaButtonReceiverHolder {
context.startActivityAsUser(mediaButtonIntent, userHandle);
break;
case COMPONENT_TYPE_SERVICE:
- context.startForegroundServiceAsUser(mediaButtonIntent,
- userHandle);
+ context.createContextAsUser(userHandle, 0).startForegroundService(
+ mediaButtonIntent);
break;
default:
// Legacy behavior for other cases.
diff --git a/services/core/java/com/android/server/media/MediaResourceMonitorService.java b/services/core/java/com/android/server/media/MediaResourceMonitorService.java
index 6669b8cec143..e5da9b1c178c 100644
--- a/services/core/java/com/android/server/media/MediaResourceMonitorService.java
+++ b/services/core/java/com/android/server/media/MediaResourceMonitorService.java
@@ -25,7 +25,6 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
-import android.util.Slog;
import com.android.server.SystemService;
@@ -53,7 +52,7 @@ public class MediaResourceMonitorService extends SystemService {
public void notifyResourceGranted(int pid, int type)
throws RemoteException {
if (DEBUG) {
- Slog.d(TAG, "notifyResourceGranted(pid=" + pid + ", type=" + type + ")");
+ Log.d(TAG, "notifyResourceGranted(pid=" + pid + ", type=" + type + ")");
}
final long identity = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 9f6c18d5ec72..e2f70e320cb8 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -25,6 +25,8 @@ import static com.android.server.media.MediaKeyDispatcher.isLongPressOverridden;
import static com.android.server.media.MediaKeyDispatcher.isSingleTapOverridden;
import static com.android.server.media.MediaKeyDispatcher.isTripleTapOverridden;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.app.NotificationManager;
@@ -85,6 +87,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.Watchdog;
import com.android.server.Watchdog.Monitor;
@@ -333,19 +336,21 @@ public class MediaSessionService extends SystemService implements Monitor {
}
@Override
- public void onStartUser(int userId) {
- if (DEBUG) Log.d(TAG, "onStartUser: " + userId);
+ public void onUserStarting(@NonNull TargetUser user) {
+ if (DEBUG) Log.d(TAG, "onStartUser: " + user);
updateUser();
}
@Override
- public void onSwitchUser(int userId) {
- if (DEBUG) Log.d(TAG, "onSwitchUser: " + userId);
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+ if (DEBUG) Log.d(TAG, "onSwitchUser: " + to);
updateUser();
}
@Override
- public void onCleanupUser(int userId) {
+ public void onUserStopped(@NonNull TargetUser targetUser) {
+ int userId = targetUser.getUserIdentifier();
+
if (DEBUG) Log.d(TAG, "onCleanupUser: " + userId);
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(userId);
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 1a749b34d85e..94776f8c7cb4 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -17,6 +17,8 @@
package com.android.server.media.projection;
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.IProcessObserver;
@@ -48,6 +50,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.Watchdog;
import java.io.FileDescriptor;
@@ -122,8 +125,8 @@ public final class MediaProjectionManagerService extends SystemService
}
@Override
- public void onSwitchUser(int userId) {
- mMediaRouter.rebindAsUser(userId);
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+ mMediaRouter.rebindAsUser(to.getUserIdentifier());
synchronized (mLock) {
if (mProjectionGrant != null) {
mProjectionGrant.stop();
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 05ab2ae87aa5..342a11b87aa5 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -28,6 +28,7 @@ import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
+import static android.net.NetworkUtils.multiplySafeByRational;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static com.android.server.net.NetworkStatsService.TAG;
@@ -185,35 +186,6 @@ public class NetworkStatsCollection implements FileRotator.Reader {
}
}
- /**
- * Safely multiple a value by a rational.
- * <p>
- * Internally it uses integer-based math whenever possible, but switches
- * over to double-based math if values would overflow.
- */
- @VisibleForTesting
- public static long multiplySafe(long value, long num, long den) {
- if (den == 0) den = 1;
- long x = value;
- long y = num;
-
- // Logic shamelessly borrowed from Math.multiplyExact()
- long r = x * y;
- long ax = Math.abs(x);
- long ay = Math.abs(y);
- if (((ax | ay) >>> 31 != 0)) {
- // Some bits greater than 2^31 that might cause overflow
- // Check the result using the divide operator
- // and check for the special case of Long.MIN_VALUE * -1
- if (((y != 0) && (r / y != x)) ||
- (x == Long.MIN_VALUE && y == -1)) {
- // Use double math to avoid overflowing
- return (long) (((double) num / den) * value);
- }
- }
- return r / den;
- }
-
public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) {
return getRelevantUids(accessLevel, Binder.getCallingUid());
}
@@ -311,11 +283,13 @@ public class NetworkStatsCollection implements FileRotator.Reader {
}
final long rawBytes = entry.rxBytes + entry.txBytes;
- final long rawRxBytes = entry.rxBytes;
- final long rawTxBytes = entry.txBytes;
+ final long rawRxBytes = entry.rxBytes == 0 ? 1 : entry.rxBytes;
+ final long rawTxBytes = entry.txBytes == 0 ? 1 : entry.txBytes;
final long targetBytes = augmentPlan.getDataUsageBytes();
- final long targetRxBytes = multiplySafe(targetBytes, rawRxBytes, rawBytes);
- final long targetTxBytes = multiplySafe(targetBytes, rawTxBytes, rawBytes);
+
+ final long targetRxBytes = multiplySafeByRational(targetBytes, rawRxBytes, rawBytes);
+ final long targetTxBytes = multiplySafeByRational(targetBytes, rawTxBytes, rawBytes);
+
// Scale all matching buckets to reach anchor target
final long beforeTotal = combined.getTotalBytes();
@@ -323,8 +297,10 @@ public class NetworkStatsCollection implements FileRotator.Reader {
combined.getValues(i, entry);
if (entry.bucketStart >= augmentStart
&& entry.bucketStart + entry.bucketDuration <= augmentEnd) {
- entry.rxBytes = multiplySafe(targetRxBytes, entry.rxBytes, rawRxBytes);
- entry.txBytes = multiplySafe(targetTxBytes, entry.txBytes, rawTxBytes);
+ entry.rxBytes = multiplySafeByRational(
+ targetRxBytes, entry.rxBytes, rawRxBytes);
+ entry.txBytes = multiplySafeByRational(
+ targetTxBytes, entry.txBytes, rawTxBytes);
// We purposefully clear out packet counters to indicate
// that this data has been augmented.
entry.rxPackets = 0;
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 86ad0b308676..e9868fde3059 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -59,7 +59,7 @@ public class NetworkStatsFactory {
private static final String TAG = "NetworkStatsFactory";
private static final boolean USE_NATIVE_PARSING = true;
- private static final boolean SANITY_CHECK_NATIVE = false;
+ private static final boolean VALIDATE_NATIVE_STATS = false;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
private final File mStatsXtIfaceAll;
@@ -347,7 +347,7 @@ public class NetworkStatsFactory {
INTERFACES_ALL, TAG_ALL, mUseBpfStats) != 0) {
throw new IOException("Failed to parse network stats");
}
- if (SANITY_CHECK_NATIVE) {
+ if (VALIDATE_NATIVE_STATS) {
final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid,
UID_ALL, INTERFACES_ALL, TAG_ALL);
assertEquals(javaStats, stats);
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index 9eff5d1648bd..ce741693cb4b 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -227,7 +227,7 @@ public class NetworkStatsRecorder {
for (int i = 0; i < delta.size(); i++) {
entry = delta.getValues(i, entry);
- // As a last-ditch sanity check, report any negative values and
+ // As a last-ditch check, report any negative values and
// clamp them so recording below doesn't croak.
if (entry.isNegative()) {
if (mObserver != null) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index cf08e735bbd2..d71c33e6e6f5 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -261,6 +261,7 @@ import com.android.server.EventLogTags;
import com.android.server.IoThread;
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.lights.LightsManager;
import com.android.server.lights.LogicalLight;
@@ -322,7 +323,7 @@ public class NotificationManagerService extends SystemService {
static final boolean DEBUG_INTERRUPTIVENESS = SystemProperties.getBoolean(
"debug.notification.interruptiveness", false);
- static final int MAX_PACKAGE_NOTIFICATIONS = 25;
+ static final int MAX_PACKAGE_NOTIFICATIONS = 50;
static final float DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE = 5f;
// message codes
@@ -2351,11 +2352,11 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public void onUnlockUser(@NonNull UserInfo userInfo) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
mHandler.post(() -> {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "notifHistoryUnlockUser");
try {
- mHistoryManager.onUserUnlocked(userInfo.id);
+ mHistoryManager.onUserUnlocked(user.getUserIdentifier());
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
@@ -2363,11 +2364,11 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public void onStopUser(@NonNull UserInfo userInfo) {
+ public void onUserStopping(@NonNull TargetUser user) {
mHandler.post(() -> {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "notifHistoryStopUser");
try {
- mHistoryManager.onUserStopped(userInfo.id);
+ mHistoryManager.onUserStopped(user.getUserIdentifier());
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
@@ -4861,7 +4862,6 @@ public class NotificationManagerService extends SystemService {
// calculate the final importance here
r.calculateImportance();
foundEnqueued = true;
- break;
}
}
if (!foundEnqueued) {
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index d6b1b27360ca..cb6e960b721d 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -27,6 +27,7 @@ import android.content.pm.PackageInfo;
import android.os.Build.VERSION_CODES;
import android.os.OverlayablePolicy;
import android.os.SystemProperties;
+import android.text.TextUtils;
import android.util.Slog;
import java.io.IOException;
@@ -53,11 +54,20 @@ final class IdmapManager {
}
private final IdmapDaemon mIdmapDaemon;
- private final OverlayableInfoCallback mOverlayableCallback;
+ private final PackageManagerHelper mPackageManager;
- IdmapManager(final IdmapDaemon idmapDaemon, final OverlayableInfoCallback verifyCallback) {
- mOverlayableCallback = verifyCallback;
+ /**
+ * Package name of the reference package defined in 'config-signature' tag of
+ * SystemConfig or empty String if tag not defined. This package is vetted on scan by
+ * PackageManagerService that it's a system package and is used to check if overlay matches
+ * its signature in order to fulfill the config_signature policy.
+ */
+ private final String mConfigSignaturePackage;
+
+ IdmapManager(final IdmapDaemon idmapDaemon, final PackageManagerHelper packageManager) {
+ mPackageManager = packageManager;
mIdmapDaemon = idmapDaemon;
+ mConfigSignaturePackage = packageManager.getConfigSignaturePackage();
}
/**
@@ -139,7 +149,7 @@ final class IdmapManager {
int fulfilledPolicies = OverlayablePolicy.PUBLIC;
// Overlay matches target signature
- if (mOverlayableCallback.signaturesMatching(targetPackage.packageName,
+ if (mPackageManager.signaturesMatching(targetPackage.packageName,
overlayPackage.packageName, userId)) {
fulfilledPolicies |= OverlayablePolicy.SIGNATURE;
}
@@ -149,6 +159,16 @@ final class IdmapManager {
fulfilledPolicies |= OverlayablePolicy.ACTOR_SIGNATURE;
}
+ // If SystemConfig defines 'config-signature' package, given that
+ // this package is vetted by OverlayManagerService that it's a
+ // preinstalled package, check if overlay matches its signature.
+ if (!TextUtils.isEmpty(mConfigSignaturePackage)
+ && mPackageManager.signaturesMatching(mConfigSignaturePackage,
+ overlayPackage.packageName,
+ userId)) {
+ fulfilledPolicies |= OverlayablePolicy.CONFIG_SIGNATURE;
+ }
+
// Vendor partition (/vendor)
if (ai.isVendor()) {
return fulfilledPolicies | OverlayablePolicy.VENDOR_PARTITION;
@@ -183,12 +203,12 @@ final class IdmapManager {
String targetOverlayableName = overlayPackage.targetOverlayableName;
if (targetOverlayableName != null) {
try {
- OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget(
+ OverlayableInfo overlayableInfo = mPackageManager.getOverlayableForTarget(
targetPackage.packageName, targetOverlayableName, userId);
if (overlayableInfo != null && overlayableInfo.actor != null) {
String actorPackageName = OverlayActorEnforcer.getPackageNameForActor(
- overlayableInfo.actor, mOverlayableCallback.getNamedActors()).first;
- if (mOverlayableCallback.signaturesMatching(actorPackageName,
+ overlayableInfo.actor, mPackageManager.getNamedActors()).first;
+ if (mPackageManager.signaturesMatching(actorPackageName,
overlayPackage.packageName, userId)) {
return true;
}
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
index 2bc34998785b..8c03c6ce3092 100644
--- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
@@ -45,7 +45,7 @@ public class OverlayActorEnforcer {
// By default, the reason is not logged to prevent leaks of why it failed
private static final boolean DEBUG_REASON = false;
- private final OverlayableInfoCallback mOverlayableCallback;
+ private final PackageManagerHelper mPackageManager;
/**
* @return nullable actor result with {@link ActorState} failure status
@@ -79,8 +79,8 @@ public class OverlayActorEnforcer {
return Pair.create(packageName, ActorState.ALLOWED);
}
- public OverlayActorEnforcer(@NonNull OverlayableInfoCallback overlayableCallback) {
- mOverlayableCallback = overlayableCallback;
+ public OverlayActorEnforcer(@NonNull PackageManagerHelper packageManager) {
+ mPackageManager = packageManager;
}
void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName,
@@ -110,7 +110,7 @@ public class OverlayActorEnforcer {
return ActorState.ALLOWED;
}
- String[] callingPackageNames = mOverlayableCallback.getPackagesForUid(callingUid);
+ String[] callingPackageNames = mPackageManager.getPackagesForUid(callingUid);
if (ArrayUtils.isEmpty(callingPackageNames)) {
return ActorState.NO_PACKAGES_FOR_UID;
}
@@ -125,12 +125,12 @@ public class OverlayActorEnforcer {
if (TextUtils.isEmpty(targetOverlayableName)) {
try {
- if (mOverlayableCallback.doesTargetDefineOverlayable(targetPackageName, userId)) {
+ if (mPackageManager.doesTargetDefineOverlayable(targetPackageName, userId)) {
return ActorState.MISSING_TARGET_OVERLAYABLE_NAME;
} else {
// If there's no overlayable defined, fallback to the legacy permission check
try {
- mOverlayableCallback.enforcePermission(
+ mPackageManager.enforcePermission(
android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
// If the previous method didn't throw, check passed
@@ -146,7 +146,7 @@ public class OverlayActorEnforcer {
OverlayableInfo targetOverlayable;
try {
- targetOverlayable = mOverlayableCallback.getOverlayableForTarget(targetPackageName,
+ targetOverlayable = mPackageManager.getOverlayableForTarget(targetPackageName,
targetOverlayableName, userId);
} catch (IOException e) {
return ActorState.UNABLE_TO_GET_TARGET;
@@ -160,7 +160,7 @@ public class OverlayActorEnforcer {
if (TextUtils.isEmpty(actor)) {
// If there's no actor defined, fallback to the legacy permission check
try {
- mOverlayableCallback.enforcePermission(
+ mPackageManager.enforcePermission(
android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
// If the previous method didn't throw, check passed
@@ -170,7 +170,7 @@ public class OverlayActorEnforcer {
}
}
- Map<String, Map<String, String>> namedActors = mOverlayableCallback.getNamedActors();
+ Map<String, Map<String, String>> namedActors = mPackageManager.getNamedActors();
Pair<String, ActorState> actorUriPair = getPackageNameForActor(actor, namedActors);
ActorState actorUriState = actorUriPair.second;
if (actorUriState != ActorState.ALLOWED) {
@@ -178,7 +178,7 @@ public class OverlayActorEnforcer {
}
String packageName = actorUriPair.first;
- PackageInfo packageInfo = mOverlayableCallback.getPackageInfo(packageName, userId);
+ PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, userId);
if (packageInfo == null) {
return ActorState.MISSING_APP_INFO;
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 396815399874..a4debc16493a 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -31,6 +31,7 @@ import static android.os.Trace.traceEnd;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.BroadcastReceiver;
@@ -68,6 +69,7 @@ import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.pm.UserManagerService;
import libcore.util.EmptyArray;
@@ -303,7 +305,11 @@ public final class OverlayManagerService extends SystemService {
}
@Override
- public void onSwitchUser(final int newUserId) {
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+ onSwitchUser(to.getUserIdentifier());
+ }
+
+ private void onSwitchUser(@UserIdInt int newUserId) {
try {
traceBegin(TRACE_TAG_RRO, "OMS#onSwitchUser " + newUserId);
// ensure overlays in the settings are up-to-date, and propagate
@@ -1053,8 +1059,7 @@ public final class OverlayManagerService extends SystemService {
}
}
- private static final class PackageManagerHelperImpl implements PackageManagerHelper,
- OverlayableInfoCallback {
+ private static final class PackageManagerHelperImpl implements PackageManagerHelper {
private final Context mContext;
private final IPackageManager mPackageManager;
@@ -1127,6 +1132,14 @@ public final class OverlayManagerService extends SystemService {
return overlays;
}
+ @Override
+ public String getConfigSignaturePackage() {
+ final String[] pkgs = mPackageManagerInternal.getKnownPackageNames(
+ PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE,
+ UserHandle.USER_SYSTEM);
+ return (pkgs.length == 0) ? null : pkgs[0];
+ }
+
@Nullable
@Override
public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
diff --git a/services/core/java/com/android/server/om/OverlayReferenceMapper.java b/services/core/java/com/android/server/om/OverlayReferenceMapper.java
index cadb8e4746f3..a9dbb2f29535 100644
--- a/services/core/java/com/android/server/om/OverlayReferenceMapper.java
+++ b/services/core/java/com/android/server/om/OverlayReferenceMapper.java
@@ -18,14 +18,15 @@ package com.android.server.om;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import android.text.TextUtils;
import android.util.Pair;
+import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.CollectionUtils;
import com.android.server.SystemConfig;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.util.Collections;
import java.util.HashMap;
@@ -72,6 +73,8 @@ import java.util.Set;
*/
public class OverlayReferenceMapper {
+ private static final String TAG = "OverlayReferenceMapper";
+
private final Object mLock = new Object();
/**
@@ -144,7 +147,7 @@ public class OverlayReferenceMapper {
public boolean isValidActor(@NonNull String targetName, @NonNull String actorPackageName) {
synchronized (mLock) {
- assertMapBuilt();
+ ensureMapBuilt();
Set<String> validSet = mActorPkgToPkgs.get(actorPackageName);
return validSet != null && validSet.contains(targetName);
}
@@ -292,10 +295,11 @@ public class OverlayReferenceMapper {
}
}
- private void assertMapBuilt() {
+ private void ensureMapBuilt() {
if (mDeferRebuild) {
- throw new IllegalStateException("The actor map must be built by calling "
- + "rebuildIfDeferred before it is queried");
+ rebuildIfDeferred();
+ Slog.w(TAG, "The actor map was queried before the system was ready, which may"
+ + "result in decreased performance.");
}
}
@@ -360,7 +364,7 @@ public class OverlayReferenceMapper {
* Given the actor string from an overlayable definition, return the actor's package name.
*/
@Nullable
- String getActorPkg(String actor);
+ String getActorPkg(@NonNull String actor);
/**
* Mock response of multiple overlay tags.
diff --git a/services/core/java/com/android/server/om/OverlayableInfoCallback.java b/services/core/java/com/android/server/om/OverlayableInfoCallback.java
deleted file mode 100644
index 5066ecdd6316..000000000000
--- a/services/core/java/com/android/server/om/OverlayableInfoCallback.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.om;
-
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.om.OverlayableInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-
-import com.android.server.pm.PackageManagerServiceUtils;
-
-import java.io.IOException;
-import java.util.Map;
-
-/**
- * Delegate to the system for querying information about overlayables and packages.
- */
-public interface OverlayableInfoCallback {
-
- /**
- * Read from the APK and AndroidManifest of a package to return the overlayable defined for
- * a given name.
- *
- * @throws IOException if the target can't be read
- */
- @Nullable
- OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
- @NonNull String targetOverlayableName, int userId)
- throws IOException;
-
- /**
- * @see PackageManager#getPackagesForUid(int)
- */
- @Nullable
- String[] getPackagesForUid(int uid);
-
- /**
- * @param userId user to filter package visibility by
- * @see PackageManager#getPackageInfo(String, int)
- */
- @Nullable
- PackageInfo getPackageInfo(@NonNull String packageName, int userId);
-
- /**
- * @return map of system pre-defined, uniquely named actors; keys are namespace,
- * value maps actor name to package name
- */
- @NonNull
- Map<String, Map<String, String>> getNamedActors();
-
- /**
- * @return true if the target package has declared an overlayable
- */
- boolean doesTargetDefineOverlayable(String targetPackageName, int userId) throws IOException;
-
- /**
- * @throws SecurityException containing message if the caller doesn't have the given
- * permission
- */
- void enforcePermission(String permission, String message) throws SecurityException;
-
- /**
- * @return true if {@link PackageManagerServiceUtils#compareSignatures} run on both packages
- * in the system returns {@link PackageManager#SIGNATURE_MATCH}
- */
- boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
-}
diff --git a/services/core/java/com/android/server/om/PackageManagerHelper.java b/services/core/java/com/android/server/om/PackageManagerHelper.java
index ec9c5e64e390..b1a8b4ee4d9f 100644
--- a/services/core/java/com/android/server/om/PackageManagerHelper.java
+++ b/services/core/java/com/android/server/om/PackageManagerHelper.java
@@ -17,11 +17,17 @@
package com.android.server.om;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.om.OverlayableInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import com.android.server.pm.PackageManagerServiceUtils;
+
+import java.io.IOException;
import java.util.List;
+import java.util.Map;
/**
* Delegate for {@link PackageManager} and {@link PackageManagerInternal} functionality,
@@ -30,7 +36,65 @@ import java.util.List;
* @hide
*/
interface PackageManagerHelper {
+ /**
+ * @return true if the target package has declared an overlayable
+ */
+ boolean doesTargetDefineOverlayable(String targetPackageName, int userId) throws IOException;
+
+ /**
+ * @throws SecurityException containing message if the caller doesn't have the given
+ * permission
+ */
+ void enforcePermission(String permission, String message) throws SecurityException;
+
+ /**
+ * Returns the package name of the reference package defined in 'overlay-config-signature' tag
+ * of SystemConfig. This package is vetted on scan by PackageManagerService that it's a system
+ * package and is used to check if overlay matches its signature in order to fulfill the
+ * config_signature policy.
+ */
+ @Nullable
+ String getConfigSignaturePackage();
+
+ /**
+ * @return map of system pre-defined, uniquely named actors; keys are namespace,
+ * value maps actor name to package name
+ */
+ @NonNull
+ Map<String, Map<String, String>> getNamedActors();
+
+ /**
+ * @see PackageManagerInternal#getOverlayPackages(int)
+ */
+ List<PackageInfo> getOverlayPackages(int userId);
+
+ /**
+ * Read from the APK and AndroidManifest of a package to return the overlayable defined for
+ * a given name.
+ *
+ * @throws IOException if the target can't be read
+ */
+ @Nullable
+ OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
+ @NonNull String targetOverlayableName, int userId)
+ throws IOException;
+
+ /**
+ * @see PackageManager#getPackagesForUid(int)
+ */
+ @Nullable
+ String[] getPackagesForUid(int uid);
+
+ /**
+ * @param userId user to filter package visibility by
+ * @see PackageManager#getPackageInfo(String, int)
+ */
+ @Nullable
PackageInfo getPackageInfo(@NonNull String packageName, int userId);
+
+ /**
+ * @return true if {@link PackageManagerServiceUtils#compareSignatures} run on both packages
+ * in the system returns {@link PackageManager#SIGNATURE_MATCH}
+ */
boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
- List<PackageInfo> getOverlayPackages(int userId);
}
diff --git a/services/core/java/com/android/server/os/TEST_MAPPING b/services/core/java/com/android/server/os/TEST_MAPPING
index a837fb4184ba..d937af1e3fdb 100644
--- a/services/core/java/com/android/server/os/TEST_MAPPING
+++ b/services/core/java/com/android/server/os/TEST_MAPPING
@@ -1,6 +1,14 @@
{
"presubmit": [
- // TODO(159590499) add BugreportManagerTestCases
+ {
+ "file_patterns": ["Bugreport[^/]*\\.java"],
+ "name": "BugreportManagerTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.LargeTest"
+ }
+ ]
+ },
{
"file_patterns": ["Bugreport[^/]*\\.java"],
"name": "CtsBugreportTestCases",
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index c3c2e5e65103..92c0c6af17d4 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -137,11 +137,11 @@ public class AppsFilter {
@VisibleForTesting(visibility = PRIVATE)
AppsFilter(StateProvider stateProvider,
FeatureConfig featureConfig,
- String[] forceQueryableWhitelist,
+ String[] forceQueryableList,
boolean systemAppsQueryable,
@Nullable OverlayReferenceMapper.Provider overlayProvider) {
mFeatureConfig = featureConfig;
- mForceQueryableByDevicePackageNames = forceQueryableWhitelist;
+ mForceQueryableByDevicePackageNames = forceQueryableList;
mSystemAppsQueryable = systemAppsQueryable;
mOverlayReferenceMapper = new OverlayReferenceMapper(true /*deferRebuild*/,
overlayProvider);
@@ -746,11 +746,11 @@ public class AppsFilter {
* @param users the set of users that should be evaluated for this calculation
* @param existingSettings the set of all package settings that currently exist on device
* @return a SparseArray mapping userIds to a sorted int array of appIds that may view the
- * provided setting or null if the app is visible to all and no whitelist should be
+ * provided setting or null if the app is visible to all and no allow list should be
* applied.
*/
@Nullable
- public SparseArray<int[]> getVisibilityWhitelist(PackageSetting setting, int[] users,
+ public SparseArray<int[]> getVisibilityAllowList(PackageSetting setting, int[] users,
ArrayMap<String, PackageSetting> existingSettings) {
if (mForceQueryable.contains(setting.appId)) {
return null;
@@ -761,14 +761,14 @@ public class AppsFilter {
final int userId = users[u];
int[] appIds = new int[existingSettings.size()];
int[] buffer = null;
- int whitelistSize = 0;
+ int allowListSize = 0;
for (int i = existingSettings.size() - 1; i >= 0; i--) {
final PackageSetting existingSetting = existingSettings.valueAt(i);
final int existingAppId = existingSetting.appId;
if (existingAppId < Process.FIRST_APPLICATION_UID) {
continue;
}
- final int loc = Arrays.binarySearch(appIds, 0, whitelistSize, existingAppId);
+ final int loc = Arrays.binarySearch(appIds, 0, allowListSize, existingAppId);
if (loc >= 0) {
continue;
}
@@ -778,13 +778,13 @@ public class AppsFilter {
buffer = new int[appIds.length];
}
final int insert = ~loc;
- System.arraycopy(appIds, insert, buffer, 0, whitelistSize - insert);
+ System.arraycopy(appIds, insert, buffer, 0, allowListSize - insert);
appIds[insert] = existingAppId;
- System.arraycopy(buffer, 0, appIds, insert + 1, whitelistSize - insert);
- whitelistSize++;
+ System.arraycopy(buffer, 0, appIds, insert + 1, allowListSize - insert);
+ allowListSize++;
}
}
- result.put(userId, Arrays.copyOf(appIds, whitelistSize));
+ result.put(userId, Arrays.copyOf(appIds, allowListSize));
}
return result;
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 5415967c3bdc..d48570fa3b0f 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -337,6 +337,7 @@ public class BackgroundDexOptService extends JobService {
private int idleOptimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
long lowStorageThreshold) {
ArraySet<String> updatedPackages = new ArraySet<>();
+ ArraySet<String> updatedPackagesDueToSecondaryDex = new ArraySet<>();
try {
final boolean supportSecondaryDex = supportSecondaryDex();
@@ -391,11 +392,14 @@ public class BackgroundDexOptService extends JobService {
}
int secondaryResult = optimizePackages(pm, pkgs, lowStorageThreshold,
- /*isForPrimaryDex*/ false, updatedPackages);
+ /*isForPrimaryDex*/ false, updatedPackagesDueToSecondaryDex);
return secondaryResult;
} finally {
// Always let the pinner service know about changes.
notifyPinService(updatedPackages);
+ // Only notify IORap the primary dex opt, because we don't want to
+ // invalidate traces unnecessary due to b/161633001 and that it's
+ // better to have a trace than no trace at all.
notifyPackagesUpdated(updatedPackages);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 391a08db6716..7765f18300fe 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -157,6 +157,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@@ -164,10 +165,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final boolean LOGD = true;
private static final String REMOVE_MARKER_EXTENSION = ".removed";
- private static final int MSG_STREAM_VALIDATE_AND_COMMIT = 1;
- private static final int MSG_INSTALL = 2;
- private static final int MSG_ON_PACKAGE_INSTALLED = 3;
- private static final int MSG_SESSION_VERIFICATION_FAILURE = 4;
+ private static final int MSG_ON_SESSION_SEALED = 1;
+ private static final int MSG_STREAM_VALIDATE_AND_COMMIT = 2;
+ private static final int MSG_INSTALL = 3;
+ private static final int MSG_ON_PACKAGE_INSTALLED = 4;
+ private static final int MSG_SESSION_VERIFICATION_FAILURE = 5;
/** XML constants used for persisting a session */
static final String TAG_SESSION = "session";
@@ -261,6 +263,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private final Object mLock = new Object();
+ /**
+ * Used to detect and reject concurrent access to this session object to ensure mutation
+ * to multiple objects like {@link #addChildSessionId} are done atomically.
+ */
+ private final AtomicBoolean mTransactionLock = new AtomicBoolean(false);
+
/** Timestamp of the last time this session changed state */
@GuardedBy("mLock")
private long updatedMillis;
@@ -444,6 +452,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
+ case MSG_ON_SESSION_SEALED:
+ handleSessionSealed();
+ break;
case MSG_STREAM_VALIDATE_AND_COMMIT:
handleStreamValidateAndCommit();
break;
@@ -1172,6 +1183,22 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ dispatchSessionSealed();
+ }
+
+ /**
+ * Kicks off the install flow. The first step is to persist 'sealed' flags
+ * to prevent mutations of hard links created later.
+ */
+ private void dispatchSessionSealed() {
+ mHandler.obtainMessage(MSG_ON_SESSION_SEALED).sendToTarget();
+ }
+
+ private void handleSessionSealed() {
+ assertSealed("dispatchSessionSealed");
+ // Persist the fact that we've sealed ourselves to prevent
+ // mutations of any hard links we create.
+ mCallback.onSessionSealedBlocking(this);
dispatchStreamValidateAndCommit();
}
@@ -1425,11 +1452,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
- // Persist the fact that we've sealed ourselves to prevent
- // mutations of any hard links we create. We do this without holding
- // the session lock, since otherwise it's a lock inversion.
- mCallback.onSessionSealedBlocking(this);
-
return true;
}
@@ -1701,11 +1723,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mInstallerUid = newOwnerAppInfo.uid;
mInstallSource = InstallSource.create(packageName, null, packageName, null);
}
-
- // Persist the fact that we've sealed ourselves to prevent
- // mutations of any hard links we create. We do this without holding
- // the session lock, since otherwise it's a lock inversion.
- mCallback.onSessionSealedBlocking(this);
}
private void handleInstall() {
@@ -1736,7 +1753,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
try {
- installNonStaged(childSessions);
+ verifyNonStaged(childSessions);
} catch (PackageManagerException e) {
final String completeMsg = ExceptionUtils.getCompleteMessage(e);
Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
@@ -1745,23 +1762,64 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ private void verifyNonStaged(List<PackageInstallerSession> childSessions)
+ throws PackageManagerException {
+ final PackageManagerService.VerificationParams verifyingSession =
+ makeVerificationParams();
+ if (verifyingSession == null) {
+ return;
+ }
+ if (isMultiPackage()) {
+ List<PackageManagerService.VerificationParams> verifyingChildSessions =
+ new ArrayList<>(childSessions.size());
+ boolean success = true;
+ PackageManagerException failure = null;
+ for (int i = 0; i < childSessions.size(); ++i) {
+ final PackageInstallerSession session = childSessions.get(i);
+ try {
+ final PackageManagerService.VerificationParams verifyingChildSession =
+ session.makeVerificationParams();
+ if (verifyingChildSession != null) {
+ verifyingChildSessions.add(verifyingChildSession);
+ }
+ } catch (PackageManagerException e) {
+ failure = e;
+ success = false;
+ }
+ }
+ if (!success) {
+ final IntentSender statusReceiver;
+ synchronized (mLock) {
+ statusReceiver = mRemoteStatusReceiver;
+ }
+ sendOnPackageInstalled(mContext, statusReceiver, sessionId,
+ isInstallerDeviceOwnerOrAffiliatedProfileOwner(), userId, null,
+ failure.error, failure.getLocalizedMessage(), null);
+ return;
+ }
+ mPm.verifyStage(verifyingSession, verifyingChildSessions);
+ } else {
+ mPm.verifyStage(verifyingSession);
+ }
+ }
+
private void installNonStaged(List<PackageInstallerSession> childSessions)
throws PackageManagerException {
- final PackageManagerService.ActiveInstallSession installingSession =
- makeSessionActive();
+ final PackageManagerService.InstallParams installingSession =
+ makeInstallParams();
if (installingSession == null) {
return;
}
if (isMultiPackage()) {
- List<PackageManagerService.ActiveInstallSession> installingChildSessions =
+ List<PackageManagerService.InstallParams> installingChildSessions =
new ArrayList<>(childSessions.size());
boolean success = true;
PackageManagerException failure = null;
for (int i = 0; i < childSessions.size(); ++i) {
final PackageInstallerSession session = childSessions.get(i);
try {
- final PackageManagerService.ActiveInstallSession installingChildSession =
- session.makeSessionActive();
+ final PackageManagerService.InstallParams installingChildSession =
+ session.makeInstallParams();
if (installingChildSession != null) {
installingChildSessions.add(installingChildSession);
}
@@ -1787,11 +1845,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
/**
- * Stages this session for install and returns a
- * {@link PackageManagerService.ActiveInstallSession} representing this new staged state or null
- * in case permissions need to be requested before install can proceed.
+ * Stages this session for verification and returns a
+ * {@link PackageManagerService.VerificationParams} representing this new staged state or null
+ * in case permissions need to be requested before verification can proceed.
*/
- private PackageManagerService.ActiveInstallSession makeSessionActive()
+ @Nullable
+ private PackageManagerService.VerificationParams makeVerificationParams()
throws PackageManagerException {
assertNotLocked("makeSessionActive");
@@ -1810,6 +1869,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ // TODO(b/159331446): Move this to makeSessionActiveForInstall and update javadoc
if (!params.isMultiPackage && needToAskForPermissions()) {
// User needs to confirm installation;
// give installer an intent they can use to involve
@@ -1831,12 +1891,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
synchronized (mLock) {
- return makeSessionActiveLocked();
+ return makeVerificationParamsLocked();
}
}
@GuardedBy("mLock")
- private PackageManagerService.ActiveInstallSession makeSessionActiveLocked()
+ private PackageManagerService.VerificationParams makeVerificationParamsLocked()
throws PackageManagerException {
if (!params.isMultiPackage) {
Objects.requireNonNull(mPackageName);
@@ -1900,29 +1960,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
extractNativeLibraries(stageDir, params.abiOverride, mayInheritNativeLibs());
}
- // We've reached point of no return; call into PMS to install the stage.
- // Regardless of success or failure we always destroy session.
- final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
- @Override
- public void onUserActionRequired(Intent intent) {
- throw new IllegalStateException();
- }
-
- @Override
- public void onPackageInstalled(String basePackageName, int returnCode, String msg,
- Bundle extras) {
- destroyInternal();
- dispatchSessionFinished(returnCode, msg, extras);
- }
- };
-
- // An observer through which PMS returns the result of verification
- // TODO(samiul): We are temporarily assigning two observer to ActiveInstallSession. One for
- // installation and one for verification. This will be fixed within next few CLs.
- final IPackageInstallObserver2 sessionVerificationObserver;
+ final IPackageInstallObserver2 localObserver;
if (!hasParentSessionId()) {
// Avoid attaching this observer to child session since they won't use it.
- sessionVerificationObserver = new IPackageInstallObserver2.Stub() {
+ localObserver = new IPackageInstallObserver2.Stub() {
@Override
public void onUserActionRequired(Intent intent) {
throw new IllegalStateException();
@@ -1932,16 +1973,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
Bundle extras) {
if (returnCode == PackageManager.INSTALL_SUCCEEDED) {
- // TODO(samiul): In future, packages will not be installed immediately after
- // verification. Package verification will return control back to here,
- // and we will have call into PMS again to install package.
- //
- // For now, this is a no op.
+ onVerificationComplete();
+ } else {
+ destroyInternal();
+ dispatchSessionFinished(returnCode, msg, extras);
}
}
};
} else {
- sessionVerificationObserver = null;
+ localObserver = null;
}
final UserHandle user;
@@ -1952,9 +1992,73 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
mRelinquished = true;
- return new PackageManagerService.ActiveInstallSession(mPackageName, stageDir, localObserver,
- sessionVerificationObserver, sessionId, params, mInstallerUid, mInstallSource, user,
- mSigningDetails);
+
+ return mPm.new VerificationParams(user, stageDir, localObserver, params,
+ mInstallSource, mInstallerUid, mSigningDetails, sessionId);
+ }
+
+ private void onVerificationComplete() {
+ if ((params.installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
+ destroyInternal();
+ dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Dry run", new Bundle());
+ return;
+ }
+
+ List<PackageInstallerSession> childSessions = getChildSessionsNotLocked();
+ try {
+ installNonStaged(childSessions);
+ } catch (PackageManagerException e) {
+ final String completeMsg = ExceptionUtils.getCompleteMessage(e);
+ Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
+ destroyInternal();
+ dispatchSessionFinished(e.error, completeMsg, null);
+ }
+ }
+
+ /**
+ * Stages this session for install and returns a
+ * {@link PackageManagerService.InstallParams} representing this new staged state.
+ */
+ private PackageManagerService.InstallParams makeInstallParams()
+ throws PackageManagerException {
+ synchronized (mLock) {
+ if (mDestroyed) {
+ throw new PackageManagerException(
+ INSTALL_FAILED_INTERNAL_ERROR, "Session destroyed");
+ }
+ if (!mSealed) {
+ throw new PackageManagerException(
+ INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
+ }
+ }
+
+ // We've reached point of no return; call into PMS to install the stage.
+ // Regardless of success or failure we always destroy session.
+ final IPackageInstallObserver2 localObserver = new IPackageInstallObserver2.Stub() {
+ @Override
+ public void onUserActionRequired(Intent intent) {
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public void onPackageInstalled(String basePackageName, int returnCode, String msg,
+ Bundle extras) {
+ destroyInternal();
+ dispatchSessionFinished(returnCode, msg, extras);
+ }
+ };
+
+ final UserHandle user;
+ if ((params.installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
+ user = UserHandle.ALL;
+ } else {
+ user = new UserHandle(userId);
+ }
+
+ synchronized (mLock) {
+ return mPm.new InstallParams(stageDir, localObserver, params, mInstallSource, user,
+ mSigningDetails, mInstallerUid);
+ }
}
private static void maybeRenameFile(File from, File to) throws PackageManagerException {
@@ -2923,9 +3027,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
if (hasParentSessionId()) {
mSessionProvider.getSession(
- getParentSessionId()).dispatchStreamValidateAndCommit();
+ getParentSessionId()).dispatchSessionSealed();
} else {
- dispatchStreamValidateAndCommit();
+ dispatchSessionSealed();
}
if (manualStartAndDestroy) {
dataLoader.destroy(dataLoaderId);
@@ -3063,39 +3167,85 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ private void acquireTransactionLock() {
+ if (!mTransactionLock.compareAndSet(false, true)) {
+ throw new UnsupportedOperationException("Concurrent access not supported");
+ }
+ }
+
+ private void releaseTransactionLock() {
+ mTransactionLock.compareAndSet(true, false);
+ }
+
@Override
public void addChildSessionId(int childSessionId) {
+ if (!params.isMultiPackage) {
+ throw new IllegalStateException("Single-session " + sessionId + " can't have child.");
+ }
+
final PackageInstallerSession childSession = mSessionProvider.getSession(childSessionId);
- if (childSession == null || !childSession.canBeAddedAsChild(sessionId)) {
+ if (childSession == null) {
throw new IllegalStateException("Unable to add child session " + childSessionId
- + " as it does not exist or is in an invalid state.");
+ + " as it does not exist.");
+ }
+ if (childSession.params.isMultiPackage) {
+ throw new IllegalStateException("Multi-session " + childSessionId
+ + " can't be a child.");
}
- synchronized (mLock) {
- assertCallerIsOwnerOrRootLocked();
- assertPreparedAndNotSealedLocked("addChildSessionId");
- final int indexOfSession = mChildSessionIds.indexOfKey(childSessionId);
- if (indexOfSession >= 0) {
- return;
+ try {
+ acquireTransactionLock();
+ childSession.acquireTransactionLock();
+
+ if (!childSession.canBeAddedAsChild(sessionId)) {
+ throw new IllegalStateException("Unable to add child session " + childSessionId
+ + " as it is in an invalid state.");
+ }
+ synchronized (mLock) {
+ assertCallerIsOwnerOrRootLocked();
+ assertPreparedAndNotSealedLocked("addChildSessionId");
+
+ final int indexOfSession = mChildSessionIds.indexOfKey(childSessionId);
+ if (indexOfSession >= 0) {
+ return;
+ }
+ childSession.setParentSessionId(this.sessionId);
+ addChildSessionIdLocked(childSessionId);
}
- childSession.setParentSessionId(this.sessionId);
- addChildSessionIdLocked(childSessionId);
+ } finally {
+ releaseTransactionLock();
+ childSession.releaseTransactionLock();
}
}
@Override
public void removeChildSessionId(int sessionId) {
final PackageInstallerSession session = mSessionProvider.getSession(sessionId);
- synchronized (mLock) {
- final int indexOfSession = mChildSessionIds.indexOfKey(sessionId);
+ try {
+ acquireTransactionLock();
if (session != null) {
- session.setParentSessionId(SessionInfo.INVALID_ID);
+ session.acquireTransactionLock();
}
- if (indexOfSession < 0) {
- // not added in the first place; no-op
- return;
+
+ synchronized (mLock) {
+ assertCallerIsOwnerOrRootLocked();
+ assertPreparedAndNotSealedLocked("removeChildSessionId");
+
+ final int indexOfSession = mChildSessionIds.indexOfKey(sessionId);
+ if (indexOfSession < 0) {
+ // not added in the first place; no-op
+ return;
+ }
+ if (session != null) {
+ session.setParentSessionId(SessionInfo.INVALID_ID);
+ }
+ mChildSessionIds.removeAt(indexOfSession);
+ }
+ } finally {
+ releaseTransactionLock();
+ if (session != null) {
+ session.releaseTransactionLock();
}
- mChildSessionIds.removeAt(indexOfSession);
}
}
@@ -3250,7 +3400,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private void destroyInternal() {
synchronized (mLock) {
mSealed = true;
- if (!params.isStaged || isStagedAndInTerminalState()) {
+ if (!params.isStaged) {
mDestroyed = true;
}
// Force shut down all bridges
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 73db48a4939e..a726c8d26b98 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -120,6 +120,7 @@ import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getDefaultCompilerFilter;
+import static com.android.server.pm.PackageManagerServiceUtils.comparePackageSignatures;
import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures;
import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists;
import static com.android.server.pm.PackageManagerServiceUtils.decompressFile;
@@ -331,6 +332,7 @@ 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.permission.persistence.RuntimePermissionsPersistence;
import com.android.server.AttributeCache;
import com.android.server.DeviceIdleInternal;
import com.android.server.EventLogTags;
@@ -1127,6 +1129,7 @@ public class PackageManagerService extends IPackageManager.Stub
public @Nullable String storageManagerPackage;
public @Nullable String defaultTextClassifierPackage;
public @Nullable String systemTextClassifierPackage;
+ public @Nullable String overlayConfigSignaturePackage;
public ViewCompiler viewCompiler;
public @Nullable String wellbeingPackage;
public @Nullable String retailDemoPackage;
@@ -1159,7 +1162,7 @@ public class PackageManagerService extends IPackageManager.Stub
final SparseArray<PackageVerificationState> mPendingVerification = new SparseArray<>();
/** List of packages waiting for rollback to be enabled. */
- final SparseArray<InstallParams> mPendingEnableRollback = new SparseArray<>();
+ final SparseArray<VerificationParams> mPendingEnableRollback = new SparseArray<>();
final PackageInstallerService mInstallerService;
@@ -1659,6 +1662,7 @@ public class PackageManagerService extends IPackageManager.Stub
final @Nullable String mServicesExtensionPackageName;
final @Nullable String mSharedSystemSharedLibraryPackageName;
final @Nullable String mRetailDemoPackage;
+ final @Nullable String mOverlayConfigSignaturePackage;
private final PackageUsage mPackageUsage = new PackageUsage();
private final CompilerStats mCompilerStats = new CompilerStats();
@@ -1833,7 +1837,7 @@ public class PackageManagerService extends IPackageManager.Stub
if ((state != null) && !state.isVerificationComplete()
&& !state.timeoutExtended()) {
- final InstallParams params = state.getInstallParams();
+ final VerificationParams params = state.getVerificationParams();
final Uri originUri = Uri.fromFile(params.origin.resolvedFile);
Slog.i(TAG, "Verification timed out for " + originUri);
@@ -1874,7 +1878,7 @@ public class PackageManagerService extends IPackageManager.Stub
final PackageVerificationState state = mPendingVerification.get(verificationId);
if (state != null && !state.isIntegrityVerificationComplete()) {
- final InstallParams params = state.getInstallParams();
+ final VerificationParams params = state.getVerificationParams();
final Uri originUri = Uri.fromFile(params.origin.resolvedFile);
Slog.i(TAG, "Integrity verification timed out for " + originUri);
@@ -1919,7 +1923,7 @@ public class PackageManagerService extends IPackageManager.Stub
state.setVerifierResponse(response.callerUid, response.code);
if (state.isVerificationComplete()) {
- final InstallParams params = state.getInstallParams();
+ final VerificationParams params = state.getVerificationParams();
final Uri originUri = Uri.fromFile(params.origin.resolvedFile);
if (state.isInstallAllowed()) {
@@ -1953,7 +1957,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
final int response = (Integer) msg.obj;
- final InstallParams params = state.getInstallParams();
+ final VerificationParams params = state.getVerificationParams();
final Uri originUri = Uri.fromFile(params.origin.resolvedFile);
state.setIntegrityVerificationResult(response);
@@ -2037,7 +2041,8 @@ public class PackageManagerService extends IPackageManager.Stub
case ENABLE_ROLLBACK_STATUS: {
final int enableRollbackToken = msg.arg1;
final int enableRollbackCode = msg.arg2;
- InstallParams params = mPendingEnableRollback.get(enableRollbackToken);
+ final VerificationParams params =
+ mPendingEnableRollback.get(enableRollbackToken);
if (params == null) {
Slog.w(TAG, "Invalid rollback enabled token "
+ enableRollbackToken + " received");
@@ -2061,7 +2066,8 @@ public class PackageManagerService extends IPackageManager.Stub
case ENABLE_ROLLBACK_TIMEOUT: {
final int enableRollbackToken = msg.arg1;
final int sessionId = msg.arg2;
- final InstallParams params = mPendingEnableRollback.get(enableRollbackToken);
+ final VerificationParams params =
+ mPendingEnableRollback.get(enableRollbackToken);
if (params != null) {
final Uri originUri = Uri.fromFile(params.origin.resolvedFile);
@@ -2210,17 +2216,17 @@ public class PackageManagerService extends IPackageManager.Stub
}
extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
// Send to all running apps.
- final SparseArray<int[]> newBroadcastWhitelist;
+ final SparseArray<int[]> newBroadcastAllowList;
synchronized (mLock) {
- newBroadcastWhitelist = mAppsFilter.getVisibilityWhitelist(
+ newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
getPackageSettingInternal(res.name, Process.SYSTEM_UID),
updateUserIds, mSettings.mPackages);
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, newBroadcastWhitelist);
+ updateUserIds, instantUserIds, newBroadcastAllowList);
if (installerPackageName != null) {
// Send to the installer, even if it's not running.
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
@@ -2252,7 +2258,7 @@ public class PackageManagerService extends IPackageManager.Stub
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
packageName, extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
- updateUserIds, instantUserIds, res.removedInfo.broadcastWhitelist);
+ updateUserIds, instantUserIds, res.removedInfo.broadcastAllowList);
if (installerPackageName != null) {
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, 0 /*flags*/,
@@ -2588,7 +2594,7 @@ public class PackageManagerService extends IPackageManager.Stub
(i, pm) ->
new Settings(Environment.getDataDirectory(),
i.getPermissionManagerServiceInternal().getPermissionSettings(),
- lock),
+ RuntimePermissionsPersistence.createInstance(), lock),
new Injector.LocalServicesProducer<>(ActivityTaskManagerInternal.class),
new Injector.LocalServicesProducer<>(ActivityManagerInternal.class),
new Injector.LocalServicesProducer<>(DeviceIdleInternal.class),
@@ -2814,6 +2820,7 @@ public class PackageManagerService extends IPackageManager.Stub
mIncidentReportApproverPackage = testParams.incidentReportApproverPackage;
mServicesExtensionPackageName = testParams.servicesExtensionPackageName;
mSharedSystemSharedLibraryPackageName = testParams.sharedSystemSharedLibraryPackageName;
+ mOverlayConfigSignaturePackage = testParams.overlayConfigSignaturePackage;
mResolveComponentName = testParams.resolveComponentName;
mPackages.putAll(testParams.packages);
@@ -3379,6 +3386,7 @@ public class PackageManagerService extends IPackageManager.Stub
mAppPredictionServicePackage = getAppPredictionServicePackageName();
mIncidentReportApproverPackage = getIncidentReportApproverPackageName();
mRetailDemoPackage = getRetailDemoPackageName();
+ mOverlayConfigSignaturePackage = getOverlayConfigSignaturePackageName();
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
@@ -4205,13 +4213,9 @@ public class PackageManagerService extends IPackageManager.Stub
Iterator<ResolveInfo> iter = matches.iterator();
while (iter.hasNext()) {
final ResolveInfo rInfo = iter.next();
- final PackageSetting ps = mSettings.mPackages.get(rInfo.activityInfo.packageName);
- if (ps != null) {
- final PermissionsState permissionsState = ps.getPermissionsState();
- if (permissionsState.hasPermission(Manifest.permission.INSTALL_PACKAGES, 0)
- || Build.IS_ENG) {
- continue;
- }
+ if (checkPermission(Manifest.permission.INSTALL_PACKAGES,
+ rInfo.activityInfo.packageName, 0) == PERMISSION_GRANTED || Build.IS_ENG) {
+ continue;
}
iter.remove();
}
@@ -8591,10 +8595,9 @@ public class PackageManagerService extends IPackageManager.Stub
private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps,
String[] permissions, boolean[] tmp, int flags, int userId) {
int numMatch = 0;
- final PermissionsState permissionsState = ps.getPermissionsState();
for (int i=0; i<permissions.length; i++) {
final String permission = permissions[i];
- if (permissionsState.hasPermission(permission, userId)) {
+ if (checkPermission(permission, ps.name, userId) == PERMISSION_GRANTED) {
tmp[i] = true;
numMatch++;
} else {
@@ -12119,12 +12122,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
// Exempt SharedUsers signed with the platform key.
PackageSetting platformPkgSetting = mSettings.mPackages.get("android");
- if ((platformPkgSetting.signatures.mSigningDetails
- != PackageParser.SigningDetails.UNKNOWN)
- && (compareSignatures(
- platformPkgSetting.signatures.mSigningDetails.signatures,
- pkg.getSigningDetails().signatures)
- != PackageManager.SIGNATURE_MATCH)) {
+ if (!comparePackageSignatures(platformPkgSetting,
+ pkg.getSigningDetails().signatures)) {
throw new PackageManagerException("Apps that share a user with a " +
"privileged app must themselves be marked as privileged. " +
pkg.getPackageName() + " shares privileged user " +
@@ -12171,12 +12170,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.Q) {
final PackageSetting platformPkgSetting =
mSettings.getPackageLPr("android");
- if ((platformPkgSetting.signatures.mSigningDetails
- != PackageParser.SigningDetails.UNKNOWN)
- && (compareSignatures(
- platformPkgSetting.signatures.mSigningDetails.signatures,
- pkg.getSigningDetails().signatures)
- != PackageManager.SIGNATURE_MATCH)) {
+ if (!comparePackageSignatures(platformPkgSetting,
+ pkg.getSigningDetails().signatures)) {
throw new PackageManagerException("Overlay "
+ pkg.getPackageName()
+ " must target Q or later, "
@@ -12185,24 +12180,35 @@ public class PackageManagerService extends IPackageManager.Stub
}
// A non-preloaded overlay package, without <overlay android:targetName>, will
- // only be used if it is signed with the same certificate as its target. If the
- // target is already installed, check this here to augment the last line of
- // defence which is OMS.
+ // only be used if it is signed with the same certificate as its target OR if
+ // it is signed with the same certificate as a reference package declared
+ // in 'config-signature' tag of SystemConfig.
+ // If the target is already installed or 'config-signature' tag in SystemConfig
+ // is set, check this here to augment the last line of defence which is OMS.
if (pkg.getOverlayTargetName() == null) {
final PackageSetting targetPkgSetting =
mSettings.getPackageLPr(pkg.getOverlayTarget());
if (targetPkgSetting != null) {
- if ((targetPkgSetting.signatures.mSigningDetails
- != PackageParser.SigningDetails.UNKNOWN)
- && (compareSignatures(
- targetPkgSetting.signatures.mSigningDetails.signatures,
- pkg.getSigningDetails().signatures)
- != PackageManager.SIGNATURE_MATCH)) {
- throw new PackageManagerException("Overlay "
- + pkg.getPackageName() + " and target "
- + pkg.getOverlayTarget() + " signed with"
- + " different certificates, and the overlay lacks"
- + " <overlay android:targetName>");
+ if (!comparePackageSignatures(targetPkgSetting,
+ pkg.getSigningDetails().signatures)) {
+ // check reference signature
+ if (mOverlayConfigSignaturePackage == null) {
+ throw new PackageManagerException("Overlay "
+ + pkg.getPackageName() + " and target "
+ + pkg.getOverlayTarget() + " signed with"
+ + " different certificates, and the overlay lacks"
+ + " <overlay android:targetName>");
+ }
+ final PackageSetting refPkgSetting =
+ mSettings.getPackageLPr(mOverlayConfigSignaturePackage);
+ if (!comparePackageSignatures(refPkgSetting,
+ pkg.getSigningDetails().signatures)) {
+ throw new PackageManagerException("Overlay "
+ + pkg.getPackageName() + " signed with a different "
+ + "certificate than both the reference package and "
+ + "target " + pkg.getOverlayTarget() + ", and the "
+ + "overlay lacks <overlay android:targetName>");
+ }
}
}
}
@@ -12672,7 +12678,7 @@ public class PackageManagerService extends IPackageManager.Stub
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,
- @Nullable SparseArray<int[]> broadcastWhitelist) {
+ @Nullable SparseArray<int[]> broadcastAllowList) {
mHandler.post(() -> {
try {
final IActivityManager am = ActivityManager.getService();
@@ -12684,7 +12690,7 @@ public class PackageManagerService extends IPackageManager.Stub
resolvedUserIds = userIds;
}
doSendBroadcast(am, action, pkg, extras, flags, targetPkg, finishedReceiver,
- resolvedUserIds, false, broadcastWhitelist);
+ resolvedUserIds, false, broadcastAllowList);
if (instantUserIds != null && instantUserIds != EMPTY_INT_ARRAY) {
doSendBroadcast(am, action, pkg, extras, flags, targetPkg, finishedReceiver,
instantUserIds, true, null);
@@ -12757,7 +12763,7 @@ public class PackageManagerService extends IPackageManager.Stub
*/
private void doSendBroadcast(IActivityManager am, String action, String pkg, Bundle extras,
int flags, String targetPkg, IIntentReceiver finishedReceiver,
- int[] userIds, boolean isInstantApp, @Nullable SparseArray<int[]> broadcastWhitelist) {
+ int[] userIds, boolean isInstantApp, @Nullable SparseArray<int[]> broadcastAllowList) {
for (int id : userIds) {
final Intent intent = new Intent(action,
pkg != null ? Uri.fromParts(PACKAGE_SCHEME, pkg, null) : null);
@@ -12787,7 +12793,7 @@ public class PackageManagerService extends IPackageManager.Stub
mInjector.getActivityManagerInternal().broadcastIntent(
intent, finishedReceiver, requiredPermissions,
finishedReceiver != null, id,
- broadcastWhitelist == null ? null : broadcastWhitelist.get(id));
+ broadcastAllowList == null ? null : broadcastAllowList.get(id));
}
}
@@ -12850,15 +12856,8 @@ public class PackageManagerService extends IPackageManager.Stub
return installReason;
}
- void installStage(ActiveInstallSession activeInstallSession) {
- if (DEBUG_INSTANT) {
- if ((activeInstallSession.getSessionParams().installFlags
- & PackageManager.INSTALL_INSTANT_APP) != 0) {
- Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
- }
- }
+ void installStage(InstallParams params) {
final Message msg = mHandler.obtainMessage(INIT_COPY);
- final InstallParams params = new InstallParams(activeInstallSession);
params.setTraceMethod("installStage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -12870,11 +12869,11 @@ public class PackageManagerService extends IPackageManager.Stub
mHandler.sendMessage(msg);
}
- void installStage(ActiveInstallSession parent, List<ActiveInstallSession> children)
+ void installStage(InstallParams parent, List<InstallParams> children)
throws PackageManagerException {
final Message msg = mHandler.obtainMessage(INIT_COPY);
final MultiPackageInstallParams params =
- new MultiPackageInstallParams(UserHandle.ALL, parent, children);
+ new MultiPackageInstallParams(parent, children);
params.setTraceMethod("installStageMultiPackage")
.setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -12886,6 +12885,21 @@ public class PackageManagerService extends IPackageManager.Stub
mHandler.sendMessage(msg);
}
+ void verifyStage(VerificationParams params) {
+ mHandler.post(()-> {
+ params.startCopy();
+ });
+ }
+
+ void verifyStage(VerificationParams parent, List<VerificationParams> children)
+ throws PackageManagerException {
+ final MultiPackageVerificationParams params =
+ new MultiPackageVerificationParams(parent, children);
+ mHandler.post(()-> {
+ params.startCopy();
+ });
+ }
+
private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting,
int userId, int dataLoaderType) {
final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
@@ -12919,7 +12933,7 @@ public class PackageManagerService extends IPackageManager.Stub
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
packageName, extras, 0, null, null, userIds, instantUserIds,
- mAppsFilter.getVisibilityWhitelist(
+ mAppsFilter.getVisibilityAllowList(
getPackageSettingInternal(packageName, Process.SYSTEM_UID),
userIds, mSettings.mPackages));
if (sendBootCompleted && !ArrayUtils.isEmpty(userIds)) {
@@ -14746,32 +14760,21 @@ public class PackageManagerService extends IPackageManager.Stub
* committed together.
*/
class MultiPackageInstallParams extends HandlerParams {
- private final IPackageInstallObserver2 mVerificationObserver;
- @NonNull
- private final ArrayList<InstallParams> mChildParams;
- // TODO(samiul): mCurrentState will relocated to a install-specific class in future
- @NonNull
+ private final List<InstallParams> mChildParams;
private final Map<InstallArgs, Integer> mCurrentState;
- private final Map<InstallParams, Integer> mVerificationState;
- MultiPackageInstallParams(
- @NonNull UserHandle user,
- @NonNull ActiveInstallSession parent,
- @NonNull List<ActiveInstallSession> activeInstallSessions)
+ MultiPackageInstallParams(InstallParams parent, List<InstallParams> childParams)
throws PackageManagerException {
- super(user);
- if (activeInstallSessions.size() == 0) {
+ super(parent.getUser());
+ if (childParams.size() == 0) {
throw new PackageManagerException("No child sessions found!");
}
- mChildParams = new ArrayList<>(activeInstallSessions.size());
- for (int i = 0; i < activeInstallSessions.size(); i++) {
- final InstallParams childParams = new InstallParams(activeInstallSessions.get(i));
- childParams.mParentInstallParams = this;
- this.mChildParams.add(childParams);
+ mChildParams = childParams;
+ for (int i = 0; i < childParams.size(); i++) {
+ final InstallParams childParam = childParams.get(i);
+ childParam.mParentInstallParams = this;
}
this.mCurrentState = new ArrayMap<>(mChildParams.size());
- this.mVerificationState = new ArrayMap<>(mChildParams.size());
- mVerificationObserver = parent.getVerificationObserver();
}
@Override
@@ -14788,7 +14791,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- // TODO(samiul): this method will relocated to a install-specific class in future
void tryProcessInstallRequest(InstallArgs args, int currentStatus) {
mCurrentState.put(args, currentStatus);
if (mCurrentState.size() != mChildParams.size()) {
@@ -14812,122 +14814,67 @@ public class PackageManagerService extends IPackageManager.Stub
completeStatus == PackageManager.INSTALL_SUCCEEDED,
installRequests);
}
-
- void trySendVerificationCompleteNotification(InstallParams child, int currentStatus) {
- mVerificationState.put(child, currentStatus);
- if (mVerificationState.size() != mChildParams.size()) {
- return;
- }
- int completeStatus = PackageManager.INSTALL_SUCCEEDED;
- for (Integer status : mVerificationState.values()) {
- if (status == PackageManager.INSTALL_UNKNOWN) {
- return;
- } else if (status != PackageManager.INSTALL_SUCCEEDED) {
- completeStatus = status;
- break;
- }
- }
- try {
- mVerificationObserver.onPackageInstalled(null, completeStatus,
- "Package Verification Result", new Bundle());
- } catch (RemoteException e) {
- Slog.i(TAG, "Observer no longer exists.");
- }
- }
}
class InstallParams extends HandlerParams {
- // TODO: see if we can collapse this into ActiveInstallSession
-
final OriginInfo origin;
final MoveInfo move;
- final IPackageInstallObserver2 mInstallObserver;
- private final IPackageInstallObserver2 mVerificationObserver;
+ final IPackageInstallObserver2 observer;
int installFlags;
@NonNull final InstallSource installSource;
final String volumeUuid;
- private boolean mWaitForVerificationToComplete;
- private boolean mWaitForIntegrityVerificationToComplete;
- private boolean mWaitForEnableRollbackToComplete;
int mRet;
final String packageAbiOverride;
final String[] grantedRuntimePermissions;
final List<String> whitelistedRestrictedPermissions;
final int autoRevokePermissionsMode;
- final VerificationInfo verificationInfo;
final PackageParser.SigningDetails signingDetails;
final int installReason;
- @Nullable
- MultiPackageInstallParams mParentInstallParams;
- final long requiredInstalledVersionCode;
+ @Nullable MultiPackageInstallParams mParentInstallParams;
final boolean forceQueryableOverride;
final int mDataLoaderType;
- final int mSessionId;
- InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 installObserver,
+ InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer,
int installFlags, InstallSource installSource, String volumeUuid,
- VerificationInfo verificationInfo, UserHandle user, String packageAbiOverride,
- String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
- int autoRevokePermissionsMode,
- SigningDetails signingDetails, int installReason,
- long requiredInstalledVersionCode, int dataLoaderType) {
+ UserHandle user, String packageAbiOverride) {
super(user);
this.origin = origin;
this.move = move;
- this.mInstallObserver = installObserver;
- this.mVerificationObserver = null;
+ this.observer = observer;
this.installFlags = installFlags;
this.installSource = Preconditions.checkNotNull(installSource);
this.volumeUuid = volumeUuid;
- this.verificationInfo = verificationInfo;
this.packageAbiOverride = packageAbiOverride;
- this.grantedRuntimePermissions = grantedPermissions;
- this.whitelistedRestrictedPermissions = whitelistedRestrictedPermissions;
- this.autoRevokePermissionsMode = autoRevokePermissionsMode;
- this.signingDetails = signingDetails;
- this.installReason = installReason;
- this.requiredInstalledVersionCode = requiredInstalledVersionCode;
+
+ this.grantedRuntimePermissions = null;
+ this.whitelistedRestrictedPermissions = null;
+ this.autoRevokePermissionsMode = MODE_DEFAULT;
+ this.signingDetails = PackageParser.SigningDetails.UNKNOWN;
+ this.installReason = PackageManager.INSTALL_REASON_UNKNOWN;
this.forceQueryableOverride = false;
- this.mDataLoaderType = dataLoaderType;
- this.mSessionId = -1;
+ this.mDataLoaderType = DataLoaderType.NONE;
}
- InstallParams(ActiveInstallSession activeInstallSession) {
- super(activeInstallSession.getUser());
- final PackageInstaller.SessionParams sessionParams =
- activeInstallSession.getSessionParams();
- if (DEBUG_INSTANT) {
- if ((sessionParams.installFlags
- & PackageManager.INSTALL_INSTANT_APP) != 0) {
- Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName());
- }
- }
- verificationInfo = new VerificationInfo(
- sessionParams.originatingUri,
- sessionParams.referrerUri,
- sessionParams.originatingUid,
- activeInstallSession.getInstallerUid());
- origin = OriginInfo.fromStagedFile(activeInstallSession.getStagedDir());
+ InstallParams(File stagedDir, IPackageInstallObserver2 observer,
+ PackageInstaller.SessionParams sessionParams, InstallSource installSource,
+ UserHandle user, SigningDetails signingDetails, int installerUid) {
+ super(user);
+ origin = OriginInfo.fromStagedFile(stagedDir);
move = null;
installReason = fixUpInstallReason(
- activeInstallSession.getInstallSource().installerPackageName,
- activeInstallSession.getInstallerUid(),
- sessionParams.installReason);
- mInstallObserver = activeInstallSession.getInstallObserver();
- mVerificationObserver = activeInstallSession.getVerificationObserver();
+ installSource.installerPackageName, installerUid, sessionParams.installReason);
+ this.observer = observer;
installFlags = sessionParams.installFlags;
- installSource = activeInstallSession.getInstallSource();
+ this.installSource = installSource;
volumeUuid = sessionParams.volumeUuid;
packageAbiOverride = sessionParams.abiOverride;
grantedRuntimePermissions = sessionParams.grantedRuntimePermissions;
whitelistedRestrictedPermissions = sessionParams.whitelistedRestrictedPermissions;
autoRevokePermissionsMode = sessionParams.autoRevokePermissionsMode;
- signingDetails = activeInstallSession.getSigningDetails();
- requiredInstalledVersionCode = sessionParams.requiredInstalledVersionCode;
+ this.signingDetails = signingDetails;
forceQueryableOverride = sessionParams.forceQueryableOverride;
mDataLoaderType = (sessionParams.dataLoaderParams != null)
? sessionParams.dataLoaderParams.getType() : DataLoaderType.NONE;
- mSessionId = activeInstallSession.getSessionId();
}
@Override
@@ -15074,12 +15021,146 @@ public class PackageManagerService extends IPackageManager.Stub
public void handleStartCopy() {
PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
origin.resolvedPath, installFlags, packageAbiOverride);
+ mRet = overrideInstallLocation(pkgLite);
+ }
- mRet = verifyReplacingVersionCode(pkgLite);
+ @Override
+ void handleReturnCode() {
+ processPendingInstall();
+ }
- if (mRet == INSTALL_SUCCEEDED) {
- mRet = overrideInstallLocation(pkgLite);
+ private void processPendingInstall() {
+ InstallArgs args = createInstallArgs(this);
+ if (mRet == PackageManager.INSTALL_SUCCEEDED) {
+ mRet = args.copyApk();
}
+ if (mParentInstallParams != null) {
+ mParentInstallParams.tryProcessInstallRequest(args, mRet);
+ } else {
+ PackageInstalledInfo res = createPackageInstalledInfo(mRet);
+ processInstallRequestsAsync(
+ res.returnCode == PackageManager.INSTALL_SUCCEEDED,
+ Collections.singletonList(new InstallRequest(args, res)));
+
+ }
+ }
+ }
+
+ /**
+ * Container for a multi-package install which refers to all install sessions and args being
+ * committed together.
+ */
+ class MultiPackageVerificationParams extends HandlerParams {
+ private final IPackageInstallObserver2 mObserver;
+ private final List<VerificationParams> mChildParams;
+ private final Map<VerificationParams, Integer> mVerificationState;
+
+ MultiPackageVerificationParams(
+ VerificationParams parent,
+ List<VerificationParams> children)
+ throws PackageManagerException {
+ super(parent.getUser());
+ if (children.size() == 0) {
+ throw new PackageManagerException("No child sessions found!");
+ }
+ mChildParams = children;
+ // Provide every child with reference to this object as parent
+ for (int i = 0; i < children.size(); i++) {
+ final VerificationParams childParams = children.get(i);
+ childParams.mParentVerificationParams = this;
+ }
+ this.mVerificationState = new ArrayMap<>(mChildParams.size());
+ mObserver = parent.observer;
+ }
+
+ @Override
+ void handleStartCopy() {
+ for (VerificationParams params : mChildParams) {
+ params.handleStartCopy();
+ }
+ }
+
+ @Override
+ void handleReturnCode() {
+ for (VerificationParams params : mChildParams) {
+ params.handleReturnCode();
+ }
+ }
+
+ void trySendVerificationCompleteNotification(VerificationParams child, int currentStatus) {
+ mVerificationState.put(child, currentStatus);
+ if (mVerificationState.size() != mChildParams.size()) {
+ return;
+ }
+ int completeStatus = PackageManager.INSTALL_SUCCEEDED;
+ for (Integer status : mVerificationState.values()) {
+ if (status == PackageManager.INSTALL_UNKNOWN) {
+ return;
+ } else if (status != PackageManager.INSTALL_SUCCEEDED) {
+ completeStatus = status;
+ break;
+ }
+ }
+ try {
+ mObserver.onPackageInstalled(null, completeStatus,
+ "Package Verification Result", new Bundle());
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Observer no longer exists.");
+ }
+ }
+ }
+
+ class VerificationParams extends HandlerParams {
+ final OriginInfo origin;
+ final IPackageInstallObserver2 observer;
+ final int installFlags;
+ @NonNull final InstallSource installSource;
+ final String packageAbiOverride;
+ final VerificationInfo verificationInfo;
+ final PackageParser.SigningDetails signingDetails;
+ @Nullable MultiPackageVerificationParams mParentVerificationParams;
+ final long requiredInstalledVersionCode;
+ final int mDataLoaderType;
+ final int mSessionId;
+
+ private boolean mWaitForVerificationToComplete;
+ private boolean mWaitForIntegrityVerificationToComplete;
+ private boolean mWaitForEnableRollbackToComplete;
+ private int mRet;
+
+ VerificationParams(UserHandle user, File stagedDir, IPackageInstallObserver2 observer,
+ PackageInstaller.SessionParams sessionParams, InstallSource installSource,
+ int installerUid, SigningDetails signingDetails, int sessionId) {
+ super(user);
+ origin = OriginInfo.fromStagedFile(stagedDir);
+ this.observer = observer;
+ installFlags = sessionParams.installFlags;
+ this.installSource = installSource;
+ packageAbiOverride = sessionParams.abiOverride;
+ verificationInfo = new VerificationInfo(
+ sessionParams.originatingUri,
+ sessionParams.referrerUri,
+ sessionParams.originatingUid,
+ installerUid
+ );
+ this.signingDetails = signingDetails;
+ requiredInstalledVersionCode = sessionParams.requiredInstalledVersionCode;
+ mDataLoaderType = (sessionParams.dataLoaderParams != null)
+ ? sessionParams.dataLoaderParams.getType() : DataLoaderType.NONE;
+ mSessionId = sessionId;
+ }
+
+ @Override
+ public String toString() {
+ return "InstallParams{" + Integer.toHexString(System.identityHashCode(this))
+ + " file=" + origin.file + "}";
+ }
+
+ public void handleStartCopy() {
+ PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mContext,
+ origin.resolvedPath, installFlags, packageAbiOverride);
+
+ mRet = verifyReplacingVersionCode(pkgLite);
// Perform package verification and enable rollback (unless we are simply moving the
// package).
@@ -15242,7 +15323,7 @@ public class PackageManagerService extends IPackageManager.Stub
final long idleDuration = getVerificationTimeout();
idleController.addPowerSaveTempWhitelistAppDirect(Process.myUid(),
- idleDuration,
+ idleDuration,
false, "integrity component");
final BroadcastOptions options = BroadcastOptions.makeBasic();
options.setTemporaryAppWhitelistDuration(idleDuration);
@@ -15476,44 +15557,16 @@ public class PackageManagerService extends IPackageManager.Stub
|| mWaitForEnableRollbackToComplete) {
return;
}
-
- if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
- try {
- mInstallObserver.onPackageInstalled(null, mRet, "Dry run", new Bundle());
- } catch (RemoteException e) {
- Slog.i(TAG, "Observer no longer exists.");
- }
- return;
- }
sendVerificationCompleteNotification();
-
- // TODO(samiul): In future return once verification is complete
- processPendingInstall();
- }
-
- private void processPendingInstall() {
- InstallArgs args = createInstallArgs(this);
- if (mRet == PackageManager.INSTALL_SUCCEEDED) {
- mRet = args.copyApk();
- }
- if (mParentInstallParams != null) {
- mParentInstallParams.tryProcessInstallRequest(args, mRet);
- } else {
- PackageInstalledInfo res = createPackageInstalledInfo(mRet);
- processInstallRequestsAsync(
- res.returnCode == PackageManager.INSTALL_SUCCEEDED,
- Collections.singletonList(new InstallRequest(args, res)));
-
- }
}
private void sendVerificationCompleteNotification() {
- if (mParentInstallParams != null) {
- mParentInstallParams.trySendVerificationCompleteNotification(this, mRet);
+ if (mParentVerificationParams != null) {
+ mParentVerificationParams.trySendVerificationCompleteNotification(this, mRet);
} else {
try {
- mVerificationObserver.onPackageInstalled(null, mRet,
- "Package Verification Result", new Bundle());
+ observer.onPackageInstalled(null, mRet, "Package Verification Result",
+ new Bundle());
} catch (RemoteException e) {
Slog.i(TAG, "Observer no longer exists.");
}
@@ -15597,7 +15650,7 @@ public class PackageManagerService extends IPackageManager.Stub
/** New install */
InstallArgs(InstallParams params) {
- this(params.origin, params.move, params.mInstallObserver, params.installFlags,
+ this(params.origin, params.move, params.observer, params.installFlags,
params.installSource, params.volumeUuid,
params.getUser(), null /*instructionSets*/, params.packageAbiOverride,
params.grantedRuntimePermissions, params.whitelistedRestrictedPermissions,
@@ -16713,7 +16766,7 @@ public class PackageManagerService extends IPackageManager.Stub
reconciledPkg.pkgSetting.firstInstallTime = deletedPkgSetting.firstInstallTime;
reconciledPkg.pkgSetting.lastUpdateTime = System.currentTimeMillis();
- res.removedInfo.broadcastWhitelist = mAppsFilter.getVisibilityWhitelist(
+ res.removedInfo.broadcastAllowList = mAppsFilter.getVisibilityAllowList(
reconciledPkg.pkgSetting, request.mAllUsers, mSettings.mPackages);
if (reconciledPkg.prepareResult.system) {
// Remove existing system package
@@ -18643,7 +18696,7 @@ public class PackageManagerService extends IPackageManager.Stub
boolean isStaticSharedLib;
// a two dimensional array mapping userId to the set of appIds that can receive notice
// of package changes
- SparseArray<int[]> broadcastWhitelist;
+ SparseArray<int[]> broadcastAllowList;
// Clean up resources deleted packages.
InstallArgs args = null;
@@ -18666,9 +18719,9 @@ public class PackageManagerService extends IPackageManager.Stub
extras.putInt(Intent.EXTRA_UID, removedAppId >= 0 ? removedAppId : uid);
extras.putBoolean(Intent.EXTRA_REPLACING, true);
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, removedPackage, extras,
- 0, null /*targetPackage*/, null, null, null, broadcastWhitelist);
+ 0, null /*targetPackage*/, null, null, null, broadcastAllowList);
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, removedPackage,
- extras, 0, null /*targetPackage*/, null, null, null, broadcastWhitelist);
+ extras, 0, null /*targetPackage*/, null, null, null, broadcastAllowList);
packageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
removedPackage, null, null, null, null /* broadcastWhitelist */);
if (installerPackageName != null) {
@@ -18700,7 +18753,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (removedPackage != null) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
removedPackage, extras, 0, null /*targetPackage*/, null,
- broadcastUsers, instantUserIds, broadcastWhitelist);
+ broadcastUsers, instantUserIds, broadcastAllowList);
if (installerPackageName != null) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
removedPackage, extras, 0 /*flags*/,
@@ -18709,7 +18762,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (dataRemoved && !isRemovedPackageSystemUpdate) {
packageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
removedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null,
- null, broadcastUsers, instantUserIds, broadcastWhitelist);
+ null, broadcastUsers, instantUserIds, broadcastAllowList);
packageSender.notifyPackageRemoved(removedPackage, removedUid);
}
}
@@ -18722,7 +18775,7 @@ public class PackageManagerService extends IPackageManager.Stub
packageSender.sendPackageBroadcast(Intent.ACTION_UID_REMOVED,
null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
- null, null, broadcastUsers, instantUserIds, broadcastWhitelist);
+ null, null, broadcastUsers, instantUserIds, broadcastAllowList);
}
}
@@ -19221,6 +19274,13 @@ public class PackageManagerService extends IPackageManager.Stub
final int flags = action.flags;
final boolean systemApp = isSystemApp(ps);
+ // We need to get the permission state before package state is (potentially) destroyed.
+ final SparseBooleanArray hadSuspendAppsPermission = new SparseBooleanArray();
+ for (int userId : allUserHandles) {
+ hadSuspendAppsPermission.put(userId, checkPermission(Manifest.permission.SUSPEND_APPS,
+ packageName, userId) == PERMISSION_GRANTED);
+ }
+
final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
@@ -19287,8 +19347,7 @@ public class PackageManagerService extends IPackageManager.Stub
affectedUserIds = resolveUserIds(userId);
}
for (final int affectedUserId : affectedUserIds) {
- if (ps.getPermissionsState().hasPermission(Manifest.permission.SUSPEND_APPS,
- affectedUserId)) {
+ if (hadSuspendAppsPermission.get(affectedUserId)) {
unsuspendForSuspendingPackage(packageName, affectedUserId);
removeAllDistractingPackageRestrictions(affectedUserId);
}
@@ -20755,6 +20814,11 @@ public class PackageManagerService extends IPackageManager.Stub
return ensureSystemPackageName(contentCaptureServiceComponentName.getPackageName());
}
+ public String getOverlayConfigSignaturePackageName() {
+ return ensureSystemPackageName(SystemConfig.getInstance()
+ .getOverlayConfigSignaturePackage());
+ }
+
@Nullable
private String getRetailDemoPackageName() {
final String predefinedPkgName = mContext.getString(R.string.config_retailDemoPackage);
@@ -21061,8 +21125,8 @@ public class PackageManagerService extends IPackageManager.Stub
pkgSetting.setEnabled(newState, userId, callingPackage);
if ((newState == COMPONENT_ENABLED_STATE_DISABLED_USER
|| newState == COMPONENT_ENABLED_STATE_DISABLED)
- && pkgSetting.getPermissionsState().hasPermission(
- Manifest.permission.SUSPEND_APPS, userId)) {
+ && checkPermission(Manifest.permission.SUSPEND_APPS, packageName, userId)
+ == PERMISSION_GRANTED) {
// This app should not generally be allowed to get disabled by the UI, but if it
// ever does, we don't want to end up with some of the user's apps permanently
// suspended.
@@ -21214,17 +21278,17 @@ public class PackageManagerService extends IPackageManager.Stub
final boolean isInstantApp = isInstantApp(packageName, userId);
final int[] userIds = isInstantApp ? EMPTY_INT_ARRAY : new int[] { userId };
final int[] instantUserIds = isInstantApp ? new int[] { userId } : EMPTY_INT_ARRAY;
- final SparseArray<int[]> broadcastWhitelist;
+ final SparseArray<int[]> broadcastAllowList;
synchronized (mLock) {
PackageSetting setting = getPackageSettingInternal(packageName, Process.SYSTEM_UID);
if (setting == null) {
return;
}
- broadcastWhitelist = isInstantApp ? null : mAppsFilter.getVisibilityWhitelist(setting,
+ broadcastAllowList = isInstantApp ? null : mAppsFilter.getVisibilityAllowList(setting,
userIds, mSettings.mPackages);
}
sendPackageBroadcast(Intent.ACTION_PACKAGE_CHANGED, packageName, extras, flags, null, null,
- userIds, instantUserIds, broadcastWhitelist);
+ userIds, instantUserIds, broadcastAllowList);
}
@Override
@@ -23377,12 +23441,7 @@ public class PackageManagerService extends IPackageManager.Stub
final Message msg = mHandler.obtainMessage(INIT_COPY);
final OriginInfo origin = OriginInfo.fromExistingFile(codeFile);
final InstallParams params = new InstallParams(origin, move, installObserver, installFlags,
- installSource, volumeUuid, null /*verificationInfo*/, user,
- packageAbiOverride, null /*grantedPermissions*/,
- null /*whitelistedRestrictedPermissions*/, MODE_DEFAULT /* autoRevokePermissions */,
- PackageParser.SigningDetails.UNKNOWN,
- PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.VERSION_CODE_HIGHEST,
- DataLoaderType.NONE);
+ installSource, volumeUuid, user, packageAbiOverride);
params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
@@ -24275,6 +24334,8 @@ public class PackageManagerService extends IPackageManager.Stub
return TextUtils.isEmpty(mRetailDemoPackage)
? ArrayUtils.emptyArray(String.class)
: new String[] {mRetailDemoPackage};
+ case PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE:
+ return filterOnlySystemPackages(getOverlayConfigSignaturePackageName());
default:
return ArrayUtils.emptyArray(String.class);
}
@@ -25628,79 +25689,6 @@ public class PackageManagerService extends IPackageManager.Stub
public List<String> getMimeGroup(String packageName, String mimeGroup) {
return mSettings.mPackages.get(packageName).getMimeGroup(mimeGroup);
}
-
- static class ActiveInstallSession {
- private final String mPackageName;
- private final File mStagedDir;
- private final IPackageInstallObserver2 mInstallObserver;
- // TODO(samiul): We are temporarily assigning two observer to ActiveInstallSession. One for
- // installation and one for verification. This will be fixed within next few CLs.
- private final IPackageInstallObserver2 mVerificationObserver;
- private final int mSessionId;
- private final PackageInstaller.SessionParams mSessionParams;
- private final int mInstallerUid;
- @NonNull private final InstallSource mInstallSource;
- private final UserHandle mUser;
- private final SigningDetails mSigningDetails;
-
- ActiveInstallSession(String packageName, File stagedDir,
- IPackageInstallObserver2 installObserver,
- IPackageInstallObserver2 verificationObserver,
- int sessionId, PackageInstaller.SessionParams sessionParams, int installerUid,
- InstallSource installSource, UserHandle user, SigningDetails signingDetails) {
- mPackageName = packageName;
- mStagedDir = stagedDir;
- mInstallObserver = installObserver;
- mVerificationObserver = verificationObserver;
- mSessionId = sessionId;
- mSessionParams = sessionParams;
- mInstallerUid = installerUid;
- mInstallSource = Preconditions.checkNotNull(installSource);
- mUser = user;
- mSigningDetails = signingDetails;
- }
-
- public String getPackageName() {
- return mPackageName;
- }
-
- public File getStagedDir() {
- return mStagedDir;
- }
-
- public IPackageInstallObserver2 getInstallObserver() {
- return mInstallObserver;
- }
-
- public IPackageInstallObserver2 getVerificationObserver() {
- return mVerificationObserver;
- }
-
- public int getSessionId() {
- return mSessionId;
- }
-
- public PackageInstaller.SessionParams getSessionParams() {
- return mSessionParams;
- }
-
- public int getInstallerUid() {
- return mInstallerUid;
- }
-
- @NonNull
- public InstallSource getInstallSource() {
- return mInstallSource;
- }
-
- public UserHandle getUser() {
- return mUser;
- }
-
- public SigningDetails getSigningDetails() {
- return mSigningDetails;
- }
- }
}
interface PackageSender {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 03f4708c09c4..de0e4b53adab 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -488,6 +488,18 @@ public class PackageManagerServiceUtils {
}
/**
+ * Returns true if the signature set of the package is identical to the specified signature
+ * set or if the signing details of the package are unknown.
+ */
+ public static boolean comparePackageSignatures(PackageSetting pkgSetting,
+ Signature[] signatures) {
+ return pkgSetting.signatures.mSigningDetails
+ == PackageParser.SigningDetails.UNKNOWN
+ || compareSignatures(pkgSetting.signatures.mSigningDetails.signatures, signatures)
+ == PackageManager.SIGNATURE_MATCH;
+ }
+
+ /**
* Used for backward compatibility to make sure any packages with
* certificate chains get upgraded to the new style. {@code existingSigs}
* will be in the old format (since they were stored on disk from before the
diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java
index ea7af9031bd0..cb9c2e997e22 100644
--- a/services/core/java/com/android/server/pm/PackageVerificationState.java
+++ b/services/core/java/com/android/server/pm/PackageVerificationState.java
@@ -19,7 +19,7 @@ package com.android.server.pm;
import android.content.pm.PackageManager;
import android.util.SparseBooleanArray;
-import com.android.server.pm.PackageManagerService.InstallParams;
+import com.android.server.pm.PackageManagerService.VerificationParams;
/**
* Tracks the package verification state for a particular package. Each package verification has a
@@ -28,7 +28,7 @@ import com.android.server.pm.PackageManagerService.InstallParams;
* sufficient verifiers, then package verification is considered complete.
*/
class PackageVerificationState {
- private final InstallParams mParams;
+ private final VerificationParams mParams;
private final SparseBooleanArray mSufficientVerifierUids;
@@ -50,13 +50,13 @@ class PackageVerificationState {
* Create a new package verification state where {@code requiredVerifierUid} is the user ID for
* the package that must reply affirmative before things can continue.
*/
- PackageVerificationState(InstallParams params) {
+ PackageVerificationState(VerificationParams params) {
mParams = params;
mSufficientVerifierUids = new SparseBooleanArray();
mExtendedTimeout = false;
}
- InstallParams getInstallParams() {
+ VerificationParams getVerificationParams() {
return mParams;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 7106499f9b56..1805713387ae 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -435,10 +435,11 @@ public final class Settings {
}
Settings(File dataDir, PermissionSettings permission,
- Object lock) {
+ RuntimePermissionsPersistence runtimePermissionsPersistence, Object lock) {
mLock = lock;
mPermissions = permission;
- mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
+ mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
+ runtimePermissionsPersistence, mLock);
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
@@ -5381,8 +5382,7 @@ public final class Settings {
private String mExtendedFingerprint;
- private final RuntimePermissionsPersistence mPersistence =
- RuntimePermissionsPersistence.createInstance();
+ private final RuntimePermissionsPersistence mPersistence;
private final Handler mHandler = new MyHandler();
@@ -5407,7 +5407,9 @@ public final class Settings {
// The mapping keys are user ids.
private final SparseBooleanArray mPermissionUpgradeNeeded = new SparseBooleanArray();
- public RuntimePermissionPersistence(Object persistenceLock) {
+ public RuntimePermissionPersistence(RuntimePermissionsPersistence persistence,
+ Object persistenceLock) {
+ mPersistence = persistence;
mPersistenceLock = persistenceLock;
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index f16b5b48d913..89ed3c755783 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -108,6 +108,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.StatLogger;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.pm.ShortcutUser.PackageWithUser;
import com.android.server.uri.UriGrantsManagerInternal;
@@ -614,13 +615,13 @@ public class ShortcutService extends IShortcutService.Stub {
}
@Override
- public void onStopUser(int userHandle) {
- mService.handleStopUser(userHandle);
+ public void onUserStopping(@NonNull TargetUser user) {
+ mService.handleStopUser(user.getUserIdentifier());
}
@Override
- public void onUnlockUser(int userId) {
- mService.handleUnlockUser(userId);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mService.handleUnlockUser(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 616e5d13f990..89bdb3ecbff9 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -804,6 +804,7 @@ public class StagingManager {
params.isStaged = false;
if (preReboot) {
params.installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
+ params.installFlags |= PackageManager.INSTALL_DRY_RUN;
}
final int apkParentSessionId = mPi.createSession(
params, session.getInstallerPackageName(), session.getInstallerAttributionTag(),
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index b0d3d53d58b2..8f11fd529e60 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -110,6 +110,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.am.UserState;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.utils.TimingsTraceAndSlog;
@@ -553,9 +554,9 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
- public void onStartUser(@UserIdInt int userId) {
+ public void onUserStarting(@NonNull TargetUser targetUser) {
synchronized (mUms.mUsersLock) {
- final UserData user = mUms.getUserDataLU(userId);
+ final UserData user = mUms.getUserDataLU(targetUser.getUserIdentifier());
if (user != null) {
user.startRealtime = SystemClock.elapsedRealtime();
}
@@ -563,9 +564,9 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
- public void onUnlockUser(@UserIdInt int userId) {
+ public void onUserUnlocking(@NonNull TargetUser targetUser) {
synchronized (mUms.mUsersLock) {
- final UserData user = mUms.getUserDataLU(userId);
+ final UserData user = mUms.getUserDataLU(targetUser.getUserIdentifier());
if (user != null) {
user.unlockRealtime = SystemClock.elapsedRealtime();
}
@@ -573,9 +574,9 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
- public void onStopUser(@UserIdInt int userId) {
+ public void onUserStopping(@NonNull TargetUser targetUser) {
synchronized (mUms.mUsersLock) {
- final UserData user = mUms.getUserDataLU(userId);
+ final UserData user = mUms.getUserDataLU(targetUser.getUserIdentifier());
if (user != null) {
user.startRealtime = 0;
user.unlockRealtime = 0;
diff --git a/services/core/java/com/android/server/pm/dex/OWNERS b/services/core/java/com/android/server/pm/dex/OWNERS
index fcc1f6c10eac..5a4431ee8c89 100644
--- a/services/core/java/com/android/server/pm/dex/OWNERS
+++ b/services/core/java/com/android/server/pm/dex/OWNERS
@@ -1,4 +1,2 @@
-agampe@google.com
calin@google.com
ngeoffray@google.com
-sehr@google.com
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 bc7554c54eb0..be93b8f95b79 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -554,13 +554,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
return null;
}
+ final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
synchronized (mLock) {
final BasePermission bp = mSettings.getPermissionLocked(permName);
if (bp == null) {
return null;
}
final int adjustedProtectionLevel = adjustPermissionProtectionFlagsLocked(
- bp.getProtectionLevel(), packageName, callingUid);
+ bp.getProtectionLevel(), pkg, callingUid);
return bp.generatePermissionInfo(adjustedProtectionLevel, flags);
}
}
@@ -1927,10 +1928,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
if (doGrant && packageName != null) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultBrowser(packageName,
- userId);
- }
+ mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultBrowser(packageName,
+ userId);
}
return true;
}
@@ -1940,10 +1939,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int callingUid = Binder.getCallingUid();
PackageManagerServiceUtils
.enforceSystemOrPhoneCaller("grantPermissionsToEnabledCarrierApps", callingUid);
- synchronized (mLock) {
- Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
- .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId));
- }
+ Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+ .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId));
}
@Override
@@ -1951,10 +1948,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int callingUid = Binder.getCallingUid();
PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
"grantDefaultPermissionsToEnabledImsServices", callingUid);
- synchronized (mLock) {
- Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
- .grantDefaultPermissionsToEnabledImsServices(packageNames, userId));
- }
+ Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+ .grantDefaultPermissionsToEnabledImsServices(packageNames, userId));
}
@Override
@@ -1963,11 +1958,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int callingUid = Binder.getCallingUid();
PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
"grantDefaultPermissionsToEnabledTelephonyDataServices", callingUid);
- synchronized (mLock) {
- Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
- .grantDefaultPermissionsToEnabledTelephonyDataServices(
- packageNames, userId));
- }
+ Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+ .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId));
}
@Override
@@ -1976,11 +1968,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int callingUid = Binder.getCallingUid();
PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
"revokeDefaultPermissionsFromDisabledTelephonyDataServices", callingUid);
- synchronized (mLock) {
- Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
- .revokeDefaultPermissionsFromDisabledTelephonyDataServices(
- packageNames, userId));
- }
+ Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+ .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames, userId));
}
@Override
@@ -1988,10 +1977,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int callingUid = Binder.getCallingUid();
PackageManagerServiceUtils
.enforceSystemOrPhoneCaller("grantDefaultPermissionsToActiveLuiApp", callingUid);
- synchronized (mLock) {
- Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
- .grantDefaultPermissionsToActiveLuiApp(packageName, userId));
- }
+ Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+ .grantDefaultPermissionsToActiveLuiApp(packageName, userId));
}
@Override
@@ -1999,10 +1986,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int callingUid = Binder.getCallingUid();
PackageManagerServiceUtils
.enforceSystemOrPhoneCaller("revokeDefaultPermissionsFromLuiApps", callingUid);
- synchronized (mLock) {
- Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
- .revokeDefaultPermissionsFromLuiApps(packageNames, userId));
- }
+ Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+ .revokeDefaultPermissionsFromLuiApps(packageNames, userId));
}
@Override
@@ -2229,8 +2214,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- private int adjustPermissionProtectionFlagsLocked(
- int protectionLevel, String packageName, int uid) {
+ private int adjustPermissionProtectionFlagsLocked(int protectionLevel,
+ @Nullable AndroidPackage pkg, int uid) {
// Signature permission flags area always reported
final int protectionLevelMasked = protectionLevel
& (PermissionInfo.PROTECTION_NORMAL
@@ -2245,8 +2230,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|| appId == Process.SHELL_UID) {
return protectionLevel;
}
- // Normalize package name to handle renamed packages and static libs
- final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
if (pkg == null) {
return protectionLevel;
}
@@ -2254,14 +2237,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return protectionLevelMasked;
}
// Apps that target O see flags for all protection levels.
- final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting(
- pkg.getPackageName());
- if (ps == null) {
- return protectionLevel;
- }
- if (ps.getAppId() != appId) {
- return protectionLevel;
- }
return protectionLevel;
}
@@ -2586,8 +2561,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(), UserManagerService.getInstance().getUserIds());
+ updatedUserIds = revokeUnusedSharedUserPermissionsLocked(ps.getSharedUser(),
+ currentUserIds);
if (!ArrayUtils.isEmpty(updatedUserIds)) {
runtimePermissionsRevoked = true;
}
@@ -2597,150 +2572,152 @@ public class PermissionManagerService extends IPermissionManager.Stub {
permissionsState.setGlobalGids(mGlobalGids);
- synchronized (mLock) {
- ArraySet<String> newImplicitPermissions = new ArraySet<>();
-
- final int N = pkg.getRequestedPermissions().size();
- for (int i = 0; i < N; i++) {
- final String permName = pkg.getRequestedPermissions().get(i);
- final BasePermission bp = mSettings.getPermissionLocked(permName);
- final boolean appSupportsRuntimePermissions =
- pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
- String upgradedActivityRecognitionPermission = null;
-
- if (DEBUG_INSTALL && bp != null) {
- Log.i(TAG, "Package " + pkg.getPackageName()
- + " checking " + permName + ": " + bp);
- }
+ ArraySet<String> newImplicitPermissions = new ArraySet<>();
- if (bp == null || getSourcePackageSetting(bp) == null) {
- if (packageOfInterest == null || packageOfInterest.equals(
- pkg.getPackageName())) {
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Unknown permission " + permName
- + " in package " + pkg.getPackageName());
- }
+ final int N = pkg.getRequestedPermissions().size();
+ for (int i = 0; i < N; i++) {
+ final String permName = pkg.getRequestedPermissions().get(i);
+ final BasePermission bp = mSettings.getPermission(permName);
+ final boolean appSupportsRuntimePermissions =
+ pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
+ String upgradedActivityRecognitionPermission = null;
+
+ if (DEBUG_INSTALL && bp != null) {
+ Log.i(TAG, "Package " + pkg.getPackageName()
+ + " checking " + permName + ": " + bp);
+ }
+
+ if (bp == null || getSourcePackageSetting(bp) == null) {
+ if (packageOfInterest == null || packageOfInterest.equals(
+ pkg.getPackageName())) {
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Unknown permission " + permName
+ + " in package " + pkg.getPackageName());
}
- continue;
}
+ continue;
+ }
- // Cache newImplicitPermissions before modifing permissionsState as for the shared
- // uids the original and new state are the same object
- if (!origPermissions.hasRequestedPermission(permName)
- && (pkg.getImplicitPermissions().contains(permName)
- || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
- if (pkg.getImplicitPermissions().contains(permName)) {
- // If permName is an implicit permission, try to auto-grant
- newImplicitPermissions.add(permName);
+ // Cache newImplicitPermissions before modifing permissionsState as for the shared
+ // uids the original and new state are the same object
+ if (!origPermissions.hasRequestedPermission(permName)
+ && (pkg.getImplicitPermissions().contains(permName)
+ || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
+ if (pkg.getImplicitPermissions().contains(permName)) {
+ // If permName is an implicit permission, try to auto-grant
+ newImplicitPermissions.add(permName);
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, permName + " is newly added for " + pkg.getPackageName());
- }
- } else {
- // Special case for Activity Recognition permission. Even if AR permission
- // is not an implicit permission we want to add it to the list (try to
- // auto-grant it) if the app was installed on a device before AR permission
- // was split, regardless of if the app now requests the new AR permission
- // or has updated its target SDK and AR is no longer implicit to it.
- // This is a compatibility workaround for apps when AR permission was
- // split in Q.
- final List<SplitPermissionInfoParcelable> permissionList =
- getSplitPermissions();
- int numSplitPerms = permissionList.size();
- for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
- SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum);
- String splitPermName = sp.getSplitPermission();
- if (sp.getNewPermissions().contains(permName)
- && origPermissions.hasInstallPermission(splitPermName)) {
- upgradedActivityRecognitionPermission = splitPermName;
- newImplicitPermissions.add(permName);
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, permName + " is newly added for " + pkg.getPackageName());
+ }
+ } else {
+ // Special case for Activity Recognition permission. Even if AR permission
+ // is not an implicit permission we want to add it to the list (try to
+ // auto-grant it) if the app was installed on a device before AR permission
+ // was split, regardless of if the app now requests the new AR permission
+ // or has updated its target SDK and AR is no longer implicit to it.
+ // This is a compatibility workaround for apps when AR permission was
+ // split in Q.
+ final List<SplitPermissionInfoParcelable> permissionList =
+ getSplitPermissions();
+ int numSplitPerms = permissionList.size();
+ for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
+ SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum);
+ String splitPermName = sp.getSplitPermission();
+ if (sp.getNewPermissions().contains(permName)
+ && origPermissions.hasInstallPermission(splitPermName)) {
+ upgradedActivityRecognitionPermission = splitPermName;
+ newImplicitPermissions.add(permName);
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, permName + " is newly added for "
- + pkg.getPackageName());
- }
- break;
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, permName + " is newly added for "
+ + pkg.getPackageName());
}
+ break;
}
}
}
+ }
- // TODO(b/140256621): The package instant app method has been removed
- // as part of work in b/135203078, so this has been commented out in the meantime
- // Limit ephemeral apps to ephemeral allowed permissions.
-// if (/*pkg.isInstantApp()*/ false && !bp.isInstant()) {
-// if (DEBUG_PERMISSIONS) {
-// Log.i(TAG, "Denying non-ephemeral permission " + bp.getName()
-// + " for package " + pkg.getPackageName());
-// }
-// continue;
+ // TODO(b/140256621): The package instant app method has been removed
+ // as part of work in b/135203078, so this has been commented out in the meantime
+ // Limit ephemeral apps to ephemeral allowed permissions.
+// if (/*pkg.isInstantApp()*/ false && !bp.isInstant()) {
+// if (DEBUG_PERMISSIONS) {
+// Log.i(TAG, "Denying non-ephemeral permission " + bp.getName()
+// + " for package " + pkg.getPackageName());
// }
+// continue;
+// }
- if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {
- if (DEBUG_PERMISSIONS) {
- Log.i(TAG, "Denying runtime-only permission " + bp.getName()
- + " for package " + pkg.getPackageName());
- }
- continue;
+ if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {
+ if (DEBUG_PERMISSIONS) {
+ Log.i(TAG, "Denying runtime-only permission " + bp.getName()
+ + " for package " + pkg.getPackageName());
}
+ continue;
+ }
- final String perm = bp.getName();
- boolean allowedSig = false;
- int grant = GRANT_DENIED;
+ final String perm = bp.getName();
+ boolean allowedSig = false;
+ int grant = GRANT_DENIED;
- // Keep track of app op permissions.
- if (bp.isAppOp()) {
- mSettings.addAppOpPackage(perm, pkg.getPackageName());
- }
+ // Keep track of app op permissions.
+ if (bp.isAppOp()) {
+ mSettings.addAppOpPackage(perm, pkg.getPackageName());
+ }
- if (bp.isNormal()) {
- // For all apps normal permissions are install time ones.
- grant = GRANT_INSTALL;
- } else if (bp.isRuntime()) {
- if (origPermissions.hasInstallPermission(bp.getName())
- || upgradedActivityRecognitionPermission != null) {
- // Before Q we represented some runtime permissions as install permissions,
- // in Q we cannot do this anymore. Hence upgrade them all.
- grant = GRANT_UPGRADE;
- } else {
- // For modern apps keep runtime permissions unchanged.
- grant = GRANT_RUNTIME;
- }
- } else if (bp.isSignature()) {
- // For all apps signature permissions are install time ones.
- allowedSig = grantSignaturePermission(perm, pkg, ps, bp, origPermissions);
- if (allowedSig) {
- grant = GRANT_INSTALL;
- }
+ if (bp.isNormal()) {
+ // For all apps normal permissions are install time ones.
+ grant = GRANT_INSTALL;
+ } else if (bp.isRuntime()) {
+ if (origPermissions.hasInstallPermission(bp.getName())
+ || upgradedActivityRecognitionPermission != null) {
+ // Before Q we represented some runtime permissions as install permissions,
+ // in Q we cannot do this anymore. Hence upgrade them all.
+ grant = GRANT_UPGRADE;
+ } else {
+ // For modern apps keep runtime permissions unchanged.
+ grant = GRANT_RUNTIME;
}
-
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Considering granting permission " + perm + " to package "
- + pkg.getPackageName());
+ } else if (bp.isSignature()) {
+ // For all apps signature permissions are install time ones.
+ allowedSig = shouldGrantSignaturePermission(perm, pkg, ps, bp, origPermissions);
+ if (allowedSig) {
+ grant = GRANT_INSTALL;
}
+ }
- if (grant != GRANT_DENIED) {
- if (!ps.isSystem() && ps.areInstallPermissionsFixed() && !bp.isRuntime()) {
- // If this is an existing, non-system package, then
- // we can't add any new permissions to it. Runtime
- // permissions can be added any time - they ad dynamic.
- if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
- // Except... if this is a permission that was added
- // to the platform (note: need to only do this when
- // updating the platform).
- if (!isNewPlatformPermissionForPackage(perm, pkg)) {
- grant = GRANT_DENIED;
- }
+ if (grant != GRANT_DENIED) {
+ if (!ps.isSystem() && ps.areInstallPermissionsFixed() && !bp.isRuntime()) {
+ // If this is an existing, non-system package, then
+ // we can't add any new permissions to it. Runtime
+ // permissions can be added any time - they ad dynamic.
+ if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
+ // Except... if this is a permission that was added
+ // to the platform (note: need to only do this when
+ // updating the platform).
+ if (!isNewPlatformPermissionForPackage(perm, pkg)) {
+ grant = GRANT_DENIED;
}
}
+ }
+ }
+
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Considering granting permission " + perm + " to package "
+ + pkg.getPackageName());
+ }
+ synchronized (mLock) {
+ if (grant != GRANT_DENIED) {
switch (grant) {
case GRANT_INSTALL: {
// Revoke this as runtime permission to handle the case of
// a runtime permission being downgraded to an install one.
// Also in permission review mode we keep dangerous permissions
// for legacy apps
- for (int userId : UserManagerService.getInstance().getUserIds()) {
+ for (int userId : currentUserIds) {
if (origPermissions.getRuntimePermissionState(
perm, userId) != null) {
// Revoke the runtime permission and clear the flags.
@@ -3042,20 +3019,23 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
}
+ }
- if ((changedInstallPermission || replace) && !ps.areInstallPermissionsFixed() &&
- !ps.isSystem() || ps.getPkgState().isUpdatedSystemApp()) {
- // This is the first that we have heard about this package, so the
- // permissions we have now selected are fixed until explicitly
- // changed.
- ps.setInstallPermissionsFixed(true);
- }
+ if ((changedInstallPermission || replace) && !ps.areInstallPermissionsFixed() &&
+ !ps.isSystem() || ps.getPkgState().isUpdatedSystemApp()) {
+ // This is the first that we have heard about this package, so the
+ // permissions we have now selected are fixed until explicitly
+ // changed.
+ ps.setInstallPermissionsFixed(true);
+ }
+ synchronized (mLock) {
updatedUserIds = revokePermissionsNoLongerImplicitLocked(permissionsState, pkg,
- updatedUserIds);
+ currentUserIds, updatedUserIds);
updatedUserIds = setInitialGrantForNewImplicitPermissionsLocked(origPermissions,
- permissionsState, pkg, newImplicitPermissions, updatedUserIds);
- updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, updatedUserIds);
+ permissionsState, pkg, newImplicitPermissions, currentUserIds, updatedUserIds);
+ updatedUserIds = checkIfLegacyStorageOpsNeedToBeUpdated(pkg, replace, currentUserIds,
+ updatedUserIds);
}
// Persist the runtime permissions state for users with changes. If permissions
@@ -3076,23 +3056,19 @@ public class PermissionManagerService extends IPermissionManager.Stub {
*
* @param ps The state of the permissions of the package
* @param pkg The package that is currently looked at
+ * @param userIds All user IDs in the system, must be passed in because this method is locked
* @param updatedUserIds a list of user ids that needs to be amended if the permission state
* for a user is changed.
*
* @return The updated value of the {@code updatedUserIds} parameter
*/
- private @NonNull int[] revokePermissionsNoLongerImplicitLocked(
- @NonNull PermissionsState ps, @NonNull AndroidPackage pkg,
- @NonNull int[] updatedUserIds) {
+ private @NonNull int[] revokePermissionsNoLongerImplicitLocked(@NonNull PermissionsState ps,
+ @NonNull AndroidPackage pkg, @NonNull int[] userIds, @NonNull int[] updatedUserIds) {
String pkgName = pkg.getPackageName();
boolean supportsRuntimePermissions = pkg.getTargetSdkVersion()
>= Build.VERSION_CODES.M;
- int[] users = UserManagerService.getInstance().getUserIds();
- int numUsers = users.length;
- for (int i = 0; i < numUsers; i++) {
- int userId = users[i];
-
+ for (int userId : userIds) {
for (String permission : ps.getPermissions(userId)) {
if (!pkg.getImplicitPermissions().contains(permission)) {
if (!ps.hasInstallPermission(permission)) {
@@ -3188,16 +3164,17 @@ public class PermissionManagerService extends IPermissionManager.Stub {
*
* @param pkg The package for which the permissions are updated
* @param replace If the app is being replaced
+ * @param userIds All user IDs in the system, must be passed in because this method is locked
* @param updatedUserIds The ids of the users that already changed.
*
* @return The ids of the users that are changed
*/
- private @NonNull int[] checkIfLegacyStorageOpsNeedToBeUpdated(
- @NonNull AndroidPackage pkg, boolean replace, @NonNull int[] updatedUserIds) {
+ private @NonNull int[] checkIfLegacyStorageOpsNeedToBeUpdated(@NonNull AndroidPackage pkg,
+ boolean replace, @NonNull int[] userIds, @NonNull int[] updatedUserIds) {
if (replace && pkg.isRequestLegacyExternalStorage() && (
pkg.getRequestedPermissions().contains(READ_EXTERNAL_STORAGE)
|| pkg.getRequestedPermissions().contains(WRITE_EXTERNAL_STORAGE))) {
- return UserManagerService.getInstance().getUserIds();
+ return userIds.clone();
}
return updatedUserIds;
@@ -3209,15 +3186,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
* @param origPs The permission state of the package before the split
* @param ps The new permission state
* @param pkg The package the permission belongs to
+ * @param userIds All user IDs in the system, must be passed in because this method is locked
* @param updatedUserIds List of users for which the permission state has already been changed
*
* @return List of users for which the permission state has been changed
*/
private @NonNull int[] setInitialGrantForNewImplicitPermissionsLocked(
- @NonNull PermissionsState origPs,
- @NonNull PermissionsState ps, @NonNull AndroidPackage pkg,
- @NonNull ArraySet<String> newImplicitPermissions,
- @NonNull int[] updatedUserIds) {
+ @NonNull PermissionsState origPs, @NonNull PermissionsState ps,
+ @NonNull AndroidPackage pkg, @NonNull ArraySet<String> newImplicitPermissions,
+ @NonNull int[] userIds, @NonNull int[] updatedUserIds) {
String pkgName = pkg.getPackageName();
ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>();
@@ -3251,11 +3228,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (!ps.hasInstallPermission(newPerm)) {
BasePermission bp = mSettings.getPermissionLocked(newPerm);
- int[] users = UserManagerService.getInstance().getUserIds();
- int numUsers = users.length;
- for (int userNum = 0; userNum < numUsers; userNum++) {
- int userId = users[userNum];
-
+ for (int userId : userIds) {
if (!newPerm.equals(Manifest.permission.ACTIVITY_RECOGNITION)) {
ps.updatePermissionFlags(bp, userId,
FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
@@ -3413,7 +3386,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return wlPermissions != null && wlPermissions.contains(perm);
}
- private boolean grantSignaturePermission(String perm, AndroidPackage pkg,
+ private boolean shouldGrantSignaturePermission(String perm, AndroidPackage pkg,
PackageSetting pkgSetting, BasePermission bp, PermissionsState origPermissions) {
boolean oemPermission = bp.isOEM();
boolean vendorPrivilegedPermission = bp.isVendorPrivileged();
@@ -4210,6 +4183,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// The target package is the source of the current permission
// Set to changed for either install or uninstall
changed = true;
+ if (needsUpdate == null) {
+ needsUpdate = new ArraySet<>(mSettings.mPermissions.size());
+ }
+ needsUpdate.add(bp);
+ }
+ }
+ if (needsUpdate != null) {
+ for (final BasePermission bp : needsUpdate) {
// If the target package is being uninstalled, we need to revoke this permission
// From all other packages
if (pkg == null || !hasPermission(pkg, bp.getName())) {
@@ -4239,16 +4220,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
});
}
- it.remove();
- }
- if (needsUpdate == null) {
- needsUpdate = new ArraySet<>(mSettings.mPermissions.size());
+ mSettings.removePermissionLocked(bp.getName());
+ continue;
}
- needsUpdate.add(bp);
- }
- }
- if (needsUpdate != null) {
- for (final BasePermission bp : needsUpdate) {
final AndroidPackage sourcePkg =
mPackageManagerInt.getPackage(bp.getSourcePackageName());
final PackageSetting sourcePs =
@@ -4899,58 +4873,42 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Override
public void setDialerAppPackagesProvider(PackagesProvider provider) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy.setDialerAppPackagesProvider(provider);
- }
+ mDefaultPermissionGrantPolicy.setDialerAppPackagesProvider(provider);
}
@Override
public void setLocationExtraPackagesProvider(PackagesProvider provider) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy.setLocationExtraPackagesProvider(provider);
- }
+ mDefaultPermissionGrantPolicy.setLocationExtraPackagesProvider(provider);
}
@Override
public void setLocationPackagesProvider(PackagesProvider provider) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy.setLocationPackagesProvider(provider);
- }
+ mDefaultPermissionGrantPolicy.setLocationPackagesProvider(provider);
}
@Override
public void setSimCallManagerPackagesProvider(PackagesProvider provider) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy.setSimCallManagerPackagesProvider(provider);
- }
+ mDefaultPermissionGrantPolicy.setSimCallManagerPackagesProvider(provider);
}
@Override
public void setSmsAppPackagesProvider(PackagesProvider provider) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy.setSmsAppPackagesProvider(provider);
- }
+ mDefaultPermissionGrantPolicy.setSmsAppPackagesProvider(provider);
}
@Override
public void setSyncAdapterPackagesProvider(SyncAdapterPackagesProvider provider) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy.setSyncAdapterPackagesProvider(provider);
- }
+ mDefaultPermissionGrantPolicy.setSyncAdapterPackagesProvider(provider);
}
@Override
public void setUseOpenWifiAppPackagesProvider(PackagesProvider provider) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy.setUseOpenWifiAppPackagesProvider(provider);
- }
+ mDefaultPermissionGrantPolicy.setUseOpenWifiAppPackagesProvider(provider);
}
@Override
public void setVoiceInteractionPackagesProvider(PackagesProvider provider) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy.setVoiceInteractionPackagesProvider(provider);
- }
+ mDefaultPermissionGrantPolicy.setVoiceInteractionPackagesProvider(provider);
}
@Override
@@ -4982,36 +4940,28 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Override
public void grantDefaultPermissionsToDefaultSimCallManager(String packageName, int userId) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy
- .grantDefaultPermissionsToDefaultSimCallManager(packageName, userId);
- }
+ mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultSimCallManager(
+ packageName, userId);
}
@Override
public void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName, int userId) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy
- .grantDefaultPermissionsToDefaultUseOpenWifiApp(packageName, userId);
- }
+ mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultUseOpenWifiApp(
+ packageName, userId);
}
@Override
public void grantDefaultPermissionsToDefaultBrowser(String packageName, int userId) {
- synchronized (mLock) {
- mDefaultPermissionGrantPolicy
- .grantDefaultPermissionsToDefaultBrowser(packageName, userId);
- }
+ mDefaultPermissionGrantPolicy.grantDefaultPermissionsToDefaultBrowser(packageName,
+ userId);
}
@Override
public void onNewUserCreated(int userId) {
mDefaultPermissionGrantPolicy.grantDefaultPermissions(userId);
- synchronized (mLock) {
- // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
- PermissionManagerService.this.updateAllPermissions(
- StorageManager.UUID_PRIVATE_INTERNAL, true, mDefaultPermissionCallback);
- }
+ // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
+ PermissionManagerService.this.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL,
+ true, mDefaultPermissionCallback);
}
@Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionSettings.java b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
index 355e24326c8e..eea8ac737b86 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionSettings.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
@@ -88,12 +88,14 @@ public class PermissionSettings {
}
public void addAppOpPackage(String permName, String packageName) {
- ArraySet<String> pkgs = mAppOpPermissionPackages.get(permName);
- if (pkgs == null) {
- pkgs = new ArraySet<>();
- mAppOpPermissionPackages.put(permName, pkgs);
+ synchronized (mLock) {
+ ArraySet<String> pkgs = mAppOpPermissionPackages.get(permName);
+ if (pkgs == null) {
+ pkgs = new ArraySet<>();
+ mAppOpPermissionPackages.put(permName, pkgs);
+ }
+ pkgs.add(packageName);
}
- pkgs.add(packageName);
}
/**
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 37f088b170eb..4d48a2e63b30 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -67,6 +67,7 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
@@ -347,7 +348,11 @@ public final class PermissionPolicyService extends SystemService {
}
@Override
- public void onStartUser(@UserIdInt int userId) {
+ public void onUserStarting(@NonNull TargetUser user) {
+ onStartUser(user.getUserIdentifier());
+ }
+
+ private void onStartUser(@UserIdInt int userId) {
if (DEBUG) Slog.i(LOG_TAG, "onStartUser(" + userId + ")");
if (isStarted(userId)) {
@@ -373,11 +378,11 @@ public final class PermissionPolicyService extends SystemService {
}
@Override
- public void onStopUser(@UserIdInt int userId) {
- if (DEBUG) Slog.i(LOG_TAG, "onStopUser(" + userId + ")");
+ public void onUserStopping(@NonNull TargetUser user) {
+ if (DEBUG) Slog.i(LOG_TAG, "onStopUser(" + user + ")");
synchronized (mLock) {
- mIsStarted.delete(userId);
+ mIsStarted.delete(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 4c4680b17372..f9a49c9d8244 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -493,9 +493,6 @@ public final class PowerManagerService extends SystemService
private boolean mProximityPositive;
// Screen brightness setting limits.
- private float mScreenBrightnessSettingMinimum;
- private float mScreenBrightnessSettingMaximum;
- private float mScreenBrightnessSettingDefault;
public final float mScreenBrightnessMinimum;
public final float mScreenBrightnessMaximum;
public final float mScreenBrightnessDefault;
@@ -1030,14 +1027,6 @@ public final class PowerManagerService extends SystemService
mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
mAttentionDetector.systemReady(mContext);
- PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mScreenBrightnessSettingMinimum = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
- mScreenBrightnessSettingMaximum = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
- mScreenBrightnessSettingDefault = pm.getBrightnessConstraint(
- PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT);
-
SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
// The notifier runs on the system server's main looper so as not to interfere
@@ -2818,7 +2807,7 @@ public final class PowerManagerService extends SystemService
// Keep the brightness steady during boot. This requires the
// bootloader brightness and the default brightness to be identical.
autoBrightness = false;
- screenBrightnessOverride = mScreenBrightnessSettingDefault;
+ screenBrightnessOverride = mScreenBrightnessDefault;
} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
autoBrightness = false;
screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager;
@@ -3208,6 +3197,7 @@ public final class PowerManagerService extends SystemService
// If we're stuck in a really low-level reboot loop, and a
// rescue party is trying to prompt the user for a factory data
// reset, we must GET TO DA CHOPPA!
+ // No check point from ShutdownCheckPoints will be dumped at this state.
PowerManagerService.lowLevelReboot(reason);
} else {
throw new IllegalStateException("Too early to call shutdown() or reboot()");
@@ -3868,9 +3858,9 @@ public final class PowerManagerService extends SystemService
pw.println(" mDrawWakeLockOverrideFromSidekick=" + mDrawWakeLockOverrideFromSidekick);
pw.println(" mDozeScreenBrightnessOverrideFromDreamManager="
+ mDozeScreenBrightnessOverrideFromDreamManager);
- pw.println(" mScreenBrightnessSettingMinimumFloat=" + mScreenBrightnessSettingMinimum);
- pw.println(" mScreenBrightnessSettingMaximumFloat=" + mScreenBrightnessSettingMaximum);
- pw.println(" mScreenBrightnessSettingDefaultFloat=" + mScreenBrightnessSettingDefault);
+ pw.println(" mScreenBrightnessMinimum=" + mScreenBrightnessMinimum);
+ pw.println(" mScreenBrightnessMaximum=" + mScreenBrightnessMaximum);
+ pw.println(" mScreenBrightnessDefault=" + mScreenBrightnessDefault);
pw.println(" mDoubleTapWakeEnabled=" + mDoubleTapWakeEnabled);
pw.println(" mIsVrModeEnabled=" + mIsVrModeEnabled);
pw.println(" mForegroundProfile=" + mForegroundProfile);
@@ -4227,15 +4217,15 @@ public final class PowerManagerService extends SystemService
proto.write(
PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
.SETTING_MINIMUM_FLOAT,
- mScreenBrightnessSettingMinimum);
+ mScreenBrightnessMinimum);
proto.write(
PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
.SETTING_MAXIMUM_FLOAT,
- mScreenBrightnessSettingMaximum);
+ mScreenBrightnessMaximum);
proto.write(
PowerServiceSettingsAndConfigurationDumpProto.ScreenBrightnessSettingLimitsProto
.SETTING_DEFAULT_FLOAT,
- mScreenBrightnessSettingDefault);
+ mScreenBrightnessDefault);
proto.end(screenBrightnessSettingLimitsToken);
proto.write(
@@ -5114,6 +5104,7 @@ public final class PowerManagerService extends SystemService
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
}
+ ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait);
@@ -5132,10 +5123,11 @@ public final class PowerManagerService extends SystemService
public void rebootSafeMode(boolean confirm, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+ String reason = PowerManager.REBOOT_SAFE_MODE;
+ ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
final long ident = Binder.clearCallingIdentity();
try {
- shutdownOrRebootInternal(HALT_MODE_REBOOT_SAFE_MODE, confirm,
- PowerManager.REBOOT_SAFE_MODE, wait);
+ shutdownOrRebootInternal(HALT_MODE_REBOOT_SAFE_MODE, confirm, reason, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -5151,6 +5143,7 @@ public final class PowerManagerService extends SystemService
public void shutdown(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+ ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(HALT_MODE_SHUTDOWN, confirm, reason, wait);
diff --git a/services/core/java/com/android/server/power/ShutdownCheckPoints.java b/services/core/java/com/android/server/power/ShutdownCheckPoints.java
index e6d0dddf710c..05ee7dfb4cae 100644
--- a/services/core/java/com/android/server/power/ShutdownCheckPoints.java
+++ b/services/core/java/com/android/server/power/ShutdownCheckPoints.java
@@ -90,18 +90,19 @@ public final class ShutdownCheckPoints {
}
/** Records the stack trace of this {@link Thread} as a shutdown check point. */
- public static void recordCheckPoint() {
- INSTANCE.recordCheckPointInternal();
+ public static void recordCheckPoint(@Nullable String reason) {
+ INSTANCE.recordCheckPointInternal(reason);
}
/** Records the pid of the caller process as a shutdown check point. */
- public static void recordCheckPoint(int callerProcessId) {
- INSTANCE.recordCheckPointInternal(callerProcessId);
+ public static void recordCheckPoint(int callerProcessId, @Nullable String reason) {
+ INSTANCE.recordCheckPointInternal(callerProcessId, reason);
}
/** Records the {@link android.content.Intent} name and package as a shutdown check point. */
- public static void recordCheckPoint(String intentName, String packageName) {
- INSTANCE.recordCheckPointInternal(intentName, packageName);
+ public static void recordCheckPoint(
+ String intentName, String packageName, @Nullable String reason) {
+ INSTANCE.recordCheckPointInternal(intentName, packageName, reason);
}
/** Serializes the recorded check points and writes them to given {@code printWriter}. */
@@ -119,24 +120,24 @@ public final class ShutdownCheckPoints {
}
@VisibleForTesting
- void recordCheckPointInternal() {
- recordCheckPointInternal(new SystemServerCheckPoint(mInjector));
+ void recordCheckPointInternal(@Nullable String reason) {
+ recordCheckPointInternal(new SystemServerCheckPoint(mInjector, reason));
Slog.v(TAG, "System server shutdown checkpoint recorded");
}
@VisibleForTesting
- void recordCheckPointInternal(int callerProcessId) {
+ void recordCheckPointInternal(int callerProcessId, @Nullable String reason) {
recordCheckPointInternal(callerProcessId == Process.myPid()
- ? new SystemServerCheckPoint(mInjector)
- : new BinderCheckPoint(mInjector, callerProcessId));
+ ? new SystemServerCheckPoint(mInjector, reason)
+ : new BinderCheckPoint(mInjector, callerProcessId, reason));
Slog.v(TAG, "Binder shutdown checkpoint recorded with pid=" + callerProcessId);
}
@VisibleForTesting
- void recordCheckPointInternal(String intentName, String packageName) {
+ void recordCheckPointInternal(String intentName, String packageName, @Nullable String reason) {
recordCheckPointInternal("android".equals(packageName)
- ? new SystemServerCheckPoint(mInjector)
- : new IntentCheckPoint(mInjector, intentName, packageName));
+ ? new SystemServerCheckPoint(mInjector, reason)
+ : new IntentCheckPoint(mInjector, intentName, packageName, reason));
Slog.v(TAG, String.format("Shutdown intent checkpoint recorded intent=%s from package=%s",
intentName, packageName));
}
@@ -182,14 +183,20 @@ public final class ShutdownCheckPoints {
private abstract static class CheckPoint {
private final long mTimestamp;
+ @Nullable private final String mReason;
- CheckPoint(Injector injector) {
+ CheckPoint(Injector injector, @Nullable String reason) {
mTimestamp = injector.currentTimeMillis();
+ mReason = reason;
}
final void dump(PrintWriter printWriter) {
printWriter.print("Shutdown request from ");
printWriter.print(getOrigin());
+ if (mReason != null) {
+ printWriter.print(" for reason ");
+ printWriter.print(mReason);
+ }
printWriter.print(" at ");
printWriter.print(DATE_FORMAT.format(new Date(mTimestamp)));
printWriter.println(" (epoch=" + mTimestamp + ")");
@@ -206,8 +213,8 @@ public final class ShutdownCheckPoints {
private final StackTraceElement[] mStackTraceElements;
- SystemServerCheckPoint(Injector injector) {
- super(injector);
+ SystemServerCheckPoint(Injector injector, @Nullable String reason) {
+ super(injector, reason);
mStackTraceElements = Thread.currentThread().getStackTrace();
}
@@ -263,8 +270,8 @@ public final class ShutdownCheckPoints {
private final int mCallerProcessId;
private final IActivityManager mActivityManager;
- BinderCheckPoint(Injector injector, int callerProcessId) {
- super(injector);
+ BinderCheckPoint(Injector injector, int callerProcessId, @Nullable String reason) {
+ super(injector, reason);
mCallerProcessId = callerProcessId;
mActivityManager = injector.activityManager();
}
@@ -307,8 +314,9 @@ public final class ShutdownCheckPoints {
private final String mIntentName;
private final String mPackageName;
- IntentCheckPoint(Injector injector, String intentName, String packageName) {
- super(injector);
+ IntentCheckPoint(
+ Injector injector, String intentName, String packageName, @Nullable String reason) {
+ super(injector, reason);
mIntentName = intentName;
mPackageName = packageName;
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 2621d8b46494..e94575c43363 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -65,7 +65,7 @@ public final class ShutdownThread extends Thread {
private static final int RADIOS_STATE_POLL_SLEEP_MS = 100;
// maximum time we wait for the shutdown broadcast before going on.
private static final int MAX_BROADCAST_TIME = 10 * 1000;
- private static final int MAX_CHECK_POINTS_DUMP_WAIT_TIME = 20 * 1000;
+ private static final int MAX_CHECK_POINTS_DUMP_WAIT_TIME = 10 * 1000;
private static final int MAX_RADIO_WAIT_TIME = 12 * 1000;
private static final int MAX_UNCRYPT_WAIT_TIME = 15 * 60 * 1000;
// constants for progress bar. the values are roughly estimated based on timeout.
@@ -165,6 +165,10 @@ public final class ShutdownThread extends Thread {
}
}
+ // Add checkpoint for this shutdown attempt. The user might still cancel the dialog, but
+ // this point preserves the system trace of the trigger point of the ShutdownThread.
+ ShutdownCheckPoints.recordCheckPoint(/* reason= */ null);
+
final int longPressBehavior = context.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
final int resourceId = mRebootSafeMode
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 392792dbae69..a291cef5b39e 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -34,14 +34,11 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.PermissionChecker;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
-import android.database.CursorWindow;
import android.os.Binder;
-import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteCallback;
import android.os.RemoteCallbackList;
@@ -74,6 +71,7 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import java.io.ByteArrayOutputStream;
@@ -217,8 +215,8 @@ public class RoleManagerService extends SystemService implements RoleUserState.C
}
@Override
- public void onStartUser(@UserIdInt int userId) {
- maybeGrantDefaultRolesSync(userId);
+ public void onUserStarting(@NonNull TargetUser user) {
+ maybeGrantDefaultRolesSync(user.getUserIdentifier());
}
@MainThread
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerService.java b/services/core/java/com/android/server/rollback/RollbackManagerService.java
index ce1156bbe059..04a5ca515c5c 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerService.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerService.java
@@ -16,10 +16,12 @@
package com.android.server.rollback;
+import android.annotation.NonNull;
import android.content.Context;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
/**
* Service that manages APK level rollbacks. Publishes
@@ -43,8 +45,8 @@ public final class RollbackManagerService extends SystemService {
}
@Override
- public void onUserUnlocking(TargetUser user) {
- mService.onUnlockUser(user.getUserHandle().getIdentifier());
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mService.onUnlockUser(user.getUserIdentifier());
}
@Override
diff --git a/services/core/java/com/android/server/search/SearchManagerService.java b/services/core/java/com/android/server/search/SearchManagerService.java
index fea68d3090f0..7091c47b8e83 100644
--- a/services/core/java/com/android/server/search/SearchManagerService.java
+++ b/services/core/java/com/android/server/search/SearchManagerService.java
@@ -16,9 +16,7 @@
package com.android.server.search;
-import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
-import android.app.IActivityTaskManager;
+import android.annotation.NonNull;
import android.app.ISearchManager;
import android.app.SearchManager;
import android.app.SearchableInfo;
@@ -26,18 +24,14 @@ import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
import android.database.ContentObserver;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.service.voice.VoiceInteractionService;
import android.util.Log;
import android.util.SparseArray;
@@ -48,6 +42,7 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.FileDescriptor;
@@ -76,18 +71,13 @@ public class SearchManagerService extends ISearchManager.Stub {
}
@Override
- public void onUnlockUser(final int userId) {
- mService.mHandler.post(new Runnable() {
- @Override
- public void run() {
- mService.onUnlockUser(userId);
- }
- });
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mService.mHandler.post(() -> mService.onUnlockUser(user.getUserIdentifier()));
}
@Override
- public void onCleanupUser(int userHandle) {
- mService.onCleanupUser(userHandle);
+ public void onUserStopped(@NonNull TargetUser user) {
+ mService.onCleanupUser(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 7c8c49461e64..4349ca451c36 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -26,6 +26,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Process.SYSTEM_UID;
import android.Manifest.permission;
+import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.app.slice.ISliceManager;
import android.app.slice.SliceSpec;
@@ -59,10 +60,10 @@ import android.util.Xml.Encoding;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
-import com.android.internal.util.Preconditions;
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;
@@ -615,13 +616,13 @@ public class SliceManagerService extends ISliceManager.Stub {
}
@Override
- public void onUnlockUser(int userHandle) {
- mService.onUnlockUser(userHandle);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mService.onUnlockUser(user.getUserIdentifier());
}
@Override
- public void onStopUser(int userHandle) {
- mService.onStopUser(userHandle);
+ public void onUserStopping(@NonNull TargetUser user) {
+ mService.onStopUser(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 93ea5e3a3c2b..9bc8afa3561f 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -67,6 +67,7 @@ import com.android.server.UiThread;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.notification.NotificationDelegate;
import com.android.server.policy.GlobalActionsProvider;
+import com.android.server.power.ShutdownCheckPoints;
import com.android.server.power.ShutdownThread;
import java.io.FileDescriptor;
@@ -1182,13 +1183,14 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
@Override
public void shutdown() {
enforceStatusBarService();
+ String reason = PowerManager.SHUTDOWN_USER_REQUESTED;
+ ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.prepareForPossibleShutdown();
// ShutdownThread displays UI, so give it a UI context.
mHandler.post(() ->
- ShutdownThread.shutdown(getUiContext(),
- PowerManager.SHUTDOWN_USER_REQUESTED, false));
+ ShutdownThread.shutdown(getUiContext(), reason, false));
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1200,6 +1202,10 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
@Override
public void reboot(boolean safeMode) {
enforceStatusBarService();
+ String reason = safeMode
+ ? PowerManager.REBOOT_SAFE_MODE
+ : PowerManager.SHUTDOWN_USER_REQUESTED;
+ ShutdownCheckPoints.recordCheckPoint(Binder.getCallingPid(), reason);
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.prepareForPossibleShutdown();
@@ -1208,8 +1214,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
if (safeMode) {
ShutdownThread.rebootSafeMode(getUiContext(), true);
} else {
- ShutdownThread.reboot(getUiContext(),
- PowerManager.SHUTDOWN_USER_REQUESTED, false);
+ ShutdownThread.reboot(getUiContext(), reason, false);
}
});
} finally {
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index 361a5067b9bf..1c29c69239f6 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -29,6 +29,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
@@ -64,9 +65,6 @@ public final class StorageUserConnection {
private static final String TAG = "StorageUserConnection";
private static final int DEFAULT_REMOTE_TIMEOUT_SECONDS = 20;
- // TODO(b/161702661): Workaround for demo user to have shorter timeout.
- // This allows the DevicePolicyManagerService#enableSystemApp call to succeed without ANR.
- private static final int DEMO_USER_REMOTE_TIMEOUT_SECONDS = 5;
private final Object mLock = new Object();
private final Context mContext;
@@ -75,6 +73,7 @@ public final class StorageUserConnection {
private final ActiveConnection mActiveConnection = new ActiveConnection();
private final boolean mIsDemoUser;
@GuardedBy("mLock") private final Map<String, Session> mSessions = new HashMap<>();
+ @GuardedBy("mLock") @Nullable private HandlerThread mHandlerThread;
public StorageUserConnection(Context context, int userId, StorageSessionController controller) {
mContext = Objects.requireNonNull(context);
@@ -82,6 +81,10 @@ public final class StorageUserConnection {
mSessionController = controller;
mIsDemoUser = LocalServices.getService(UserManagerInternal.class)
.getUserInfo(userId).isDemo();
+ if (mIsDemoUser) {
+ mHandlerThread = new HandlerThread("StorageUserConnectionThread-" + mUserId);
+ mHandlerThread.start();
+ }
}
/**
@@ -188,6 +191,9 @@ public final class StorageUserConnection {
*/
public void close() {
mActiveConnection.close();
+ if (mIsDemoUser) {
+ mHandlerThread.quit();
+ }
}
/** Returns all created sessions. */
@@ -207,8 +213,7 @@ public final class StorageUserConnection {
private void waitForLatch(CountDownLatch latch, String reason) throws TimeoutException {
try {
- if (!latch.await(mIsDemoUser ? DEMO_USER_REMOTE_TIMEOUT_SECONDS
- : DEFAULT_REMOTE_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
+ if (!latch.await(DEFAULT_REMOTE_TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
// TODO(b/140025078): Call ActivityManager ANR API?
Slog.wtf(TAG, "Failed to bind to the ExternalStorageService for user " + mUserId);
throw new TimeoutException("Latch wait for " + reason + " elapsed");
@@ -424,15 +429,32 @@ public final class StorageUserConnection {
};
Slog.i(TAG, "Binding to the ExternalStorageService for user " + mUserId);
- if (mContext.bindServiceAsUser(new Intent().setComponent(name), mServiceConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
- UserHandle.of(mUserId))) {
- Slog.i(TAG, "Bound to the ExternalStorageService for user " + mUserId);
- return mLatch;
+ if (mIsDemoUser) {
+ // Schedule on a worker thread for demo user to avoid deadlock
+ if (mContext.bindServiceAsUser(new Intent().setComponent(name),
+ mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
+ mHandlerThread.getThreadHandler(),
+ UserHandle.of(mUserId))) {
+ Slog.i(TAG, "Bound to the ExternalStorageService for user " + mUserId);
+ return mLatch;
+ } else {
+ mIsConnecting = false;
+ throw new ExternalStorageServiceException(
+ "Failed to bind to the ExternalStorageService for user " + mUserId);
+ }
} else {
- mIsConnecting = false;
- throw new ExternalStorageServiceException(
- "Failed to bind to the ExternalStorageService for user " + mUserId);
+ if (mContext.bindServiceAsUser(new Intent().setComponent(name),
+ mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
+ UserHandle.of(mUserId))) {
+ Slog.i(TAG, "Bound to the ExternalStorageService for user " + mUserId);
+ return mLatch;
+ } else {
+ mIsConnecting = false;
+ throw new ExternalStorageServiceException(
+ "Failed to bind to the ExternalStorageService for user " + mUserId);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 1707d9542813..363e86dea8b1 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -66,6 +66,7 @@ import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -118,14 +119,14 @@ public final class TextClassificationManagerService extends ITextClassifierServi
}
@Override
- public void onStartUser(int userId) {
- processAnyPendingWork(userId);
+ public void onUserStarting(@NonNull TargetUser user) {
+ processAnyPendingWork(user.getUserIdentifier());
}
@Override
- public void onUnlockUser(int userId) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
// Rebind if we failed earlier due to locked encrypted user
- processAnyPendingWork(userId);
+ processAnyPendingWork(user.getUserIdentifier());
}
private void processAnyPendingWork(int userId) {
@@ -135,7 +136,9 @@ public final class TextClassificationManagerService extends ITextClassifierServi
}
@Override
- public void onStopUser(int userId) {
+ public void onUserStopping(@NonNull TargetUser user) {
+ int userId = user.getUserIdentifier();
+
synchronized (mManagerService.mLock) {
UserState userState = mManagerService.peekUserStateLocked(userId);
if (userState != null) {
diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
index e0bac93cce16..f39067b110a8 100644
--- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
@@ -58,6 +58,7 @@ import com.android.internal.textservice.ITextServicesSessionListener;
import com.android.internal.util.DumpUtils;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import org.xmlpull.v1.XmlPullParserException;
@@ -287,21 +288,21 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
}
@Override
- public void onStopUser(@UserIdInt int userHandle) {
+ public void onUserStopping(@NonNull TargetUser user) {
if (DBG) {
- Slog.d(TAG, "onStopUser userId: " + userHandle);
+ Slog.d(TAG, "onStopUser user: " + user);
}
- mService.onStopUser(userHandle);
+ mService.onStopUser(user.getUserIdentifier());
}
@Override
- public void onUnlockUser(@UserIdInt int userHandle) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
if(DBG) {
- Slog.d(TAG, "onUnlockUser userId: " + userHandle);
+ Slog.d(TAG, "onUnlockUser userId: " + user);
}
// Called on the system server's main looper thread.
// TODO: Dispatch this to a worker thread as needed.
- mService.onUnlockUser(userHandle);
+ mService.onUnlockUser(user.getUserIdentifier());
}
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index fd3c1f97df8b..6adff0d32d88 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -17,6 +17,8 @@
package com.android.server.trust;
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AlarmManager;
@@ -71,6 +73,7 @@ import com.android.internal.content.PackageMonitor;
import com.android.internal.util.DumpUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -1042,28 +1045,28 @@ public class TrustManagerService extends SystemService {
// User lifecycle
@Override
- public void onStartUser(int userId) {
- mHandler.obtainMessage(MSG_START_USER, userId, 0, null).sendToTarget();
+ public void onUserStarting(@NonNull TargetUser user) {
+ mHandler.obtainMessage(MSG_START_USER, user.getUserIdentifier(), 0, null).sendToTarget();
}
@Override
- public void onCleanupUser(int userId) {
- mHandler.obtainMessage(MSG_CLEANUP_USER, userId, 0, null).sendToTarget();
+ public void onUserStopped(@NonNull TargetUser user) {
+ mHandler.obtainMessage(MSG_CLEANUP_USER, user.getUserIdentifier(), 0, null).sendToTarget();
}
@Override
- public void onSwitchUser(int userId) {
- mHandler.obtainMessage(MSG_SWITCH_USER, userId, 0, null).sendToTarget();
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
+ mHandler.obtainMessage(MSG_SWITCH_USER, to.getUserIdentifier(), 0, null).sendToTarget();
}
@Override
- public void onUnlockUser(int userId) {
- mHandler.obtainMessage(MSG_UNLOCK_USER, userId, 0, null).sendToTarget();
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mHandler.obtainMessage(MSG_UNLOCK_USER, user.getUserIdentifier(), 0, null).sendToTarget();
}
@Override
- public void onStopUser(@UserIdInt int userId) {
- mHandler.obtainMessage(MSG_STOP_USER, userId, 0, null).sendToTarget();
+ public void onUserStopping(@NonNull TargetUser user) {
+ mHandler.obtainMessage(MSG_STOP_USER, user.getUserIdentifier(), 0, null).sendToTarget();
}
// Plumbing
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 323ac7b8806e..b3ec849e6c90 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -20,6 +20,7 @@ import static android.media.AudioManager.DEVICE_NONE;
import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
@@ -83,6 +84,7 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.IoThread;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import java.io.File;
import java.io.FileDescriptor;
@@ -165,10 +167,10 @@ public final class TvInputManagerService extends SystemService {
}
@Override
- public void onUnlockUser(int userHandle) {
- if (DEBUG) Slog.d(TAG, "onUnlockUser(userHandle=" + userHandle + ")");
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ if (DEBUG) Slog.d(TAG, "onUnlockUser(user=" + user + ")");
synchronized (mLock) {
- if (mCurrentUserId != userHandle) {
+ if (mCurrentUserId != user.getUserIdentifier()) {
return;
}
buildTvInputListLocked(mCurrentUserId, null);
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index 88a60ddc5a1e..47ab12742e9d 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -23,7 +23,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.icu.impl.CalendarAstronomer;
import android.icu.util.Calendar;
import android.location.Location;
import android.location.LocationListener;
@@ -38,6 +37,8 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
+import com.ibm.icu.impl.CalendarAstronomer;
+
import java.util.Objects;
/**
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 45689ce73c9f..ae873e2fe467 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -19,6 +19,7 @@ import static android.view.Display.INVALID_DISPLAY;
import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
@@ -65,6 +66,7 @@ import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.utils.ManagedApplicationService;
import com.android.server.utils.ManagedApplicationService.BinderChecker;
import com.android.server.utils.ManagedApplicationService.LogEvent;
@@ -817,14 +819,14 @@ public class VrManagerService extends SystemService
}
@Override
- public void onStartUser(int userHandle) {
+ public void onUserStarting(@NonNull TargetUser user) {
synchronized (mLock) {
mComponentObserver.onUsersChanged();
}
}
@Override
- public void onSwitchUser(int userHandle) {
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
FgThread.getHandler().post(() -> {
synchronized (mLock) {
mComponentObserver.onUsersChanged();
@@ -834,7 +836,7 @@ public class VrManagerService extends SystemService
}
@Override
- public void onStopUser(int userHandle) {
+ public void onUserStopping(@NonNull TargetUser user) {
synchronized (mLock) {
mComponentObserver.onUsersChanged();
}
@@ -842,7 +844,7 @@ public class VrManagerService extends SystemService
}
@Override
- public void onCleanupUser(int userHandle) {
+ public void onUserStopped(@NonNull TargetUser user) {
synchronized (mLock) {
mComponentObserver.onUsersChanged();
}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 90f87b16e70d..2f695c6fd3f1 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -105,6 +105,7 @@ import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.wm.WindowManagerInternal;
@@ -166,9 +167,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
@Override
- public void onUnlockUser(int userHandle) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
if (mService != null) {
- mService.onUnlockUser(userHandle);
+ mService.onUnlockUser(user.getUserIdentifier());
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index dd67b3d2c330..b72ff2db7e6c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2865,7 +2865,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (hasProcess()) {
if (removeFromApp) {
- app.removeActivity(this);
+ app.removeActivity(this, true /* keepAssociation */);
if (!app.hasActivities()) {
mAtmService.clearHeavyWeightProcessIfEquals(app);
// Update any services we are bound to that might care about whether
@@ -2914,7 +2914,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
setState(DESTROYED,
"destroyActivityLocked. not finishing or skipping destroy");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this);
- app = null;
+ detachFromProcess();
}
} else {
// Remove this record from the history.
@@ -2963,13 +2963,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
setState(DESTROYED, "removeFromHistory");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
- app = null;
+ detachFromProcess();
removeAppTokenFromDisplay();
cleanUpActivityServices();
removeUriPermissionsLocked();
}
+ void detachFromProcess() {
+ if (app != null) {
+ app.removeActivity(this, false /* keepAssociation */);
+ }
+ app = null;
+ }
+
void makeFinishingLocked() {
if (finishing) {
return;
@@ -3019,7 +3026,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (setState) {
setState(DESTROYED, "cleanUp");
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + this);
- app = null;
+ detachFromProcess();
}
// Inform supervisor the activity has been removed.
@@ -3160,6 +3167,64 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mServiceConnectionsHolder = null;
}
+ /**
+ * Detach this activity from process and clear the references to it. If the activity is
+ * finishing or has no saved state or crashed many times, it will also be removed from history.
+ */
+ void handleAppDied() {
+ final boolean remove;
+ if ((mRelaunchReason == RELAUNCH_REASON_WINDOWING_MODE_RESIZE
+ || mRelaunchReason == RELAUNCH_REASON_FREE_RESIZE)
+ && launchCount < 3 && !finishing) {
+ // If the process crashed during a resize, always try to relaunch it, unless it has
+ // failed more than twice. Skip activities that's already finishing cleanly by itself.
+ remove = false;
+ } else if ((!mHaveState && !stateNotNeeded
+ && !isState(ActivityState.RESTARTING_PROCESS)) || finishing) {
+ // Don't currently have state for the activity, or it is finishing -- always remove it.
+ remove = true;
+ } else if (!mVisibleRequested && launchCount > 2
+ && lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
+ // We have launched this activity too many times since it was able to run, so give up
+ // and remove it. (Note if the activity is visible, we don't remove the record. We leave
+ // the dead window on the screen but the process will not be restarted unless user
+ // explicitly tap on it.)
+ remove = true;
+ } else {
+ // The process may be gone, but the activity lives on!
+ remove = false;
+ }
+ if (remove) {
+ if (ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
+ Slog.i(TAG_ADD_REMOVE, "Removing activity " + this
+ + " hasSavedState=" + mHaveState + " stateNotNeeded=" + stateNotNeeded
+ + " finishing=" + finishing + " state=" + mState
+ + " callers=" + Debug.getCallers(5));
+ }
+ if (!finishing || (app != null && app.isRemoved())) {
+ Slog.w(TAG, "Force removing " + this + ": app died, no saved state");
+ EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),
+ task != null ? task.mTaskId : -1, shortComponentName,
+ "proc died without state saved");
+ }
+ } else {
+ // We have the current state for this activity, so it can be restarted later
+ // when needed.
+ if (DEBUG_APP) {
+ Slog.v(TAG_APP, "Keeping entry during removeHistory for activity " + this);
+ }
+ // Set nowVisible to previous visible state. If the app was visible while it died, we
+ // leave the dead window on screen so it's basically visible. This is needed when user
+ // later tap on the dead window, we need to stop other apps when user transfers focus
+ // to the restarted activity.
+ nowVisible = mVisibleRequested;
+ }
+ cleanUp(true /* cleanServices */, true /* setState */);
+ if (remove) {
+ removeFromHistory("appDied");
+ }
+ }
+
@Override
void removeImmediately() {
onRemovedFromDisplay();
@@ -4114,6 +4179,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Now that the app is going invisible, we can remove it. It will be restarted
// if made visible again.
removeDeadWindows();
+ // If this activity is about to finish/stopped and now becomes invisible, remove it
+ // from the unknownApp list in case the activity does not want to draw anything, which
+ // keep the user waiting for the next transition to start.
+ if (finishing || isState(STOPPED)) {
+ displayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
+ }
} else {
if (!appTransition.isTransitionSet()
&& appTransition.isReady()) {
@@ -5919,10 +5990,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// stack, i.e. the hierarchy of the surfaces is unchanged.
if (inPinnedWindowingMode()) {
return getStack().getSurfaceControl();
- } else if (WindowManagerService.sHierarchicalAnimations) {
- return super.getAnimationLeashParent();
} else {
- return getAppAnimationLayer();
+ return super.getAnimationLeashParent();
}
}
@@ -6010,11 +6079,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mAnimationBoundsLayer = createAnimationBoundsLayer(t);
// Crop to stack bounds.
- if (!WindowManagerService.sHierarchicalAnimations) {
- // For Hierarchical animation, we don't need to set window crop since the leash
- // surface size has already same as the animating container.
- t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
- }
t.setLayer(leash, 0);
t.setLayer(mAnimationBoundsLayer, getAnimationLayer());
@@ -7568,6 +7632,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
@Override
+ boolean canCustomizeAppTransition() {
+ return true;
+ }
+
+ @Override
public String toString() {
if (stringName != null) {
return stringName + " t" + (task == null ? INVALID_TASK_ID : task.mTaskId) +
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 04b1edc3eede..ed1ea353eb3e 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -891,7 +891,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// This is the first time we failed -- restart process and
// retry.
r.launchFailed = true;
- proc.removeActivity(r);
+ proc.removeActivity(r, true /* keepAssociation */);
throw e;
}
} finally {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index e84f040931bb..f7cb0146ea52 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -118,6 +118,7 @@ import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.IVoiceInteractor;
import com.android.server.am.PendingIntentRecord;
import com.android.server.pm.InstantAppResolver;
+import com.android.server.power.ShutdownCheckPoints;
import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
import com.android.server.wm.ActivityStackSupervisor.PendingActivityLaunch;
@@ -647,6 +648,19 @@ class ActivityStarter {
mRequest.resolveActivity(mSupervisor);
}
+ // Add checkpoint for this shutdown or reboot attempt, so we can record the original
+ // intent action and package name.
+ if (mRequest.intent != null) {
+ String intentAction = mRequest.intent.getAction();
+ String callingPackage = mRequest.callingPackage;
+ if (intentAction != null && callingPackage != null
+ && (Intent.ACTION_REQUEST_SHUTDOWN.equals(intentAction)
+ || Intent.ACTION_SHUTDOWN.equals(intentAction)
+ || Intent.ACTION_REBOOT.equals(intentAction))) {
+ ShutdownCheckPoints.recordCheckPoint(intentAction, callingPackage, null);
+ }
+ }
+
int res;
synchronized (mService.mGlobalLock) {
final boolean globalConfigWillChange = mRequest.globalConfig != null
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index c4af3e2c04c9..5534b8c257f0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -254,6 +254,7 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.AttributeCache;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.SystemServiceManager;
import com.android.server.UiThread;
import com.android.server.Watchdog;
@@ -1027,16 +1028,17 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
- public void onUnlockUser(int userId) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
synchronized (mService.getGlobalLock()) {
- mService.mStackSupervisor.onUserUnlocked(userId);
+ mService.mStackSupervisor.onUserUnlocked(user.getUserIdentifier());
}
}
@Override
- public void onCleanupUser(int userId) {
+ public void onUserStopped(@NonNull TargetUser user) {
synchronized (mService.getGlobalLock()) {
- mService.mStackSupervisor.mLaunchParamsPersister.onCleanupUser(userId);
+ mService.mStackSupervisor.mLaunchParamsPersister
+ .onCleanupUser(user.getUserIdentifier());
}
}
@@ -6789,11 +6791,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public void handleAppDied(WindowProcessController wpc, boolean restarting,
Runnable finishInstrumentationCallback) {
synchronized (mGlobalLockWithoutBoost) {
- // Remove this application's activities from active lists.
- boolean hasVisibleActivities = mRootWindowContainer.handleAppDied(wpc);
-
- wpc.clearRecentTasks();
- wpc.clearActivities();
+ mStackSupervisor.beginDeferResume();
+ final boolean hasVisibleActivities;
+ try {
+ // Remove this application's activities from active lists.
+ hasVisibleActivities = wpc.handleAppDied();
+ } finally {
+ mStackSupervisor.endDeferResume();
+ }
if (wpc.isInstrumenting()) {
finishInstrumentationCallback.run();
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 3abc54f8f2eb..11a468be8f9f 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -203,6 +203,7 @@ public class AppTransition implements Dump {
private static final int NEXT_TRANSIT_TYPE_REMOTE = 10;
private int mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
+ private boolean mNextAppTransitionOverrideRequested;
// These are the possible states for the enter/exit activities during a thumbnail transition
private static final int THUMBNAIL_TRANSITION_ENTER_SCALE_UP = 0;
@@ -337,6 +338,11 @@ public class AppTransition implements Dump {
mNextAppTransitionFlags |= flags;
setLastAppTransition(TRANSIT_UNSET, null, null, null);
updateBooster();
+ if (isTransitionSet()) {
+ removeAppTransitionTimeoutCallbacks();
+ mHandler.postDelayed(mHandleAppTransitionTimeoutRunnable,
+ APP_TRANSITION_TIMEOUT_MS);
+ }
}
void setLastAppTransition(int transit, ActivityRecord openingApp, ActivityRecord closingApp,
@@ -454,6 +460,7 @@ public class AppTransition implements Dump {
void clear() {
mNextAppTransitionType = NEXT_TRANSIT_TYPE_NONE;
+ mNextAppTransitionOverrideRequested = false;
mNextAppTransitionPackage = null;
mNextAppTransitionAnimationsSpecs.clear();
mRemoteAnimationController = null;
@@ -1574,6 +1581,7 @@ public class AppTransition implements Dump {
*/
boolean canSkipFirstFrame() {
return mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM
+ && !mNextAppTransitionOverrideRequested
&& mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE
&& mNextAppTransitionType != NEXT_TRANSIT_TYPE_CLIP_REVEAL
&& mNextAppTransition != TRANSIT_KEYGUARD_GOING_AWAY;
@@ -1608,6 +1616,11 @@ public class AppTransition implements Dump {
int orientation, Rect frame, Rect displayFrame, Rect insets,
@Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction,
boolean freeform, WindowContainer container) {
+
+ if (mNextAppTransitionOverrideRequested && container.canCustomizeAppTransition()) {
+ mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
+ }
+
Animation a;
if (isKeyguardGoingAwayTransit(transit) && enter) {
a = loadKeyguardExitAnimation(transit);
@@ -1648,7 +1661,6 @@ public class AppTransition implements Dump {
"applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s "
+ "isEntrance=%b Callers=%s",
a, appTransitionToString(transit), enter, Debug.getCallers(3));
- setAppTransitionFinishedCallbackIfNeeded(a);
} else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) {
a = loadAnimationRes(mNextAppTransitionPackage, mNextAppTransitionInPlace);
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
@@ -1775,6 +1787,7 @@ public class AppTransition implements Dump {
a, animAttr, appTransitionToString(transit), enter,
Debug.getCallers(3));
}
+ setAppTransitionFinishedCallbackIfNeeded(a);
return a;
}
@@ -1816,7 +1829,7 @@ public class AppTransition implements Dump {
IRemoteCallback startedCallback, IRemoteCallback endedCallback) {
if (canOverridePendingAppTransition()) {
clear();
- mNextAppTransitionType = NEXT_TRANSIT_TYPE_CUSTOM;
+ mNextAppTransitionOverrideRequested = true;
mNextAppTransitionPackage = packageName;
mNextAppTransitionEnter = enterAnim;
mNextAppTransitionExit = exitAnim;
@@ -2134,15 +2147,16 @@ public class AppTransition implements Dump {
pw.print(prefix); pw.print("mNextAppTransitionType=");
pw.println(transitTypeToString());
}
+ if (mNextAppTransitionOverrideRequested
+ || mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
+ pw.print(prefix); pw.print("mNextAppTransitionPackage=");
+ pw.println(mNextAppTransitionPackage);
+ pw.print(prefix); pw.print("mNextAppTransitionEnter=0x");
+ pw.print(Integer.toHexString(mNextAppTransitionEnter));
+ pw.print(" mNextAppTransitionExit=0x");
+ pw.println(Integer.toHexString(mNextAppTransitionExit));
+ }
switch (mNextAppTransitionType) {
- case NEXT_TRANSIT_TYPE_CUSTOM:
- pw.print(prefix); pw.print("mNextAppTransitionPackage=");
- pw.println(mNextAppTransitionPackage);
- pw.print(prefix); pw.print("mNextAppTransitionEnter=0x");
- pw.print(Integer.toHexString(mNextAppTransitionEnter));
- pw.print(" mNextAppTransitionExit=0x");
- pw.println(Integer.toHexString(mNextAppTransitionExit));
- break;
case NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE:
pw.print(prefix); pw.print("mNextAppTransitionPackage=");
pw.println(mNextAppTransitionPackage);
@@ -2229,12 +2243,7 @@ public class AppTransition implements Dump {
setAppTransition(transit, flags);
}
}
- boolean prepared = prepare();
- if (isTransitionSet()) {
- removeAppTransitionTimeoutCallbacks();
- mHandler.postDelayed(mHandleAppTransitionTimeoutRunnable, APP_TRANSITION_TIMEOUT_MS);
- }
- return prepared;
+ return prepare();
}
/**
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index d60d098071cc..5720e9b7f193 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -411,10 +411,6 @@ public class AppTransitionController {
}
}
- if (!WindowManagerService.sHierarchicalAnimations) {
- return new ArraySet<>(candidates);
- }
-
final ArraySet<ActivityRecord> otherApps = visible ? closingApps : openingApps;
// Ancestors of closing apps while finding animation targets for opening apps, or ancestors
// of opening apps while finding animation targets for closing apps.
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 0d8e882ad58f..13033a6fcf81 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -93,9 +93,17 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
private final Rect mTmpRect = new Rect();
static final int BOUNDS_CHANGE_NONE = 0;
- // Return value from {@link setBounds} indicating the position of the override bounds changed.
+
+ /**
+ * Return value from {@link #setBounds(Rect)} indicating the position of the override bounds
+ * changed.
+ */
static final int BOUNDS_CHANGE_POSITION = 1;
- // Return value from {@link setBounds} indicating the size of the override bounds changed.
+
+ /**
+ * Return value from {@link #setBounds(Rect)} indicating the size of the override bounds
+ * changed.
+ */
static final int BOUNDS_CHANGE_SIZE = 1 << 1;
/**
@@ -226,6 +234,11 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return equivalentBounds(getRequestedOverrideBounds(), bounds);
}
+ /** Similar to {@link #equivalentRequestedOverrideBounds(Rect)}, but compares max bounds. */
+ public boolean equivalentRequestedOverrideMaxBounds(Rect bounds) {
+ return equivalentBounds(getRequestedOverrideMaxBounds(), bounds);
+ }
+
/**
* Returns whether the two bounds are equal to each other or are a combination of null or empty.
*/
@@ -238,7 +251,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
/**
* Returns the effective bounds of this container, inheriting the first non-empty bounds set in
* its ancestral hierarchy, including itself.
- * @return
*/
public Rect getBounds() {
mReturnBounds.set(getConfiguration().windowConfiguration.getBounds());
@@ -249,6 +261,12 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
outBounds.set(getBounds());
}
+ /** Similar to {@link #getBounds()}, but reports the max bounds. */
+ public Rect getMaxBounds() {
+ mReturnBounds.set(getConfiguration().windowConfiguration.getMaxBounds());
+ return mReturnBounds;
+ }
+
/**
* Sets {@code out} to the top-left corner of the bounds as returned by {@link #getBounds()}.
*/
@@ -273,6 +291,13 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return mReturnBounds;
}
+ /** Similar to {@link #getRequestedOverrideBounds()}, but returns the max bounds. */
+ public Rect getRequestedOverrideMaxBounds() {
+ mReturnBounds.set(getRequestedOverrideConfiguration().windowConfiguration.getMaxBounds());
+
+ return mReturnBounds;
+ }
+
/**
* Returns {@code true} if the {@link WindowConfiguration} in the requested override
* {@link Configuration} specifies bounds.
@@ -283,7 +308,7 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
/**
* Sets the passed in {@link Rect} to the current bounds.
- * @see {@link #getRequestedOverrideBounds()}.
+ * @see #getRequestedOverrideBounds()
*/
public void getRequestedOverrideBounds(Rect outBounds) {
outBounds.set(getRequestedOverrideBounds());
@@ -295,19 +320,25 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
* {@link #getRequestedOverrideBounds()}. If
* an empty {@link Rect} or null is specified, this container will be considered to match its
* parent bounds {@see #matchParentBounds} and will inherit bounds from its parent.
+ *
* @param bounds The bounds defining the container size.
+ *
* @return a bitmask representing the types of changes made to the bounds.
*/
public int setBounds(Rect bounds) {
int boundsChange = diffRequestedOverrideBounds(bounds);
+ final boolean overrideMaxBounds = providesMaxBounds()
+ && diffRequestedOverrideMaxBounds(bounds) != BOUNDS_CHANGE_NONE;
- if (boundsChange == BOUNDS_CHANGE_NONE) {
+ if (boundsChange == BOUNDS_CHANGE_NONE && !overrideMaxBounds) {
return boundsChange;
}
-
mRequestsTmpConfig.setTo(getRequestedOverrideConfiguration());
mRequestsTmpConfig.windowConfiguration.setBounds(bounds);
+ if (overrideMaxBounds) {
+ mRequestsTmpConfig.windowConfiguration.setMaxBounds(bounds);
+ }
onRequestedOverrideConfigurationChanged(mRequestsTmpConfig);
return boundsChange;
@@ -318,6 +349,40 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return setBounds(mTmpRect);
}
+ /**
+ * Returns {@code true} if this {@link ConfigurationContainer} provides the maximum bounds to
+ * its child {@link ConfigurationContainer}s. Returns {@code false}, otherwise.
+ * <p>
+ * The maximum bounds is how large a window can be expanded. Currently only
+ * {@link DisplayContent} and {@link DisplayArea} effect this property.
+ * </p>
+ */
+ protected boolean providesMaxBounds() {
+ return false;
+ }
+
+ int diffRequestedOverrideMaxBounds(Rect bounds) {
+ if (equivalentRequestedOverrideMaxBounds(bounds)) {
+ return BOUNDS_CHANGE_NONE;
+ }
+
+ int boundsChange = BOUNDS_CHANGE_NONE;
+
+ final Rect existingBounds = getRequestedOverrideMaxBounds();
+
+ if (bounds == null || existingBounds.left != bounds.left
+ || existingBounds.top != bounds.top) {
+ boundsChange |= BOUNDS_CHANGE_POSITION;
+ }
+
+ if (bounds == null || existingBounds.width() != bounds.width()
+ || existingBounds.height() != bounds.height()) {
+ boundsChange |= BOUNDS_CHANGE_SIZE;
+ }
+
+ return boundsChange;
+ }
+
int diffRequestedOverrideBounds(Rect bounds) {
if (equivalentRequestedOverrideBounds(bounds)) {
return BOUNDS_CHANGE_NONE;
@@ -340,10 +405,6 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
return boundsChange;
}
- boolean hasOverrideConfiguration() {
- return mHasOverrideConfiguration;
- }
-
public WindowConfiguration getWindowConfiguration() {
return mFullConfiguration.windowConfiguration;
}
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 546c5d4c29de..6ffb48282017 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -25,6 +25,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS;
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;
@@ -194,6 +195,7 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
final long token = proto.start(fieldId);
super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
proto.write(NAME, mName);
+ proto.write(IS_TASK_DISPLAY_AREA, isTaskDisplayArea());
proto.end(token);
}
@@ -349,6 +351,15 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> {
return info;
}
+ @Override
+ public boolean providesMaxBounds() {
+ return true;
+ }
+
+ protected boolean isTaskDisplayArea() {
+ return false;
+ }
+
/**
* DisplayArea that contains WindowTokens, and orders them according to their type.
*/
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
index 33eb3ce57373..be18d0a9a6df 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
@@ -37,18 +37,19 @@ import java.util.ArrayList;
import java.util.List;
/**
- * Policy that manages DisplayAreas.
+ * Policy that manages {@link DisplayArea}.
*/
public abstract class DisplayAreaPolicy {
protected final WindowManagerService mWmService;
/**
- * The root DisplayArea. Attach all DisplayAreas to this area (directly or indirectly).
+ * The {@link RootDisplayArea} of the whole logical display. All {@link DisplayArea}s must be
+ * (direct or indirect) descendants of this area.
*/
protected final RootDisplayArea mRoot;
/**
- * Construct a new {@link DisplayAreaPolicy}
+ * Constructs a new {@link DisplayAreaPolicy}
*
* @param wmService the window manager service instance
* @param root the root display area under which the policy operates
@@ -59,9 +60,10 @@ public abstract class DisplayAreaPolicy {
}
/**
- * Called to ask the policy to attach the given WindowToken to the DisplayArea hierarchy.
+ * Called to ask the policy to attach the given {@link WindowToken} to the {@link DisplayArea}
+ * hierarchy.
*
- * This must attach the token to mRoot (or one of its descendants).
+ * <p>This must attach the token to {@link #mRoot} (or one of its descendants).
*/
public abstract void addWindow(WindowToken token);
@@ -121,13 +123,14 @@ public abstract class DisplayAreaPolicy {
/**
* Provider for {@link DisplayAreaPolicy} instances.
*
- * By implementing this interface and overriding the
+ * <p>By implementing this interface and overriding the
* {@code config_deviceSpecificDisplayAreaPolicyProvider}, a device-specific implementations
* of {@link DisplayAreaPolicy} can be supplied.
*/
public interface Provider {
/**
- * Instantiates a new DisplayAreaPolicy. It should set up the {@link DisplayArea} hierarchy.
+ * Instantiates a new {@link DisplayAreaPolicy}. It should set up the {@link DisplayArea}
+ * hierarchy.
*
* @see DisplayAreaPolicy#DisplayAreaPolicy
*/
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
index 681b21cfc829..b6cff625da5d 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
@@ -46,31 +46,90 @@ import java.util.function.BiFunction;
* A builder for instantiating a complex {@link DisplayAreaPolicy}
*
* <p>Given a set of features (that each target a set of window types), it builds the necessary
- * DisplayArea hierarchy.
+ * {@link DisplayArea} hierarchy.
*
- * <p>Example: <br />
+ * <p>Example:
*
- * <pre>
- * // Feature for targeting everything below the magnification overlay:
- * new DisplayAreaPolicyBuilder(...)
- * .addFeature(new Feature.Builder(..., "Magnification")
- * .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
- * .build())
- * .build(...)
+ * <pre class="prettyprint">
+ * // Build root hierarchy of the logical display.
+ * DisplayAreaPolicyBuilder.HierarchyBuilder rootHierarchy =
+ * new DisplayAreaPolicyBuilder.HierarchyBuilder(root)
+ * // Feature for targeting everything below the magnification overlay
+ * .addFeature(new DisplayAreaPolicyBuilder.Feature.Builder(wmService.mPolicy,
+ * "WindowedMagnification", FEATURE_WINDOWED_MAGNIFICATION)
+ * .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
+ * .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
+ * // Make the DA dimmable so that the magnify window also mirrors the
+ * // dim layer
+ * .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
+ * .build())
+ * .setImeContainer(imeContainer)
+ * .setTaskDisplayAreas(rootTdaList);
*
- * // Builds a policy with the following hierarchy:
- * - RootDisplayArea
- * - Magnification
- * - DisplayArea.Tokens (Wallpapers are attached here)
- * - TaskDisplayArea
- * - DisplayArea.Tokens (windows above Tasks up to IME are attached here)
- * - ImeContainers
- * - DisplayArea.Tokens (windows above IME up to TYPE_ACCESSIBILITY_OVERLAY attached here)
- * - DisplayArea.Tokens (TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY and up are attached here)
+ * // Build root hierarchy of front and rear DisplayAreaGroup.
+ * RootDisplayArea frontRoot = new RootDisplayArea(wmService, "FrontRoot", FEATURE_FRONT_ROOT);
+ * DisplayAreaPolicyBuilder.HierarchyBuilder frontGroupHierarchy =
+ * new DisplayAreaPolicyBuilder.HierarchyBuilder(frontRoot)
+ * // (Optional) .addFeature(...)
+ * .setTaskDisplayAreas(frontTdaList);
*
+ * RootDisplayArea rearRoot = new RootDisplayArea(wmService, "RearRoot", FEATURE_REAR_ROOT);
+ * DisplayAreaPolicyBuilder.HierarchyBuilder rearGroupHierarchy =
+ * new DisplayAreaPolicyBuilder.HierarchyBuilder(rearRoot)
+ * // (Optional) .addFeature(...)
+ * .setTaskDisplayAreas(rearTdaList);
+ *
+ * // Define the function to select root for window to attach.
+ * BiFunction<WindowToken, Bundle, RootDisplayArea> selectRootForWindowFunc =
+ * (windowToken, bundle) -> {
+ * if (bundle == null) {
+ * return root;
+ * }
+ * // OEMs need to define the condition.
+ * if (...) {
+ * return frontRoot;
+ * }
+ * if (...) {
+ * return rearRoot;
+ * }
+ * return root;
+ * };
+ *
+ * return new DisplayAreaPolicyBuilder()
+ * .setRootHierarchy(rootHierarchy)
+ * .addDisplayAreaGroupHierarchy(frontGroupHierarchy)
+ * .addDisplayAreaGroupHierarchy(rearGroupHierarchy)
+ * .setSelectRootForWindowFunc(selectRootForWindowFunc)
+ * .build(wmService, content);
* </pre>
*
- * // TODO(b/158713595): document more complex scenarios where we need multiple areas per feature.
+ * This builds a policy with the following hierarchy:
+ * <pre class="prettyprint">
+ * - RootDisplayArea (DisplayContent)
+ * - WindowedMagnification
+ * - DisplayArea.Tokens (Wallpapers can be attached here)
+ * - TaskDisplayArea
+ * - RootDisplayArea (FrontRoot)
+ * - DisplayArea.Tokens (Wallpapers can be attached here)
+ * - TaskDisplayArea
+ * - DisplayArea.Tokens (windows above Tasks up to IME can be attached here)
+ * - DisplayArea.Tokens (windows above IME can be attached here)
+ * - RootDisplayArea (RearRoot)
+ * - DisplayArea.Tokens (Wallpapers can be attached here)
+ * - TaskDisplayArea
+ * - DisplayArea.Tokens (windows above Tasks up to IME can be attached here)
+ * - DisplayArea.Tokens (windows above IME can be attached here)
+ * - DisplayArea.Tokens (windows above Tasks up to IME can be attached here)
+ * - ImeContainers
+ * - DisplayArea.Tokens (windows above IME up to TYPE_ACCESSIBILITY_OVERLAY can be
+ * attached here)
+ * - DisplayArea.Tokens (TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY and up can be attached
+ * here)
+ * </pre>
+ * When a {@link WindowToken} of Wallpaper needs to be attached, the policy will call the OEM
+ * defined {@link #mSelectRootForWindowFunc} to get a {@link RootDisplayArea}. It will then place
+ * the window to the corresponding {@link DisplayArea.Tokens} under the returned root
+ * {@link RootDisplayArea}.
*/
class DisplayAreaPolicyBuilder {
@Nullable private HierarchyBuilder mRootHierarchyBuilder;
@@ -396,7 +455,7 @@ class DisplayAreaPolicyBuilder {
/**
* Returns the id of the feature.
*
- * Must be unique among the features added to a {@link DisplayAreaPolicyBuilder}.
+ * <p>Must be unique among the features added to a {@link DisplayAreaPolicyBuilder}.
*
* @see android.window.DisplayAreaOrganizer#FEATURE_SYSTEM_FIRST
* @see android.window.DisplayAreaOrganizer#FEATURE_VENDOR_FIRST
@@ -425,7 +484,7 @@ class DisplayAreaPolicyBuilder {
* For example, {@code all().except(TYPE_STATUS_BAR)} expresses that a feature should
* apply to all types except TYPE_STATUS_BAR.
*
- * The builder starts out with the feature not applying to any types.
+ * <p>The builder starts out with the feature not applying to any types.
*
* @param name the name of the feature.
* @param id of the feature. {@see Feature#getId}
@@ -599,7 +658,7 @@ class DisplayAreaPolicyBuilder {
* Whether to skip creating a {@link DisplayArea.Tokens} if {@link #mExisting} is
* {@code null}.
*
- * This will be set for {@link HierarchyBuilder#LEAF_TYPE_IME_CONTAINERS} and
+ * <p>This will be set for {@link HierarchyBuilder#LEAF_TYPE_IME_CONTAINERS} and
* {@link HierarchyBuilder#LEAF_TYPE_TASK_CONTAINERS}, because we don't want to create
* {@link DisplayArea.Tokens} for them even if they are not set.
*/
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 0b1f4d9e1613..fc170538994c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1930,6 +1930,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
final DisplayInfo displayInfo = updateDisplayAndOrientation(config.uiMode, config);
calculateBounds(displayInfo, mTmpBounds);
config.windowConfiguration.setBounds(mTmpBounds);
+ config.windowConfiguration.setMaxBounds(mTmpBounds);
config.windowConfiguration.setWindowingMode(getWindowingMode());
config.windowConfiguration.setDisplayWindowingMode(getWindowingMode());
@@ -2544,10 +2545,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return mDisplayAreaPolicy.getDefaultTaskDisplayArea();
}
- void positionDisplayAt(int position, boolean includingParents) {
- getParent().positionChildAt(position, this, includingParents);
- }
-
/**
* Returns true if the input point is within an app window.
*/
@@ -5393,6 +5390,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
});
}
+ @Override
+ public boolean providesMaxBounds() {
+ return true;
+ }
+
/** The entry for proceeding to handle {@link #mFixedRotationLaunchingApp}. */
class FixedRotationTransitionListener extends WindowManagerInternal.AppTransitionListener {
@@ -5403,6 +5405,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
private ActivityRecord mAnimatingRecents;
+ /** Whether {@link #mAnimatingRecents} is going to be the top activity. */
+ private boolean mRecentsWillBeTop;
+
/**
* If the recents activity has a fixed orientation which is different from the current top
* activity, it will be rotated before being shown so we avoid a screen rotation animation
@@ -5428,10 +5433,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
* If {@link #mAnimatingRecents} still has fixed rotation, it should be moved to top so we
* don't clear {@link #mFixedRotationLaunchingApp} that will be handled by transition.
*/
- void onFinishRecentsAnimation(boolean moveRecentsToBack) {
+ void onFinishRecentsAnimation() {
final ActivityRecord animatingRecents = mAnimatingRecents;
+ final boolean recentsWillBeTop = mRecentsWillBeTop;
mAnimatingRecents = null;
- if (!moveRecentsToBack) {
+ mRecentsWillBeTop = false;
+ if (recentsWillBeTop) {
// The recents activity will be the top, such as staying at recents list or
// returning to home (if home and recents are the same activity).
return;
@@ -5454,6 +5461,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
}
+ void notifyRecentsWillBeTop() {
+ mRecentsWillBeTop = true;
+ }
+
/**
* Return {@code true} if there is an ongoing animation to the "Recents" activity and this
* activity as a fixed orientation so shouldn't be rotated.
@@ -5474,6 +5485,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (r == null || r == mAnimatingRecents) {
return;
}
+ if (mAnimatingRecents != null && mRecentsWillBeTop) {
+ // The activity is not the recents and it should be moved to back later, so it is
+ // better to keep its current appearance for the next transition. Otherwise the
+ // display orientation may be updated too early and the layout procedures at the
+ // end of finishing recents animation is skipped. That causes flickering because
+ // the surface of closing app hasn't updated to invisible.
+ return;
+ }
if (mFixedRotationLaunchingApp == null) {
// In most cases this is a no-op if the activity doesn't have fixed rotation.
// Otherwise it could be from finishing recents animation while the display has
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 0e24fc8bd307..4f6f75d924c4 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -356,6 +356,8 @@ public class DisplayPolicy {
private WindowState mFocusedWindow;
private WindowState mLastFocusedWindow;
+ private WindowState mSystemUiControllingWindow;
+
// The states of decor windows from the last layout. These are used to generate another display
// layout in different bounds but with the same states.
private boolean mLastNavVisible;
@@ -3436,6 +3438,7 @@ public class DisplayPolicy {
}
}
final WindowState win = winCandidate;
+ mSystemUiControllingWindow = win;
mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
@@ -3740,8 +3743,12 @@ public class DisplayPolicy {
& WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
final boolean hideStatusBarSysui =
(vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
- final boolean hideNavBarSysui =
- (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
+ final boolean hideNavBarSysui = (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
+ // We shouldn't rely on the system UI visibilities anymore because the window can
+ // use the new API (e.g., WindowInsetsController.hide) to hide navigation bar.
+ // TODO(b/149813814): clean up the system UI flag usages in this function.
+ || !win.getRequestedInsetsState().getSourceOrDefaultVisibility(
+ ITYPE_NAVIGATION_BAR);
final boolean transientStatusBarAllowed = getStatusBar() != null
&& (notificationShadeHasFocus || (!mForceShowSystemBars
@@ -3755,15 +3762,16 @@ public class DisplayPolicy {
&& now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION;
final DisplayPolicy defaultDisplayPolicy =
mService.getDefaultDisplayContentLocked().getDisplayPolicy();
- if (pendingPanic && hideNavBarSysui && !isKeyguardShowing()
+ if (pendingPanic && hideNavBarSysui && win != mNotificationShade
+ && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)
// TODO (b/111955725): Show keyguard presentation on all external displays
&& defaultDisplayPolicy.isKeyguardDrawComplete()) {
// The user performed the panic gesture recently, we're about to hide the bars,
// we're no longer on the Keyguard and the screen is ready. We can now request the bars.
mPendingPanicGestureUptime = 0;
- mStatusBarController.showTransient();
if (!isNavBarEmpty(vis)) {
- mNavigationBarController.showTransient();
+ mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
+ new int[] {ITYPE_NAVIGATION_BAR}));
}
}
@@ -3908,6 +3916,9 @@ public class DisplayPolicy {
}
private boolean isImmersiveMode(WindowState win) {
+ if (win == null) {
+ return false;
+ }
final int behavior = win.mAttrs.insetsFlags.behavior;
return getNavigationBar() != null
&& canHideNavigationBar()
@@ -3942,11 +3953,7 @@ public class DisplayPolicy {
return;
}
mPendingPanicGestureUptime = SystemClock.uptimeMillis();
- if (!isNavBarEmpty(mLastSystemUiFlags)) {
- mNavigationBarController.showTransient();
- mDisplayContent.getInsetsPolicy().showTransient(IntArray.wrap(
- new int[] {ITYPE_NAVIGATION_BAR}));
- }
+ updateSystemUiVisibilityLw();
}
}
};
@@ -3955,7 +3962,7 @@ public class DisplayPolicy {
// Detect user pressing the power button in panic when an application has
// taken over the whole screen.
boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn,
- SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags),
+ SystemClock.elapsedRealtime(), isImmersiveMode(mSystemUiControllingWindow),
isNavBarEmpty(mLastSystemUiFlags));
if (panic) {
mHandler.post(mHiddenNavPanic);
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index f5bd4cd866a6..6b3a5d6bf18c 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -702,6 +702,11 @@ public class RecentsAnimationController implements DeathRecipient {
"cleanupAnimation(): Notify animation finished mPendingAnimations=%d "
+ "reorderMode=%d",
mPendingAnimations.size(), reorderMode);
+ if (reorderMode != REORDER_MOVE_TO_ORIGINAL_POSITION) {
+ // Notify the state at the beginning because the removeAnimation may notify the
+ // transition is finished. This is a signal that there will be a next transition.
+ mDisplayContent.mFixedRotationTransitionListener.notifyRecentsWillBeTop();
+ }
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
@@ -742,8 +747,7 @@ public class RecentsAnimationController implements DeathRecipient {
mTargetActivityRecord.token);
}
}
- mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(
- reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION /* moveRecentsToBack */);
+ mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation();
// Notify that the animation has ended
if (mStatusBar != null) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 06dec7c8023d..ac96d144c4d0 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2155,6 +2155,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// non-fullscreen bounds. Then when this new PIP task exits PIP, it can restore
// to its previous freeform bounds.
stack.setLastNonFullscreenBounds(task.mLastNonFullscreenBounds);
+ stack.setBounds(task.getBounds());
// There are multiple activities in the task and moving the top activity should
// reveal/leave the other activities in their original task.
@@ -2751,7 +2752,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
if (r.app != app) return;
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
- r.app = null;
+ r.detachFromProcess();
r.getDisplay().mDisplayContent.prepareAppTransition(
TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
r.destroyIfPossible("handleAppCrashed");
@@ -3104,22 +3105,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
return null;
}
- boolean handleAppDied(WindowProcessController app) {
- if (app.isRemoved()) {
- // The package of the died process should be force-stopped, so make its activities as
- // finishing to prevent the process from being started again if the next top (or being
- // visible) activity also resides in the same process.
- app.makeFinishingForProcessRemoved();
- }
- return reduceOnAllTaskDisplayAreas((taskDisplayArea, result) -> {
- for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
- final Task stack = taskDisplayArea.getStackAt(sNdx);
- result |= stack.handleAppDied(app);
- }
- return result;
- }, false /* initValue */);
- }
-
void closeSystemDialogActivities(String reason) {
forAllActivities((r) -> {
if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index da1e4269461a..f3620050bed2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -86,8 +86,6 @@ import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
@@ -115,8 +113,6 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIB
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG;
-import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
-import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
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;
@@ -129,7 +125,6 @@ import static com.android.server.wm.Task.ActivityState.STARTED;
import static com.android.server.wm.Task.ActivityState.STOPPED;
import static com.android.server.wm.Task.ActivityState.STOPPING;
import static com.android.server.wm.TaskProto.ACTIVITY_TYPE;
-import static com.android.server.wm.TaskProto.ANIMATING_BOUNDS;
import static com.android.server.wm.TaskProto.BOUNDS;
import static com.android.server.wm.TaskProto.CREATED_BY_ORGANIZER;
import static com.android.server.wm.TaskProto.DISPLAY_ID;
@@ -600,16 +595,6 @@ class Task extends WindowContainer<WindowContainer> {
SurfaceControl.Transaction mMainWindowSizeChangeTransaction;
Task mMainWindowSizeChangeTask;
- // If this is true, we are in the bounds animating mode. The task will be down or upscaled to
- // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
- // would otherwise apply while resizing, while resizing in the bounds animating mode.
- private boolean mBoundsAnimating = false;
- // Set when an animation has been requested but has not yet started from the UI thread. This is
- // cleared when the animation actually starts.
- private boolean mBoundsAnimatingRequested = false;
- private Rect mBoundsAnimationTarget = new Rect();
- private Rect mBoundsAnimationSourceHintBounds = new Rect();
-
Rect mPreAnimationBounds = new Rect();
private final AnimatingActivityRegistry mAnimatingActivityRegistry =
@@ -757,111 +742,6 @@ class Task extends WindowContainer<WindowContainer> {
}
}
- // TODO: Can we just loop through WindowProcessController#mActivities instead of doing this?
- private final RemoveHistoryRecordsForApp mRemoveHistoryRecordsForApp =
- new RemoveHistoryRecordsForApp();
- private class RemoveHistoryRecordsForApp {
- private boolean mHasVisibleActivities;
- private boolean mIsProcessRemoved;
- private WindowProcessController mApp;
- private ArrayList<ActivityRecord> mToRemove = new ArrayList<>();
-
- boolean process(WindowProcessController app) {
- mToRemove.clear();
- mHasVisibleActivities = false;
- mApp = app;
- mIsProcessRemoved = app.isRemoved();
-
- final PooledConsumer c = PooledLambda.obtainConsumer(
- RemoveHistoryRecordsForApp::addActivityToRemove, this,
- PooledLambda.__(ActivityRecord.class));
- forAllActivities(c);
- c.recycle();
-
- while (!mToRemove.isEmpty()) {
- processActivity(mToRemove.remove(0));
- }
-
- mApp = null;
- return mHasVisibleActivities;
- }
-
- private void addActivityToRemove(ActivityRecord r) {
- if (r.app == mApp) {
- mToRemove.add(r);
- }
- }
-
- private void processActivity(ActivityRecord r) {
- if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record " + r + ": app=" + r.app);
-
- if (r.app != mApp) {
- return;
- }
- if (r.isVisible() || r.mVisibleRequested) {
- // While an activity launches a new activity, it's possible that the old
- // activity is already requested to be hidden (mVisibleRequested=false), but
- // this visibility is not yet committed, so isVisible()=true.
- mHasVisibleActivities = true;
- }
- final boolean remove;
- if ((r.mRelaunchReason == RELAUNCH_REASON_WINDOWING_MODE_RESIZE
- || r.mRelaunchReason == RELAUNCH_REASON_FREE_RESIZE)
- && r.launchCount < 3 && !r.finishing) {
- // If the process crashed during a resize, always try to relaunch it, unless
- // it has failed more than twice. Skip activities that's already finishing
- // cleanly by itself.
- remove = false;
- } else if ((!r.hasSavedState() && !r.stateNotNeeded
- && !r.isState(ActivityState.RESTARTING_PROCESS)) || r.finishing) {
- // Don't currently have state for the activity, or
- // it is finishing -- always remove it.
- remove = true;
- } else if (!r.mVisibleRequested && r.launchCount > 2
- && r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) {
- // We have launched this activity too many times since it was
- // able to run, so give up and remove it.
- // (Note if the activity is visible, we don't remove the record.
- // We leave the dead window on the screen but the process will
- // not be restarted unless user explicitly tap on it.)
- remove = true;
- } else {
- // The process may be gone, but the activity lives on!
- remove = false;
- }
- if (remove) {
- if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE,
- "Removing activity " + r + " from stack "
- + ": hasSavedState=" + r.hasSavedState()
- + " stateNotNeeded=" + r.stateNotNeeded
- + " finishing=" + r.finishing
- + " state=" + r.getState() + " callers=" + Debug.getCallers(5));
- if (!r.finishing || mIsProcessRemoved) {
- Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
- EventLogTags.writeWmFinishActivity(r.mUserId,
- System.identityHashCode(r), r.getTask().mTaskId,
- r.shortComponentName, "proc died without state saved");
- }
- } else {
- // We have the current state for this activity, so
- // it can be restarted later when needed.
- if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null");
- if (DEBUG_APP) Slog.v(TAG_APP,
- "Clearing app during removeHistory for activity " + r);
- r.app = null;
- // Set nowVisible to previous visible state. If the app was visible while
- // it died, we leave the dead window on screen so it's basically visible.
- // This is needed when user later tap on the dead window, we need to stop
- // other apps when user transfers focus to the restarted activity.
- r.nowVisible = r.mVisibleRequested;
- }
- r.cleanUp(true /* cleanServices */, true /* setState */);
- if (remove) {
- r.removeFromHistory("appDied");
- }
- }
- }
-
private final FindRootHelper mFindRootHelper = new FindRootHelper();
private class FindRootHelper {
private ActivityRecord mRoot;
@@ -3741,17 +3621,6 @@ class Task extends WindowContainer<WindowContainer> {
}
@Override
- public SurfaceControl getAnimationLeashParent() {
- if (WindowManagerService.sHierarchicalAnimations) {
- return super.getAnimationLeashParent();
- }
- // Currently, only the recents animation will create animation leashes for tasks. In this
- // case, reparent the task to the home animation layer while it is being animated to allow
- // the home activity to reorder the app windows relative to its own.
- return getAppAnimationLayer(ANIMATION_LAYER_HOME);
- }
-
- @Override
void resetSurfacePositionForAnimationLeash(SurfaceControl.Transaction t) {
if (isOrganized()) return;
super.resetSurfacePositionForAnimationLeash(t);
@@ -7132,14 +7001,6 @@ class Task extends WindowContainer<WindowContainer> {
forAllTasks(c, true /* traverseTopToBottom */);
c.recycle();
- if (mBoundsAnimating) {
- // Force to update task surface bounds and relayout windows, since configBounds
- // remains unchanged during bounds animation.
- updateSurfaceBounds();
- getDisplay().setLayoutNeeded();
- mWmService.requestTraversal();
- }
-
if (!deferResume) {
ensureVisibleActivitiesConfiguration(topRunningActivity(), preserveWindows);
}
@@ -7197,9 +7058,8 @@ class Task extends WindowContainer<WindowContainer> {
/**
* Reset local parameters because an app's activity died.
* @param app The app of the activity that died.
- * @return result from removeHistoryRecordsForAppLocked.
*/
- boolean handleAppDied(WindowProcessController app) {
+ void handleAppDied(WindowProcessController app) {
if (mPausingActivity != null && mPausingActivity.app == app) {
if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE,
"App died while pausing: " + mPausingActivity);
@@ -7209,9 +7069,6 @@ class Task extends WindowContainer<WindowContainer> {
mLastPausedActivity = null;
mLastNoHistoryActivity = null;
}
-
- mStackSupervisor.removeHistoryRecords(app);
- return mRemoveHistoryRecordsForApp.process(app);
}
boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
@@ -7541,20 +7398,6 @@ class Task extends WindowContainer<WindowContainer> {
}
/**
- * @return the final bounds for the bounds animation.
- */
- void getFinalAnimationBounds(Rect outBounds) {
- outBounds.set(mBoundsAnimationTarget);
- }
-
- /**
- * @return the final source bounds for the bounds animation.
- */
- void getFinalAnimationSourceHintBounds(Rect outBounds) {
- outBounds.set(mBoundsAnimationSourceHintBounds);
- }
-
- /**
* Put a Task in this stack. Used for adding only.
* When task is added to top of the stack, the entire branch of the hierarchy (including stack
* and display) will be brought to top.
@@ -7709,10 +7552,6 @@ class Task extends WindowContainer<WindowContainer> {
getDisplayContent().getPinnedStackController().setActions(actions);
}
- public boolean isForceScaled() {
- return mBoundsAnimating;
- }
-
/** Returns true if a removal action is still being deferred. */
boolean handleCompleteDeferredRemoval() {
if (isAnimating(TRANSITION | CHILDREN)) {
@@ -7799,8 +7638,6 @@ class Task extends WindowContainer<WindowContainer> {
mLastNonFullscreenBounds.dumpDebug(proto, LAST_NON_FULLSCREEN_BOUNDS);
}
- proto.write(ANIMATING_BOUNDS, mBoundsAnimating);
-
if (mSurfaceControl != null) {
proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 246753ad2bde..a847744247c7 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -1294,7 +1294,13 @@ final class TaskDisplayArea extends DisplayArea<Task> {
}
void onSplitScreenModeDismissed() {
- onSplitScreenModeDismissed(null /* toTop */);
+ // The focused task could be a non-resizeable fullscreen root task that is on top of the
+ // other split-screen tasks, therefore had to dismiss split-screen, make sure the current
+ // focused root task can still be on top after dismissal
+ final Task rootTask = getFocusedStack();
+ final Task toTop =
+ rootTask != null && !rootTask.inSplitScreenWindowingMode() ? rootTask : null;
+ onSplitScreenModeDismissed(toTop);
}
void onSplitScreenModeDismissed(Task toTop) {
@@ -1838,6 +1844,10 @@ final class TaskDisplayArea extends DisplayArea<Task> {
return lastReparentedStack;
}
+ @Override
+ protected boolean isTaskDisplayArea() {
+ return true;
+ }
@Override
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 9d0bac9dd290..6377a2169b34 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -68,7 +68,6 @@ public class WindowAnimator {
Object mLastWindowFreezeSource;
SparseArray<DisplayContentsAnimator> mDisplayContentsAnimators = new SparseArray<>(2);
-
private boolean mInitialized = false;
// When set to true the animator will go over all windows after an animation frame is posted and
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index f37fe3a74f15..e24d185557e8 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -51,7 +51,6 @@ 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;
import static com.android.server.wm.WindowManagerService.logWithStack;
-import static com.android.server.wm.WindowManagerService.sHierarchicalAnimations;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import android.annotation.CallSuper;
@@ -858,6 +857,14 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
/**
+ * @return {@code true} when an application can override an app transition animation on this
+ * container.
+ */
+ boolean canCustomizeAppTransition() {
+ return !WindowManagerService.sDisableCustomTaskAnimationProperty;
+ }
+
+ /**
* @return {@code true} when this container or its related containers are running an
* animation, {@code false} otherwise.
*
@@ -2366,10 +2373,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
final Rect screenBounds = getAnimationBounds(appStackClipMode);
mTmpRect.set(screenBounds);
getAnimationPosition(mTmpPoint);
- if (!sHierarchicalAnimations) {
- // Non-hierarchical animation uses position in global coordinates.
- mTmpPoint.set(mTmpRect.left, mTmpRect.top);
- }
mTmpRect.offsetTo(0, 0);
final RemoteAnimationController controller =
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 2dd25c969d0d..ede92f0cad41 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -396,23 +396,22 @@ public class WindowManagerService extends IWindowManager.Stub
private static final boolean ALWAYS_KEEP_CURRENT = true;
/**
- * If set, new app transition framework which supports setting animation on any element
- * in a surface is used.
- * <p>
- * Only set this to non-zero once the new app transition framework is productionalized.
- * </p>
+ * Restrict ability of activities overriding transition animation in a way such that
+ * an activity can do it only when the transition happens within a same task.
+ *
+ * @see android.app.Activity#overridePendingTransition(int, int)
*/
- private static final String HIERARCHICAL_ANIMATIONS_PROPERTY =
- "persist.wm.hierarchical_animations";
-
- private static final String DISABLE_TRIPLE_BUFFERING_PROPERTY =
- "ro.sf.disable_triple_buffer";
+ private static final String DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY =
+ "persist.wm.disable_custom_task_animation";
/**
- * @see #HIERARCHICAL_ANIMATIONS_PROPERTY
+ * @see #DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY
*/
- static boolean sHierarchicalAnimations =
- SystemProperties.getBoolean(HIERARCHICAL_ANIMATIONS_PROPERTY, true);
+ static boolean sDisableCustomTaskAnimationProperty =
+ SystemProperties.getBoolean(DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY, false);
+
+ private static final String DISABLE_TRIPLE_BUFFERING_PROPERTY =
+ "ro.sf.disable_triple_buffer";
static boolean sEnableTripleBuffering = !SystemProperties.getBoolean(
DISABLE_TRIPLE_BUFFERING_PROPERTY, false);
@@ -2931,8 +2930,8 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized (mGlobalLock) {
final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
if (displayContent != null && mRoot.getTopChild() != displayContent) {
- displayContent.positionDisplayAt(WindowContainer.POSITION_TOP,
- true /* includingParents */);
+ displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP,
+ displayContent, true /* includingParents */);
}
}
syncInputTransactions();
@@ -8017,7 +8016,7 @@ public class WindowManagerService extends IWindowManager.Stub
final DisplayContent displayContent = touchedWindow.getDisplayContent();
if (!displayContent.isOnTop()) {
- displayContent.positionDisplayAt(WindowContainer.POSITION_TOP,
+ displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP, displayContent,
true /* includingParents */);
}
handleTaskFocusChange(touchedWindow.getTask());
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 6ba8769842f6..df59c56f5aff 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -177,8 +177,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
// Whether this process has ever started a service with the BIND_INPUT_METHOD permission.
private volatile boolean mHasImeService;
- // all activities running in the process
+ /** All activities running in the process (exclude destroying). */
private final ArrayList<ActivityRecord> mActivities = new ArrayList<>();
+ /** The activities will be removed but still belong to this process. */
+ private ArrayList<ActivityRecord> mInactiveActivities;
// any tasks this process had run root activities in
private final ArrayList<Task> mRecentTasks = new ArrayList<>();
// The most recent top-most activity that was resumed in the process for pre-Q app.
@@ -635,21 +637,39 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
return;
}
mActivities.add(r);
+ if (mInactiveActivities != null) {
+ mInactiveActivities.remove(r);
+ }
updateActivityConfigurationListener();
}
- void removeActivity(ActivityRecord r) {
+ /**
+ * Indicates that the given activity is no longer active in this process.
+ *
+ * @param r The running activity to be removed.
+ * @param keepAssociation {@code true} if the activity still belongs to this process but will
+ * be removed soon, e.g. destroying. From the perspective of process
+ * priority, the process is not important if it only contains activities
+ * that are being destroyed. But the association is still needed to
+ * ensure all activities are reachable from this process.
+ */
+ void removeActivity(ActivityRecord r, boolean keepAssociation) {
+ if (keepAssociation) {
+ if (mInactiveActivities == null) {
+ mInactiveActivities = new ArrayList<>();
+ mInactiveActivities.add(r);
+ } else if (!mInactiveActivities.contains(r)) {
+ mInactiveActivities.add(r);
+ }
+ } else if (mInactiveActivities != null) {
+ mInactiveActivities.remove(r);
+ }
mActivities.remove(r);
updateActivityConfigurationListener();
}
- void makeFinishingForProcessRemoved() {
- for (int i = mActivities.size() - 1; i >= 0; --i) {
- mActivities.get(i).makeFinishingLocked();
- }
- }
-
void clearActivities() {
+ mInactiveActivities = null;
mActivities.clear();
updateActivityConfigurationListener();
}
@@ -1142,6 +1162,47 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mAtm.mH.sendMessage(m);
}
+ /**
+ * Clean up the activities belonging to this process.
+ *
+ * @return {@code true} if the process has any visible activity.
+ */
+ boolean handleAppDied() {
+ mAtm.mStackSupervisor.removeHistoryRecords(this);
+
+ final boolean isRemoved = isRemoved();
+ boolean hasVisibleActivities = false;
+ if (mInactiveActivities != null && !mInactiveActivities.isEmpty()) {
+ // Make sure that all activities in this process are handled.
+ mActivities.addAll(mInactiveActivities);
+ }
+ for (int i = mActivities.size() - 1; i >= 0; i--) {
+ final ActivityRecord r = mActivities.get(i);
+ if (r.mVisibleRequested || r.isVisible()) {
+ // While an activity launches a new activity, it's possible that the old activity
+ // is already requested to be hidden (mVisibleRequested=false), but this visibility
+ // is not yet committed, so isVisible()=true.
+ hasVisibleActivities = true;
+ }
+ if (isRemoved) {
+ // The package of the died process should be force-stopped, so make its activities
+ // as finishing to prevent the process from being started again if the next top (or
+ // being visible) activity also resides in the same process.
+ r.makeFinishingLocked();
+ }
+
+ final Task rootTask = r.getRootTask();
+ if (rootTask != null) {
+ rootTask.handleAppDied(this);
+ }
+ r.handleAppDied();
+ }
+ clearRecentTasks();
+ clearActivities();
+
+ return hasVisibleActivities;
+ }
+
void registerDisplayConfigurationListener(DisplayContent displayContent) {
if (displayContent == null) {
return;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 77fee851889e..d0101adaabad 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -208,16 +208,6 @@ class WindowStateAnimator {
int mAttrType;
- boolean mForceScaleUntilResize;
-
- // WindowState.mHScale and WindowState.mVScale contain the
- // scale according to client specified layout parameters (e.g.
- // one layout size, with another surface size, creates such scaling).
- // Here we track an additional scaling factor used to follow stack
- // scaling (as in the case of the Pinned stack animation).
- float mExtraHScale = (float) 1.0;
- float mExtraVScale = (float) 1.0;
-
// An offset in pixel of the surface contents from the window position. Used for Wallpaper
// to provide the effect of scrolling within a large surface. We just use these values as
// a cache.
@@ -247,11 +237,6 @@ class WindowStateAnimator {
private final SurfaceControl.Transaction mPostDrawTransaction =
new SurfaceControl.Transaction();
- // Set to true after the first frame of the Pinned stack animation
- // and reset after the last to ensure we only reset mForceScaleUntilResize
- // once per animation.
- boolean mPipAnimationStarted = false;
-
private final Point mTmpPos = new Point();
WindowStateAnimator(final WindowState win) {
@@ -870,11 +855,6 @@ class WindowStateAnimator {
calculateSurfaceBounds(w, attrs, mTmpSize);
- mExtraHScale = (float) 1.0;
- mExtraVScale = (float) 1.0;
-
- boolean wasForceScaled = mForceScaleUntilResize;
-
// Once relayout has been called at least once, we need to make sure
// we only resize the client surface during calls to relayout. For
// clients which use indeterminate measure specs (MATCH_PARENT),
@@ -889,7 +869,6 @@ class WindowStateAnimator {
} else {
mSurfaceResized = false;
}
- mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;
// If we are undergoing seamless rotation, the surface has already
// been set up to persist at it's old location. We need to freeze
// updates until a resize occurs.
@@ -913,184 +892,54 @@ class WindowStateAnimator {
final Rect insets = attrs.surfaceInsets;
- if (isForceScaled()) {
- int hInsets = insets.left + insets.right;
- int vInsets = insets.top + insets.bottom;
- float surfaceContentWidth = surfaceWidth - hInsets;
- float surfaceContentHeight = surfaceHeight - vInsets;
- if (!mForceScaleUntilResize) {
- mSurfaceController.forceScaleableInTransaction(true);
- }
-
- int posX = 0;
- int posY = 0;
- task.getRootTask().getDimBounds(mTmpStackBounds);
-
- boolean allowStretching = false;
- task.getRootTask().getFinalAnimationSourceHintBounds(mTmpSourceBounds);
- // If we don't have source bounds, we can attempt to use the content insets
- // if we have content insets.
- if (mTmpSourceBounds.isEmpty() && (mWin.mLastRelayoutContentInsets.width() > 0
- || mWin.mLastRelayoutContentInsets.height() > 0)) {
- mTmpSourceBounds.set(task.getRootTask().mPreAnimationBounds);
- mTmpSourceBounds.inset(mWin.mLastRelayoutContentInsets);
- allowStretching = true;
- }
-
- // Make sure that what we're animating to and from is actually the right size in case
- // the window cannot take up the full screen.
- mTmpStackBounds.intersectUnchecked(w.getParentFrame());
- mTmpSourceBounds.intersectUnchecked(w.getParentFrame());
- mTmpAnimatingBounds.intersectUnchecked(w.getParentFrame());
-
- if (!mTmpSourceBounds.isEmpty()) {
- // Get the final target stack bounds, if we are not animating, this is just the
- // current stack bounds
- task.getRootTask().getFinalAnimationBounds(mTmpAnimatingBounds);
-
- // Calculate the current progress and interpolate the difference between the target
- // and source bounds
- float finalWidth = mTmpAnimatingBounds.width();
- float initialWidth = mTmpSourceBounds.width();
- float tw = (surfaceContentWidth - mTmpStackBounds.width())
- / (surfaceContentWidth - mTmpAnimatingBounds.width());
- float th = tw;
- mExtraHScale = (initialWidth + tw * (finalWidth - initialWidth)) / initialWidth;
- if (allowStretching) {
- float finalHeight = mTmpAnimatingBounds.height();
- float initialHeight = mTmpSourceBounds.height();
- th = (surfaceContentHeight - mTmpStackBounds.height())
- / (surfaceContentHeight - mTmpAnimatingBounds.height());
- mExtraVScale = (initialHeight + tw * (finalHeight - initialHeight))
- / initialHeight;
+ if (!w.mSeamlesslyRotated) {
+ // Used to offset the WSA when stack position changes before a resize.
+ int xOffset = mXOffset;
+ int yOffset = mYOffset;
+ if (mOffsetPositionForStackResize) {
+ if (relayout) {
+ // Once a relayout is called, reset the offset back to 0 and defer
+ // setting it until a new frame with the updated size. This ensures that
+ // the WS position is reset (so the stack position is shown) at the same
+ // time that the buffer size changes.
+ setOffsetPositionForStackResize(false);
+ mSurfaceController.deferTransactionUntil(mWin.getClientViewRootSurface(),
+ mWin.getFrameNumber());
} else {
- mExtraVScale = mExtraHScale;
- }
-
- // Adjust the position to account for the inset bounds
- posX -= (int) (tw * mExtraHScale * mTmpSourceBounds.left);
- posY -= (int) (th * mExtraVScale * mTmpSourceBounds.top);
-
- // In pinned mode the clip rectangle applied to us by our stack has been
- // expanded outwards to allow for shadows. However in case of source bounds set
- // we need to crop to within the surface. The code above has scaled and positioned
- // the surface to fit the unexpanded stack bounds, but now we need to reapply
- // the cropping that the stack would have applied if it weren't expanded. This
- // can be different in each direction based on the source bounds.
- clipRect = mTmpClipRect;
- clipRect.set((int)((insets.left + mTmpSourceBounds.left) * tw),
- (int)((insets.top + mTmpSourceBounds.top) * th),
- insets.left + (int)(surfaceWidth
- - (tw* (surfaceWidth - mTmpSourceBounds.right))),
- insets.top + (int)(surfaceHeight
- - (th * (surfaceHeight - mTmpSourceBounds.bottom))));
- } else {
- // We want to calculate the scaling based on the content area, not based on
- // the entire surface, so that we scale in sync with windows that don't have insets.
- mExtraHScale = mTmpStackBounds.width() / surfaceContentWidth;
- mExtraVScale = mTmpStackBounds.height() / surfaceContentHeight;
-
- // Since we are scaled to fit in our previously desired crop, we can now
- // expose the whole window in buffer space, and not risk extending
- // past where the system would have cropped us
- clipRect = null;
- }
-
- // In the case of ForceScaleToStack we scale entire tasks together,
- // and so we need to scale our offsets relative to the task bounds
- // or parent and child windows would fall out of alignment.
- posX -= (int) (attrs.x * (1 - mExtraHScale));
- posY -= (int) (attrs.y * (1 - mExtraVScale));
-
- // Imagine we are scaling down. As we scale the buffer down, we decrease the
- // distance between the surface top left, and the start of the surface contents
- // (previously it was surfaceInsets.left pixels in screen space but now it
- // will be surfaceInsets.left*mExtraHScale). This means in order to keep the
- // non inset content at the same position, we have to shift the whole window
- // forward. Likewise for scaling up, we've increased this distance, and we need
- // to shift by a negative number to compensate.
- posX += insets.left * (1 - mExtraHScale);
- posY += insets.top * (1 - mExtraVScale);
-
- mSurfaceController.setPositionInTransaction((float) Math.floor(posX),
- (float) Math.floor(posY), recoveringMemory);
-
- // Various surfaces in the scaled stack may resize at different times.
- // We need to ensure for each surface, that we disable transformation matrix
- // scaling in the same transaction which we resize the surface in.
- // As we are in SCALING_MODE_SCALE_TO_WINDOW, SurfaceFlinger will
- // then take over the scaling until the new buffer arrives, and things
- // will be seamless.
- if (mPipAnimationStarted == false) {
- mForceScaleUntilResize = true;
- mPipAnimationStarted = true;
- }
- } else {
- mPipAnimationStarted = false;
-
- if (!w.mSeamlesslyRotated) {
- // Used to offset the WSA when stack position changes before a resize.
- int xOffset = mXOffset;
- int yOffset = mYOffset;
- if (mOffsetPositionForStackResize) {
- if (relayout) {
- // Once a relayout is called, reset the offset back to 0 and defer
- // setting it until a new frame with the updated size. This ensures that
- // the WS position is reset (so the stack position is shown) at the same
- // time that the buffer size changes.
- setOffsetPositionForStackResize(false);
- mSurfaceController.deferTransactionUntil(mWin.getClientViewRootSurface(),
- mWin.getFrameNumber());
- } else {
- final Task stack = mWin.getRootTask();
- mTmpPos.x = 0;
- mTmpPos.y = 0;
- if (stack != null) {
- stack.getRelativePosition(mTmpPos);
- }
-
- xOffset = -mTmpPos.x;
- yOffset = -mTmpPos.y;
-
- // Crop also needs to be extended so the bottom isn't cut off when the WSA
- // position is moved.
- if (clipRect != null) {
- clipRect.right += mTmpPos.x;
- clipRect.bottom += mTmpPos.y;
- }
+ final Task stack = mWin.getRootTask();
+ mTmpPos.x = 0;
+ mTmpPos.y = 0;
+ if (stack != null) {
+ stack.getRelativePosition(mTmpPos);
+ }
+ xOffset = -mTmpPos.x;
+ yOffset = -mTmpPos.y;
+ // Crop also needs to be extended so the bottom isn't cut off when the WSA
+ // position is moved.
+ if (clipRect != null) {
+ clipRect.right += mTmpPos.x;
+ clipRect.bottom += mTmpPos.y;
}
- }
- if (!mIsWallpaper) {
- mSurfaceController.setPositionInTransaction(xOffset, yOffset, recoveringMemory);
- } else {
- setWallpaperPositionAndScale(
- xOffset, yOffset, mWallpaperScale, recoveringMemory);
}
}
+ if (!mIsWallpaper) {
+ mSurfaceController.setPositionInTransaction(xOffset, yOffset, recoveringMemory);
+ } else {
+ setWallpaperPositionAndScale(
+ xOffset, yOffset, mWallpaperScale, recoveringMemory);
+ }
}
- // If we are ending the scaling mode. We switch to SCALING_MODE_FREEZE
- // to prevent further updates until buffer latch.
- // We also need to freeze the Surface geometry until a buffer
- // comes in at the new size (normally position and crop are unfrozen).
- // deferTransactionUntil accomplishes this for us.
- if (wasForceScaled && !mForceScaleUntilResize) {
- mSurfaceController.deferTransactionUntil(mWin.getClientViewRootSurface(),
- mWin.getFrameNumber());
- mSurfaceController.forceScaleableInTransaction(false);
- }
-
-
if (!w.mSeamlesslyRotated) {
// Wallpaper is already updated above when calling setWallpaperPositionAndScale so
// we only need to consider the non-wallpaper case here.
if (!mIsWallpaper) {
applyCrop(clipRect, recoveringMemory);
mSurfaceController.setMatrixInTransaction(
- mDsDx * w.mHScale * mExtraHScale,
- mDtDx * w.mVScale * mExtraVScale,
- mDtDy * w.mHScale * mExtraHScale,
- mDsDy * w.mVScale * mExtraVScale, recoveringMemory);
+ mDsDx * w.mHScale,
+ mDtDx * w.mVScale,
+ mDtDy * w.mHScale,
+ mDsDy * w.mVScale, recoveringMemory);
}
}
@@ -1177,10 +1026,10 @@ class WindowStateAnimator {
} else {
prepared =
mSurfaceController.prepareToShowInTransaction(mShownAlpha,
- mDsDx * w.mHScale * mExtraHScale,
- mDtDx * w.mVScale * mExtraVScale,
- mDtDy * w.mHScale * mExtraHScale,
- mDsDy * w.mVScale * mExtraVScale,
+ mDsDx * w.mHScale,
+ mDtDx * w.mVScale,
+ mDtDy * w.mHScale,
+ mDsDy * w.mVScale,
recoveringMemory);
}
@@ -1287,10 +1136,10 @@ class WindowStateAnimator {
mSurfaceController.setPositionInTransaction(mWin.mTmpMatrixArray[MTRANS_X],
mWin.mTmpMatrixArray[MTRANS_Y], recoveringMemory);
mSurfaceController.setMatrixInTransaction(
- mDsDx * mWin.mTmpMatrixArray[MSCALE_X] * mWin.mHScale * mExtraHScale,
- mDtDx * mWin.mTmpMatrixArray[MSKEW_Y] * mWin.mVScale * mExtraVScale,
- mDtDy * mWin.mTmpMatrixArray[MSKEW_X] * mWin.mHScale * mExtraHScale,
- mDsDy * mWin.mTmpMatrixArray[MSCALE_Y] * mWin.mVScale * mExtraVScale,
+ mDsDx * mWin.mTmpMatrixArray[MSCALE_X] * mWin.mHScale,
+ mDtDx * mWin.mTmpMatrixArray[MSKEW_Y] * mWin.mVScale,
+ mDtDy * mWin.mTmpMatrixArray[MSKEW_X] * mWin.mHScale,
+ mDsDy * mWin.mTmpMatrixArray[MSCALE_Y] * mWin.mVScale,
recoveringMemory);
applyCrop(null, recoveringMemory);
}
@@ -1570,18 +1419,6 @@ class WindowStateAnimator {
}
}
- /** The force-scaled state for a given window can persist past
- * the state for it's stack as the windows complete resizing
- * independently of one another.
- */
- boolean isForceScaled() {
- final Task task = mWin.getTask();
- if (task != null && task.getRootTask().isForceScaled()) {
- return true;
- }
- return mForceScaleUntilResize;
- }
-
void detachChildren() {
// Do not detach children of starting windows, as their lifecycle is well under control and
diff --git a/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp b/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp
index 503f0cf993d4..3dfce3aec059 100644
--- a/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp
+++ b/services/core/jni/com_android_server_fingerprint_FingerprintService.cpp
@@ -235,7 +235,7 @@ static jint nativeOpenHal(JNIEnv* env, jobject clazz) {
return 0;
}
- // Sanity check - remove
+ // Soundness check - remove
if (gContext.device->notify != hal_notify_callback) {
ALOGE("NOTIFY not set properly: %p != %p", gContext.device->notify, hal_notify_callback);
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 10523a2adbb2..784366318319 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -239,9 +239,9 @@ public:
void notifySwitch(nsecs_t when, uint32_t switchValues, uint32_t switchMask,
uint32_t policyFlags) override;
void notifyConfigurationChanged(nsecs_t when) override;
- std::chrono::nanoseconds notifyAnr(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<IBinder>& token,
- const std::string& reason) override;
+ std::chrono::nanoseconds notifyAnr(
+ const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
+ const sp<IBinder>& token, const std::string& reason) override;
void notifyInputChannelBroken(const sp<IBinder>& token) override;
void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) override;
bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override;
@@ -682,8 +682,8 @@ void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
}
-static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
- const sp<InputApplicationHandle>& inputApplicationHandle) {
+static jobject getInputApplicationHandleObjLocalRef(
+ JNIEnv* env, const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle) {
if (inputApplicationHandle == nullptr) {
return nullptr;
}
@@ -694,8 +694,8 @@ static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
}
std::chrono::nanoseconds NativeInputManager::notifyAnr(
- const sp<InputApplicationHandle>& inputApplicationHandle, const sp<IBinder>& token,
- const std::string& reason) {
+ const std::shared_ptr<InputApplicationHandle>& inputApplicationHandle,
+ const sp<IBinder>& token, const std::string& reason) {
#if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyANR");
#endif
@@ -780,8 +780,12 @@ void NativeInputManager::displayRemoved(JNIEnv* env, int32_t displayId) {
void NativeInputManager::setFocusedApplication(JNIEnv* env, int32_t displayId,
jobject applicationHandleObj) {
- sp<InputApplicationHandle> applicationHandle =
+ if (!applicationHandleObj) {
+ return;
+ }
+ std::shared_ptr<InputApplicationHandle> applicationHandle =
android_view_InputApplicationHandle_getHandle(env, applicationHandleObj);
+ applicationHandle->updateInfo();
mInputManager->getDispatcher()->setFocusedApplication(displayId, applicationHandle);
}
diff --git a/services/core/jni/stats/PowerStatsPuller.cpp b/services/core/jni/stats/PowerStatsPuller.cpp
index d8f6faac0ffb..7f788c226c7b 100644
--- a/services/core/jni/stats/PowerStatsPuller.cpp
+++ b/services/core/jni/stats/PowerStatsPuller.cpp
@@ -135,16 +135,11 @@ AStatsManager_PullAtomCallbackReturn PowerStatsPuller::Pull(int32_t atomTag,
}
const RailInfo& rail = gRailInfo[energyData.index];
- AStatsEvent* event =
- AStatsEventList_addStatsEvent(data);
- AStatsEvent_setAtomId(
- event,
- android::util::ON_DEVICE_POWER_MEASUREMENT);
- AStatsEvent_writeString(event, rail.subsysName.c_str());
- AStatsEvent_writeString(event, rail.railName.c_str());
- AStatsEvent_writeInt64(event, energyData.timestamp);
- AStatsEvent_writeInt64(event, energyData.energy);
- AStatsEvent_build(event);
+ android::util::addAStatsEvent(
+ data,
+ android::util::ON_DEVICE_POWER_MEASUREMENT,
+ rail.subsysName.c_str(), rail.railName.c_str(),
+ energyData.timestamp, energyData.energy);
ALOGV("power.stat: %s.%s: %llu, %llu",
rail.subsysName.c_str(), rail.railName.c_str(),
diff --git a/services/core/jni/stats/SubsystemSleepStatePuller.cpp b/services/core/jni/stats/SubsystemSleepStatePuller.cpp
index 45afb5eb7aa9..1ba98ef8dab7 100644
--- a/services/core/jni/stats/SubsystemSleepStatePuller.cpp
+++ b/services/core/jni/stats/SubsystemSleepStatePuller.cpp
@@ -194,17 +194,13 @@ static AStatsManager_PullAtomCallbackReturn getIPowerStatsDataLocked(int32_t ato
}
for (auto result : results) {
for (auto stateResidency : result.stateResidencyData) {
- AStatsEvent* event = AStatsEventList_addStatsEvent(data);
- AStatsEvent_setAtomId(event, android::util::SUBSYSTEM_SLEEP_STATE);
- AStatsEvent_writeString(event,
- gEntityNames.at(result.powerEntityId).c_str());
- AStatsEvent_writeString(event,
- gStateNames.at(result.powerEntityId)
- .at(stateResidency.powerEntityStateId)
- .c_str());
- AStatsEvent_writeInt64(event, stateResidency.totalStateEntryCount);
- AStatsEvent_writeInt64(event, stateResidency.totalTimeInStateMs);
- AStatsEvent_build(event);
+ android::util::addAStatsEvent(data, android::util::SUBSYSTEM_SLEEP_STATE,
+ gEntityNames.at(result.powerEntityId).c_str(),
+ gStateNames.at(result.powerEntityId)
+ .at(stateResidency.powerEntityStateId)
+ .c_str(),
+ stateResidency.totalStateEntryCount,
+ stateResidency.totalTimeInStateMs);
}
}
success = true;
@@ -259,26 +255,21 @@ static AStatsManager_PullAtomCallbackReturn getIPowerDataLocked(int32_t atomTag,
for (size_t i = 0; i < states.size(); i++) {
const PowerStatePlatformSleepState& state = states[i];
- AStatsEvent* event = AStatsEventList_addStatsEvent(data);
- AStatsEvent_setAtomId(event, android::util::SUBSYSTEM_SLEEP_STATE);
- AStatsEvent_writeString(event, state.name.c_str());
- AStatsEvent_writeString(event, "");
- AStatsEvent_writeInt64(event, state.totalTransitions);
- AStatsEvent_writeInt64(event, state.residencyInMsecSinceBoot);
- AStatsEvent_build(event);
+ android::util::addAStatsEvent(data, android::util::SUBSYSTEM_SLEEP_STATE,
+ state.name.c_str(), "",
+ state.totalTransitions,
+ state.residencyInMsecSinceBoot);
ALOGV("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
(long long)state.residencyInMsecSinceBoot,
(long long)state.totalTransitions,
state.supportedOnlyInSuspend ? 1 : 0);
for (const auto& voter : state.voters) {
- AStatsEvent* event = AStatsEventList_addStatsEvent(data);
- AStatsEvent_setAtomId(event, android::util::SUBSYSTEM_SLEEP_STATE);
- AStatsEvent_writeString(event, state.name.c_str());
- AStatsEvent_writeString(event, voter.name.c_str());
- AStatsEvent_writeInt64(event, voter.totalNumberOfTimesVotedSinceBoot);
- AStatsEvent_writeInt64(event, voter.totalTimeInMsecVotedForSinceBoot);
- AStatsEvent_build(event);
+ android::util::addAStatsEvent(data,
+ android::util::SUBSYSTEM_SLEEP_STATE,
+ state.name.c_str(), voter.name.c_str(),
+ voter.totalNumberOfTimesVotedSinceBoot,
+ voter.totalTimeInMsecVotedForSinceBoot);
ALOGV("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(),
voter.name.c_str(),
@@ -305,14 +296,13 @@ static AStatsManager_PullAtomCallbackReturn getIPowerDataLocked(int32_t atomTag,
for (size_t j = 0; j < subsystem.states.size(); j++) {
const PowerStateSubsystemSleepState& state =
subsystem.states[j];
- AStatsEvent* event = AStatsEventList_addStatsEvent(data);
- AStatsEvent_setAtomId(event,
- android::util::SUBSYSTEM_SLEEP_STATE);
- AStatsEvent_writeString(event, subsystem.name.c_str());
- AStatsEvent_writeString(event, state.name.c_str());
- AStatsEvent_writeInt64(event, state.totalTransitions);
- AStatsEvent_writeInt64(event, state.residencyInMsecSinceBoot);
- AStatsEvent_build(event);
+ android::util::
+ addAStatsEvent(data,
+ android::util::SUBSYSTEM_SLEEP_STATE,
+ subsystem.name.c_str(),
+ state.name.c_str(),
+ state.totalTransitions,
+ state.residencyInMsecSinceBoot);
ALOGV("subsystemstate: %s, %s, %lld, %lld, %lld",
subsystem.name.c_str(), state.name.c_str(),
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 7ec819f13e96..9a2bef85860f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -290,6 +290,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.inputmethod.InputMethodManagerInternal;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -775,18 +776,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public void onStartUser(int userHandle) {
- mService.handleStartUser(userHandle);
+ public void onUserStarting(@NonNull TargetUser user) {
+ mService.handleStartUser(user.getUserIdentifier());
}
@Override
- public void onUnlockUser(int userHandle) {
- mService.handleUnlockUser(userHandle);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mService.handleUnlockUser(user.getUserIdentifier());
}
@Override
- public void onStopUser(int userHandle) {
- mService.handleStopUser(userHandle);
+ public void onUserStopping(@NonNull TargetUser user) {
+ mService.handleStopUser(user.getUserIdentifier());
}
}
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 51478b365715..2cfdf3fd4f6f 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -16,6 +16,7 @@
package com.android.server.midi;
+import android.annotation.NonNull;
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.content.Context;
@@ -47,8 +48,8 @@ import android.util.Log;
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.XmlUtils;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import org.xmlpull.v1.XmlPullParser;
@@ -75,8 +76,8 @@ public class MidiService extends IMidiManager.Stub {
}
@Override
- public void onUnlockUser(int userHandle) {
- if (userHandle == UserHandle.USER_SYSTEM) {
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ if (user.getUserIdentifier() == UserHandle.USER_SYSTEM) {
mMidiService.onUnlockUser();
}
}
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index d064f7ee62c3..1cdcbd87c1f5 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -72,6 +72,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.dump.DualDumpOutputStream;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -101,13 +102,13 @@ public final class PrintManagerService extends SystemService {
}
@Override
- public void onUnlockUser(int userHandle) {
- mPrintManagerImpl.handleUserUnlocked(userHandle);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mPrintManagerImpl.handleUserUnlocked(user.getUserIdentifier());
}
@Override
- public void onStopUser(int userHandle) {
- mPrintManagerImpl.handleUserStopped(userHandle);
+ public void onUserStopping(@NonNull TargetUser user) {
+ mPrintManagerImpl.handleUserStopped(user.getUserIdentifier());
}
class PrintManagerImpl extends IPrintManager.Stub {
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
index 4a73efe25fdb..cd9b6aca72e0 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceRoboTest.java
@@ -38,7 +38,6 @@ import static org.testng.Assert.expectThrows;
import android.annotation.UserIdInt;
import android.app.Application;
-import android.app.backup.BackupManager;
import android.app.backup.BackupManager.OperationType;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IBackupObserver;
@@ -46,6 +45,7 @@ import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.ISelectBackupTransportCallback;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.UserInfo;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
@@ -54,6 +54,7 @@ import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
+import com.android.server.SystemService.TargetUser;
import com.android.server.backup.testing.TransportData;
import com.android.server.testing.shadows.ShadowApplicationPackageManager;
import com.android.server.testing.shadows.ShadowBinder;
@@ -1601,7 +1602,7 @@ public class BackupManagerServiceRoboTest {
BackupManagerService.Lifecycle lifecycle =
new BackupManagerService.Lifecycle(mContext, backupManagerService);
- lifecycle.onUnlockUser(UserHandle.USER_SYSTEM);
+ lifecycle.onUserUnlocking(new TargetUser(new UserInfo(UserHandle.USER_SYSTEM, null, 0)));
verify(backupManagerService).onUnlockUser(UserHandle.USER_SYSTEM);
}
@@ -1613,7 +1614,7 @@ public class BackupManagerServiceRoboTest {
BackupManagerService.Lifecycle lifecycle =
new BackupManagerService.Lifecycle(mContext, backupManagerService);
- lifecycle.onStopUser(UserHandle.USER_SYSTEM);
+ lifecycle.onUserStopping(new TargetUser(new UserInfo(UserHandle.USER_SYSTEM, null, 0)));
verify(backupManagerService).onStopUser(UserHandle.USER_SYSTEM);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
index 8ccaeddc8355..2f5e8839504b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
@@ -247,7 +247,7 @@ public class AppStateTrackerTest {
.thenAnswer(inv -> getPowerSaveState());
when(mMockAppOpsManager.getPackagesForOps(
any(int[].class)
- )).thenAnswer(mGetPackagesForOps);
+ )).thenAnswer(mGetPackagesForOps);
mMockContentResolver = new MockContentResolver();
when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
@@ -447,7 +447,7 @@ public class AppStateTrackerTest {
areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS);
areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
- // Clear the app ops and update the whitelist.
+ // Clear the app ops and update the exemption list.
setAppOps(UID_1, PACKAGE_1, false);
setAppOps(UID_10_2, PACKAGE_2, false);
@@ -462,7 +462,8 @@ public class AppStateTrackerTest {
areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS);
areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
- instance.setPowerSaveWhitelistAppIds(new int[] {UID_1}, new int[] {}, new int[] {UID_2});
+ instance.setPowerSaveExemptionListAppIds(new int[] {UID_1}, new int[] {},
+ new int[] {UID_2});
areRestricted(instance, UID_1, PACKAGE_1, NONE);
areRestricted(instance, UID_10_1, PACKAGE_1, NONE);
@@ -487,24 +488,25 @@ public class AppStateTrackerTest {
areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS);
areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE);
- assertTrue(instance.isUidPowerSaveWhitelisted(UID_1));
- assertTrue(instance.isUidPowerSaveWhitelisted(UID_10_1));
- assertFalse(instance.isUidPowerSaveWhitelisted(UID_2));
- assertFalse(instance.isUidPowerSaveWhitelisted(UID_10_2));
+ assertTrue(instance.isUidPowerSaveExempt(UID_1));
+ assertTrue(instance.isUidPowerSaveExempt(UID_10_1));
+ assertFalse(instance.isUidPowerSaveExempt(UID_2));
+ assertFalse(instance.isUidPowerSaveExempt(UID_10_2));
- assertFalse(instance.isUidTempPowerSaveWhitelisted(UID_1));
- assertFalse(instance.isUidTempPowerSaveWhitelisted(UID_10_1));
- assertTrue(instance.isUidTempPowerSaveWhitelisted(UID_2));
- assertTrue(instance.isUidTempPowerSaveWhitelisted(UID_10_2));
+ assertFalse(instance.isUidTempPowerSaveExempt(UID_1));
+ assertFalse(instance.isUidTempPowerSaveExempt(UID_10_1));
+ assertTrue(instance.isUidTempPowerSaveExempt(UID_2));
+ assertTrue(instance.isUidTempPowerSaveExempt(UID_10_2));
}
@Test
- public void testPowerSaveUserWhitelist() throws Exception {
+ public void testPowerSaveUserExemptionList() throws Exception {
final AppStateTrackerTestable instance = newInstance();
- instance.setPowerSaveWhitelistAppIds(new int[] {}, new int[] {UID_1, UID_2}, new int[] {});
- assertTrue(instance.isUidPowerSaveUserWhitelisted(UID_1));
- assertTrue(instance.isUidPowerSaveUserWhitelisted(UID_2));
- assertFalse(instance.isUidPowerSaveUserWhitelisted(UID_3));
+ instance.setPowerSaveExemptionListAppIds(new int[] {}, new int[] {UID_1, UID_2},
+ new int[] {});
+ assertTrue(instance.isUidPowerSaveUserExempt(UID_1));
+ assertTrue(instance.isUidPowerSaveUserExempt(UID_2));
+ assertFalse(instance.isUidPowerSaveUserExempt(UID_3));
}
@Test
@@ -909,9 +911,10 @@ public class AppStateTrackerTest {
reset(l);
// -------------------------------------------------------------------------
- // Tests with system/user/temp whitelist.
+ // Tests with system/user/temp exemption list.
- instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {}, new int[] {});
+ instance.setPowerSaveExemptionListAppIds(new int[] {UID_1, UID_2}, new int[] {},
+ new int[] {});
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
@@ -923,7 +926,7 @@ public class AppStateTrackerTest {
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
- instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {}, new int[] {});
+ instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {}, new int[] {});
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
@@ -935,8 +938,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
- // Update temp whitelist.
- instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {},
+ // Update temp exemption list.
+ instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {},
new int[] {UID_1, UID_3});
waitUntilMainHandlerDrain();
@@ -949,7 +952,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
- instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {}, new int[] {UID_3});
+ instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {},
+ new int[] {UID_3});
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
@@ -975,10 +979,11 @@ public class AppStateTrackerTest {
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
- instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {}, new int[] {});
+ instance.setPowerSaveExemptionListAppIds(new int[] {UID_1, UID_2}, new int[] {},
+ new int[] {});
waitUntilMainHandlerDrain();
- // Called once for updating all whitelist and once for updating temp whitelist
+ // Called once for updating all exemption list and once for updating temp exemption list
verify(l, times(2)).updateAllJobs();
verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean());
verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean());
@@ -988,7 +993,7 @@ public class AppStateTrackerTest {
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
- instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {}, new int[] {});
+ instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {}, new int[] {});
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
@@ -1000,8 +1005,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
- // Update temp whitelist.
- instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {},
+ // Update temp exemption list.
+ instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {},
new int[] {UID_1, UID_3});
waitUntilMainHandlerDrain();
@@ -1014,7 +1019,8 @@ public class AppStateTrackerTest {
verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
reset(l);
- instance.setPowerSaveWhitelistAppIds(new int[] {UID_2}, new int[] {}, new int[] {UID_3});
+ instance.setPowerSaveExemptionListAppIds(new int[] {UID_2}, new int[] {},
+ new int[] {UID_3});
waitUntilMainHandlerDrain();
verify(l, times(1)).updateAllJobs();
@@ -1254,7 +1260,7 @@ public class AppStateTrackerTest {
.mapToInt(Integer::intValue).toArray();
}
- static boolean isAnyAppIdUnwhitelistedSlow(int[] prevArray, int[] newArray) {
+ static boolean isAnyAppIdUnexemptSlow(int[] prevArray, int[] newArray) {
Arrays.sort(newArray); // Just in case...
for (int p : prevArray) {
if (Arrays.binarySearch(newArray, p) < 0) {
@@ -1264,31 +1270,31 @@ public class AppStateTrackerTest {
return false;
}
- private void checkAnyAppIdUnwhitelisted(int[] prevArray, int[] newArray, boolean expected) {
+ private void checkAnyAppIdUnexempt(int[] prevArray, int[] newArray, boolean expected) {
assertEquals("Input: " + Arrays.toString(prevArray) + " " + Arrays.toString(newArray),
- expected, AppStateTrackerImpl.isAnyAppIdUnwhitelisted(prevArray, newArray));
+ expected, AppStateTrackerImpl.isAnyAppIdUnexempt(prevArray, newArray));
- // Also test isAnyAppIdUnwhitelistedSlow.
+ // Also test isAnyAppIdUnexempt.
assertEquals("Input: " + Arrays.toString(prevArray) + " " + Arrays.toString(newArray),
- expected, isAnyAppIdUnwhitelistedSlow(prevArray, newArray));
+ expected, isAnyAppIdUnexemptSlow(prevArray, newArray));
}
@Test
- public void isAnyAppIdUnwhitelisted() {
- checkAnyAppIdUnwhitelisted(array(), array(), false);
-
- checkAnyAppIdUnwhitelisted(array(1), array(), true);
- checkAnyAppIdUnwhitelisted(array(1), array(1), false);
- checkAnyAppIdUnwhitelisted(array(1), array(0, 1), false);
- checkAnyAppIdUnwhitelisted(array(1), array(0, 1, 2), false);
- checkAnyAppIdUnwhitelisted(array(1), array(0, 1, 2), false);
-
- checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(), true);
- checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(1, 2), true);
- checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(1, 2, 10), false);
- checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(2, 10), true);
- checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(0, 1, 2, 4, 3, 10), false);
- checkAnyAppIdUnwhitelisted(array(1, 2, 10), array(0, 0, 1, 2, 10), false);
+ public void isAnyAppIdUnexempt() {
+ checkAnyAppIdUnexempt(array(), array(), false);
+
+ checkAnyAppIdUnexempt(array(1), array(), true);
+ checkAnyAppIdUnexempt(array(1), array(1), false);
+ checkAnyAppIdUnexempt(array(1), array(0, 1), false);
+ checkAnyAppIdUnexempt(array(1), array(0, 1, 2), false);
+ checkAnyAppIdUnexempt(array(1), array(0, 1, 2), false);
+
+ checkAnyAppIdUnexempt(array(1, 2, 10), array(), true);
+ checkAnyAppIdUnexempt(array(1, 2, 10), array(1, 2), true);
+ checkAnyAppIdUnexempt(array(1, 2, 10), array(1, 2, 10), false);
+ checkAnyAppIdUnexempt(array(1, 2, 10), array(2, 10), true);
+ checkAnyAppIdUnexempt(array(1, 2, 10), array(0, 1, 2, 4, 3, 10), false);
+ checkAnyAppIdUnexempt(array(1, 2, 10), array(0, 0, 1, 2, 10), false);
// Random test
int trueCount = 0;
@@ -1297,8 +1303,8 @@ public class AppStateTrackerTest {
final int[] array1 = makeRandomArray();
final int[] array2 = makeRandomArray();
- final boolean expected = isAnyAppIdUnwhitelistedSlow(array1, array2);
- final boolean actual = AppStateTrackerImpl.isAnyAppIdUnwhitelisted(array1, array2);
+ final boolean expected = isAnyAppIdUnexemptSlow(array1, array2);
+ final boolean actual = AppStateTrackerImpl.isAnyAppIdUnexempt(array1, array2);
assertEquals("Input: " + Arrays.toString(array1) + " " + Arrays.toString(array2),
expected, actual);
diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
index 6f37ff5ef329..c91bb93fc559 100644
--- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java
@@ -28,11 +28,13 @@ import static org.mockito.Mockito.when;
import android.app.StatusBarManager;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Resources;
import android.os.Looper;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
+import android.telecom.TelecomManager;
import android.test.mock.MockContentResolver;
import android.util.MutableBoolean;
import android.view.KeyEvent;
@@ -80,6 +82,7 @@ public class GestureLauncherServiceTest {
private @Mock Context mContext;
private @Mock Resources mResources;
private @Mock StatusBarManagerInternal mStatusBarManagerInternal;
+ private @Mock TelecomManager mTelecomManager;
private @Mock MetricsLogger mMetricsLogger;
private MockContentResolver mContentResolver;
private GestureLauncherService mGestureLauncherService;
@@ -104,6 +107,8 @@ public class GestureLauncherServiceTest {
mContentResolver = new MockContentResolver(mContext);
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
+ when(mContext.getSystemService(Context.TELECOM_SERVICE)).thenReturn(mTelecomManager);
+ when(mTelecomManager.createLaunchEmergencyDialerIntent(null)).thenReturn(new Intent());
mGestureLauncherService = new GestureLauncherService(mContext, mMetricsLogger);
}
@@ -176,6 +181,13 @@ public class GestureLauncherServiceTest {
}
@Test
+ public void testHandlePanicGesture_userSetupComplete() {
+ withUserSetupCompleteValue(true);
+
+ assertTrue(mGestureLauncherService.handlePanicButtonGesture());
+ }
+
+ @Test
public void testHandleCameraLaunchGesture_userSetupNotComplete() {
withUserSetupCompleteValue(false);
@@ -184,6 +196,13 @@ public class GestureLauncherServiceTest {
}
@Test
+ public void testHandlePanicGesture_userSetupNotComplete() {
+ withUserSetupCompleteValue(false);
+
+ assertFalse(mGestureLauncherService.handlePanicButtonGesture());
+ }
+
+ @Test
public void testInterceptPowerKeyDown_firstPowerDownCameraPowerGestureOnInteractive() {
withCameraDoubleTapPowerEnableConfigValue(true);
withCameraDoubleTapPowerDisableSettingValue(0);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index a9f2e4a50ded..57bfbf33d680 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -27,6 +27,7 @@ import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -95,12 +96,15 @@ public class FullScreenMagnificationControllerTest {
ValueAnimator mMockValueAnimator;
ValueAnimator.AnimatorUpdateListener mTargetAnimationListener;
+ ValueAnimator.AnimatorListener mStateListener;
FullScreenMagnificationController mFullScreenMagnificationController;
+ Runnable mEndCallback;
@Before
public void setUp() {
Looper looper = InstrumentationRegistry.getContext().getMainLooper();
+ mEndCallback = Mockito.mock(Runnable.class);
// Pretending ID of the Thread associated with looper as main thread ID in controller
when(mMockContext.getMainLooper()).thenReturn(looper);
when(mMockControllerCtx.getContext()).thenReturn(mMockContext);
@@ -319,6 +323,7 @@ public class FullScreenMagnificationControllerTest {
for (int i = 0; i < DISPLAY_COUNT; i++) {
setScaleAndCenter_animated_stateChangesAndAnimationHappens(i);
resetMockWindowManager();
+ Mockito.reset(mEndCallback);
}
}
@@ -331,7 +336,7 @@ public class FullScreenMagnificationControllerTest {
MagnificationSpec endSpec = getMagnificationSpec(scale, offsets);
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, scale,
- newCenter.x, newCenter.y, true, SERVICE_ID_1));
+ newCenter.x, newCenter.y, mEndCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(newCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5);
@@ -358,7 +363,33 @@ public class FullScreenMagnificationControllerTest {
Mockito.reset(mMockWindowManager);
when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f);
mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+ mStateListener.onAnimationEnd(mMockValueAnimator);
verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(endSpec)));
+ verify(mEndCallback).run();
+ }
+
+ @Test
+ public void testSetScaleAndCenterWithAnimation_sameSpec_noAnimationButInvokeEndCallback() {
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ setScaleAndCenter_sameSpec_noAnimationButInvokeEndCallback(i);
+ Mockito.reset(mEndCallback);
+ }
+ }
+
+ private void setScaleAndCenter_sameSpec_noAnimationButInvokeEndCallback(int displayId) {
+ register(displayId);
+ final PointF center = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ final float targetScale = 2.0f;
+ assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
+ targetScale, center.x, center.y, false, SERVICE_ID_1));
+ mMessageCapturingHandler.sendAllMessages();
+
+ assertFalse(mFullScreenMagnificationController.setScaleAndCenter(displayId,
+ targetScale, center.x, center.y, mEndCallback, SERVICE_ID_1));
+ mMessageCapturingHandler.sendAllMessages();
+
+ verify(mMockValueAnimator, never()).start();
+ verify(mEndCallback).run();
}
@Test
@@ -639,6 +670,69 @@ public class FullScreenMagnificationControllerTest {
}
@Test
+ public void testReset_notMagnifying_noStateChangeButInvokeCallback() {
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ reset_notMagnifying_noStateChangeButInvokeCallback(i);
+ Mockito.reset(mEndCallback);
+ }
+ }
+
+ private void reset_notMagnifying_noStateChangeButInvokeCallback(int displayId) {
+ register(displayId);
+
+ assertFalse(mFullScreenMagnificationController.reset(displayId, mEndCallback));
+ mMessageCapturingHandler.sendAllMessages();
+
+ verify(mMockAms, never()).notifyMagnificationChanged(eq(displayId),
+ any(Region.class), anyFloat(), anyFloat(), anyFloat());
+ verify(mEndCallback).run();
+ }
+
+ @Test
+ public void testReset_Magnifying_resetsMagnificationAndInvokeLastEndCallback() {
+ for (int i = 0; i < DISPLAY_COUNT; i++) {
+ reset_Magnifying_resetsMagnificationAndInvokeLastEndCallback(i);
+ }
+ }
+
+ private void reset_Magnifying_resetsMagnificationAndInvokeLastEndCallback(int displayId) {
+ register(displayId);
+ float scale = 2.5f;
+ PointF firstCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
+ scale, firstCenter.x, firstCenter.y, mEndCallback, SERVICE_ID_1));
+ mMessageCapturingHandler.sendAllMessages();
+ Mockito.reset(mMockValueAnimator);
+ // Stubs the logic after the animation is started.
+ doAnswer(invocation -> {
+ mStateListener.onAnimationEnd(mMockValueAnimator);
+ return null;
+ }).when(mMockValueAnimator).cancel();
+ when(mMockValueAnimator.isRunning()).thenReturn(true);
+ // Intermediate point
+ float fraction = 0.33f;
+ when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction);
+ mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+ Runnable lastEndCallback = Mockito.mock(Runnable.class);
+
+ assertTrue(mFullScreenMagnificationController.reset(displayId, lastEndCallback));
+ mMessageCapturingHandler.sendAllMessages();
+
+ // Verify expected actions.
+ verify(mEndCallback, never()).run();
+ verify(mMockValueAnimator).start();
+ verify(mMockValueAnimator).cancel();
+
+ // Fast-forward the animation to the end.
+ when(mMockValueAnimator.getAnimatedFraction()).thenReturn(1.0f);
+ mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator);
+ mStateListener.onAnimationEnd(mMockValueAnimator);
+
+ assertFalse(mFullScreenMagnificationController.isMagnifying(DISPLAY_0));
+ verify(lastEndCallback).run();
+ }
+
+ @Test
public void testTurnScreenOff_resetsMagnification() {
register(DISPLAY_0);
register(DISPLAY_1);
@@ -1043,6 +1137,10 @@ public class FullScreenMagnificationControllerTest {
ArgumentCaptor.forClass(ValueAnimator.AnimatorUpdateListener.class);
verify(mMockValueAnimator).addUpdateListener(listenerArgumentCaptor.capture());
mTargetAnimationListener = listenerArgumentCaptor.getValue();
+ ArgumentCaptor<ValueAnimator.AnimatorListener> animatorListenerArgumentCaptor =
+ ArgumentCaptor.forClass(ValueAnimator.AnimatorListener.class);
+ verify(mMockValueAnimator).addListener(animatorListenerArgumentCaptor.capture());
+ mStateListener = animatorListenerArgumentCaptor.getValue();
Mockito.reset(mMockValueAnimator); // Ignore other initialization
}
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
index 0dfdd4862d2b..922d71554426 100644
--- a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
@@ -99,6 +99,7 @@ public class AttentionManagerServiceTest {
AttentionCheck attentionCheck = new AttentionCheck(mMockAttentionCallbackInternal,
mSpyAttentionManager);
mSpyAttentionManager.mCurrentAttentionCheck = attentionCheck;
+ mSpyAttentionManager.mService = new MockIAttentionService();
}
@Test
@@ -115,6 +116,7 @@ public class AttentionManagerServiceTest {
@Test
public void testCheckAttention_returnFalseWhenPowerManagerNotInteract() throws RemoteException {
+ doReturn(true).when(mSpyAttentionManager).isAttentionServiceSupported();
doReturn(false).when(mMockIPowerManager).isInteractive();
AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
assertThat(mSpyAttentionManager.checkAttention(mTimeout, callback)).isFalse();
@@ -122,9 +124,11 @@ public class AttentionManagerServiceTest {
@Test
public void testCheckAttention_callOnSuccess() throws RemoteException {
- doReturn(true).when(mSpyAttentionManager).isServiceEnabled();
+ doReturn(true).when(mSpyAttentionManager).isAttentionServiceSupported();
+ doReturn(true).when(mSpyAttentionManager).isServiceAvailable();
doReturn(true).when(mMockIPowerManager).isInteractive();
doNothing().when(mSpyAttentionManager).freeIfInactiveLocked();
+ mSpyAttentionManager.mCurrentAttentionCheck = null;
AttentionCallbackInternal callback = Mockito.mock(AttentionCallbackInternal.class);
mSpyAttentionManager.checkAttention(mTimeout, callback);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
new file mode 100644
index 000000000000..dad360d40515
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.biometrics.sensors;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@Presubmit
+@SmallTest
+public class BiometricSchedulerTest {
+
+ private static final String TAG = "BiometricSchedulerTest";
+
+ private BiometricScheduler mScheduler;
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private ClientMonitor.LazyDaemon<Object> mLazyDaemon;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mScheduler = new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */);
+ }
+
+ @Test
+ public void testClientDuplicateFinish_ignoredBySchedulerAndDoesNotCrash() {
+ final ClientMonitor<Object> client1 = new TestClientMonitor(mContext, mLazyDaemon);
+ final ClientMonitor<Object> client2 = new TestClientMonitor(mContext, mLazyDaemon);
+ mScheduler.scheduleClientMonitor(client1);
+ mScheduler.scheduleClientMonitor(client2);
+
+ client1.mFinishCallback.onClientFinished(client1, true /* success */);
+ client1.mFinishCallback.onClientFinished(client1, true /* success */);
+ }
+
+ private static class TestClientMonitor extends ClientMonitor<Object> {
+
+ public TestClientMonitor(@NonNull Context context, @NonNull LazyDaemon<Object> lazyDaemon) {
+ super(context, lazyDaemon, null /* token */, null /* listener */, 0 /* userId */,
+ TAG, 0 /* cookie */, 0 /* sensorId */, 0 /* statsModality */,
+ 0 /* statsAction */, 0 /* statsClient */);
+ }
+
+ @Override
+ public void unableToStart() {
+
+ }
+
+ @Override
+ protected void startHalOperation() {
+
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
index 50086affcbc5..870a27417cd2 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
@@ -144,6 +144,26 @@ public class ActiveSourceActionTest {
}
@Test
+ public void playbackDevice_updatesActiveSourceState() {
+ HdmiCecLocalDevicePlayback playbackDevice = new HdmiCecLocalDevicePlayback(
+ mHdmiControlService);
+ playbackDevice.init();
+ mLocalDevices.add(playbackDevice);
+ mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+ mTestLooper.dispatchAll();
+
+ HdmiCecFeatureAction action = new com.android.server.hdmi.ActiveSourceAction(
+ playbackDevice, ADDR_TV);
+ playbackDevice.addAndStartAction(action);
+ mTestLooper.dispatchAll();
+
+ assertThat(playbackDevice.getActiveSource().logicalAddress).isEqualTo(
+ playbackDevice.mAddress);
+ assertThat(playbackDevice.getActiveSource().physicalAddress).isEqualTo(mPhysicalAddress);
+ assertThat(playbackDevice.mIsActiveSource).isTrue();
+ }
+
+ @Test
public void audioDevice_sendsActiveSource_noMenuStatus() {
HdmiCecLocalDeviceAudioSystem audioDevice = new HdmiCecLocalDeviceAudioSystem(
mHdmiControlService);
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 35f9ca5cce68..960a7ab52c22 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -15,6 +15,7 @@
*/
package com.android.server.hdmi;
+import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
import static com.android.server.hdmi.Constants.ADDR_TV;
import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
@@ -22,6 +23,7 @@ import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.hardware.hdmi.HdmiControlManager;
import android.os.Handler;
import android.os.IPowerManager;
import android.os.IThermalService;
@@ -29,6 +31,7 @@ import android.os.Looper;
import android.os.PowerManager;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
+import android.provider.Settings.Global;
import android.sysprop.HdmiProperties;
import android.view.KeyEvent;
@@ -272,7 +275,6 @@ public class HdmiCecLocalDevicePlaybackTest {
}
@Test
- @Ignore("b/120845532")
public void handleSetSystemAudioModeOn_audioSystemBroadcast() {
mHdmiControlService.setSystemAudioActivated(false);
assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse();
@@ -284,7 +286,6 @@ public class HdmiCecLocalDevicePlaybackTest {
}
@Test
- @Ignore("b/120845532")
public void handleSetSystemAudioModeOff_audioSystemToPlayback() {
mHdmiCecLocalDevicePlayback.mService.setSystemAudioActivated(true);
assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue();
@@ -298,8 +299,7 @@ public class HdmiCecLocalDevicePlaybackTest {
}
@Test
- @Ignore("b/120845532")
- public void handleSystemAudioModeStatusOn_DirectltToLocalDeviceFromAudioSystem() {
+ public void handleSystemAudioModeStatusOn_DirectlyToLocalDeviceFromAudioSystem() {
mHdmiControlService.setSystemAudioActivated(false);
assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isFalse();
HdmiCecMessage message =
@@ -324,29 +324,117 @@ public class HdmiCecLocalDevicePlaybackTest {
}
@Test
- public void handleOnStandby_ScreenOff_NotActiveSource() {
+ public void handleOnStandby_ScreenOff_NotActiveSource_ToTv() {
+ mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
+ Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV);
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
+ mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
+ HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
+
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
+ }
+
+ @Test
+ public void handleOnStandby_ScreenOff_NotActiveSource_Broadcast() {
+ mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
+ Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
- HdmiCecMessage standbyMessage = HdmiCecMessageBuilder.buildStandby(
+ HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
+ HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
+
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
+ }
+
+ @Test
+ public void handleOnStandby_ScreenOff_NotActiveSource_None() {
+ mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
+ Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE);
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(false);
+ mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
+ mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
+ HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
+
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
+ }
+
+ @Test
+ public void handleOnStandby_ScreenOff_ActiveSource_ToTv() {
+ mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
+ Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV);
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
+ mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
+ HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
- assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessage);
+ assertThat(mNativeWrapper.getResultMessages()).contains(standbyMessageToTv);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
}
@Test
- public void handleOnStandby_ScreenOff_ActiveSource() {
+ public void handleOnStandby_ScreenOff_ActiveSource_Broadcast() {
+ mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
+ Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
mTestLooper.dispatchAll();
- HdmiCecMessage standbyMessage = HdmiCecMessageBuilder.buildStandby(
+ HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
+ HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
- assertThat(mNativeWrapper.getResultMessages()).contains(standbyMessage);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
+ assertThat(mNativeWrapper.getResultMessages()).contains(standbyMessageBroadcast);
+ }
+
+ @Test
+ public void handleOnStandby_ScreenOff_ActiveSource_None() {
+ mHdmiCecLocalDevicePlayback.mService.writeStringSetting(
+ Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
+ HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE);
+ mHdmiCecLocalDevicePlayback.setIsActiveSource(true);
+ mHdmiCecLocalDevicePlayback.setAutoDeviceOff(true);
+ mHdmiCecLocalDevicePlayback.onStandby(false, HdmiControlService.STANDBY_SCREEN_OFF);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage standbyMessageToTv = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_TV);
+ HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby(
+ mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST);
+
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageToTv);
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(standbyMessageBroadcast);
}
@Test
@@ -526,4 +614,19 @@ public class HdmiCecLocalDevicePlaybackTest {
assertThat(mNativeWrapper.getResultMessages()).contains(activeSource);
}
+
+ @Test
+ public void handleSetStreamPath_afterHotplug_hasCorrectActiveSource() {
+ mHdmiControlService.onHotplug(1, false);
+ mHdmiControlService.onHotplug(1, true);
+
+ HdmiCecMessage setStreamPath = HdmiCecMessageBuilder.buildSetStreamPath(ADDR_TV,
+ mPlaybackPhysicalAddress);
+ mHdmiCecLocalDevicePlayback.dispatchMessage(setStreamPath);
+ mTestLooper.dispatchAll();
+
+ assertThat(mHdmiCecLocalDevicePlayback.getActiveSource().logicalAddress).isEqualTo(
+ mHdmiCecLocalDevicePlayback.getDeviceInfo().getLogicalAddress());
+ assertThat(mHdmiCecLocalDevicePlayback.mIsActiveSource).isTrue();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
index 6b7634db8a60..62cc111e4dae 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
@@ -97,9 +97,9 @@ public class JobSetTest {
mJobSet.remove(testJob1);
mJobSet.remove(testJob2);
assertHaveSameJobs(mJobSet.mJobsPerSourceUid, mJobSet.mJobs);
- mJobSet.removeJobsOfNonUsers(new int[] {mContext.getUserId(), SECONDARY_USER_ID_1});
+ mJobSet.removeJobsOfUnlistedUsers(new int[] {mContext.getUserId(), SECONDARY_USER_ID_1});
assertHaveSameJobs(mJobSet.mJobsPerSourceUid, mJobSet.mJobs);
- mJobSet.removeJobsOfNonUsers(new int[] {mContext.getUserId()});
+ mJobSet.removeJobsOfUnlistedUsers(new int[] {mContext.getUserId()});
assertTrue("mJobs should be empty", mJobSet.mJobs.size() == 0);
assertTrue("mJobsPerSourceUid should be empty", mJobSet.mJobsPerSourceUid.size() == 0);
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
index e08eea298aaf..08392737350a 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt
@@ -160,7 +160,7 @@ class OverlayActorEnforcerTests {
private val hasPermission: Boolean = false,
private val overlayableInfo: OverlayableInfo? = null,
private vararg val packageNames: String = arrayOf("com.test.actor.one")
- ) : OverlayableInfoCallback {
+ ) : PackageManagerHelper {
override fun getNamedActors() = if (isActor) {
mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME))
@@ -195,6 +195,14 @@ class OverlayActorEnforcerTests {
}
}
+ override fun getConfigSignaturePackage(): String {
+ throw UnsupportedOperationException()
+ }
+
+ override fun getOverlayPackages(userId: Int): MutableList<PackageInfo> {
+ throw UnsupportedOperationException()
+ }
+
override fun signaturesMatching(pkgName1: String, pkgName2: String, userId: Int): Boolean {
throw UnsupportedOperationException()
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
index b7692f912e39..e281f2b206f5 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
@@ -44,9 +44,9 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
@Test
public void testUpdateOverlaysForUser() {
final OverlayManagerServiceImpl impl = getImpl();
- addSystemPackage(target(TARGET), USER);
- addSystemPackage(target("some.other.target"), USER);;
- addSystemPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(target(TARGET), USER);
+ addPackage(target("some.other.target"), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
// do nothing, expect no change
final List<String> a = impl.updateOverlaysForUser(USER);
@@ -54,7 +54,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
assertTrue(a.contains(TARGET));
// upgrade overlay, keep target
- addSystemPackage(overlay(OVERLAY, TARGET), USER);
+ addPackage(overlay(OVERLAY, TARGET), USER);
final List<String> b = impl.updateOverlaysForUser(USER);
assertEquals(1, b.size());
@@ -66,7 +66,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
assertTrue(c.contains(TARGET));
// upgrade overlay, switch to new target
- addSystemPackage(overlay(OVERLAY, "some.other.target"), USER);
+ addPackage(overlay(OVERLAY, "some.other.target"), USER);
final List<String> d = impl.updateOverlaysForUser(USER);
assertEquals(2, d.size());
assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index f4c5506c7001..c1d862ab2ad4 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -19,6 +19,7 @@ package com.android.server.om;
import static android.content.om.OverlayInfo.STATE_DISABLED;
import static android.content.om.OverlayInfo.STATE_ENABLED;
import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
+import static android.os.OverlayablePolicy.CONFIG_SIGNATURE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -49,6 +50,10 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
private static final String OVERLAY3 = OVERLAY + "3";
private static final int USER3 = USER2 + 1;
+ private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.dummy.ref";
+ private static final String CERT_CONFIG_OK = "config_certificate_ok";
+ private static final String CERT_CONFIG_NOK = "config_certificate_nok";
+
@Test
public void testGetOverlayInfo() {
installNewPackage(overlay(OVERLAY, TARGET), USER);
@@ -204,4 +209,87 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
impl.setEnabled(OVERLAY, true, USER);
assertEquals(0, listener.count);
}
+
+ @Test
+ public void testConfigSignaturePolicyOk() {
+ setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
+ reinitializeImpl();
+
+ addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
+ installNewPackage(target(TARGET), USER);
+ installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER);
+
+ final DummyIdmapDaemon idmapd = getIdmapd();
+ final DummyDeviceState state = getState();
+ String overlayPath = state.select(OVERLAY, USER).apkPath;
+ assertTrue(idmapd.idmapExists(overlayPath, USER));
+
+ DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertTrue((CONFIG_SIGNATURE & idmap.policies) == CONFIG_SIGNATURE);
+ }
+
+ @Test
+ public void testConfigSignaturePolicyCertNok() {
+ setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
+ reinitializeImpl();
+
+ addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
+ installNewPackage(target(TARGET), USER);
+ installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+
+ final DummyIdmapDaemon idmapd = getIdmapd();
+ final DummyDeviceState state = getState();
+ String overlayPath = state.select(OVERLAY, USER).apkPath;
+ assertTrue(idmapd.idmapExists(overlayPath, USER));
+
+ DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ }
+
+ @Test
+ public void testConfigSignaturePolicyNoConfig() {
+ addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
+ installNewPackage(target(TARGET), USER);
+ installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+
+ final DummyIdmapDaemon idmapd = getIdmapd();
+ final DummyDeviceState state = getState();
+ String overlayPath = state.select(OVERLAY, USER).apkPath;
+ assertTrue(idmapd.idmapExists(overlayPath, USER));
+
+ DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ }
+
+ @Test
+ public void testConfigSignaturePolicyNoRefPkg() {
+ installNewPackage(target(TARGET), USER);
+ installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+
+ final DummyIdmapDaemon idmapd = getIdmapd();
+ final DummyDeviceState state = getState();
+ String overlayPath = state.select(OVERLAY, USER).apkPath;
+ assertTrue(idmapd.idmapExists(overlayPath, USER));
+
+ DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ }
+
+ @Test
+ public void testConfigSignaturePolicyRefPkgNotSystem() {
+ setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
+ reinitializeImpl();
+
+ addPackage(app(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
+ installNewPackage(target(TARGET), USER);
+ installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
+
+ final DummyIdmapDaemon idmapd = getIdmapd();
+ final DummyDeviceState state = getState();
+ String overlayPath = state.select(OVERLAY, USER).apkPath;
+ assertTrue(idmapd.idmapExists(overlayPath, USER));
+
+ DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
+ assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
index 733310b2508a..2faf29f45375 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -27,6 +27,7 @@ import android.content.om.OverlayInfo.State;
import android.content.om.OverlayableInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -52,6 +53,7 @@ class OverlayManagerServiceImplTestsBase {
private DummyPackageManagerHelper mPackageManager;
private DummyIdmapDaemon mIdmapDaemon;
private OverlayConfig mOverlayConfig;
+ private String mConfigSignaturePackageName;
@Before
public void setUp() {
@@ -83,6 +85,18 @@ class OverlayManagerServiceImplTestsBase {
return mListener;
}
+ DummyIdmapDaemon getIdmapd() {
+ return mIdmapDaemon;
+ }
+
+ DummyDeviceState getState() {
+ return mState;
+ }
+
+ void setConfigSignaturePackageName(String packageName) {
+ mConfigSignaturePackageName = packageName;
+ }
+
void assertState(@State int expected, final String overlayPackageName, int userId) {
final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId);
if (info == null) {
@@ -102,9 +116,14 @@ class OverlayManagerServiceImplTestsBase {
assertEquals(expected, actual);
}
+ DummyDeviceState.PackageBuilder app(String packageName) {
+ return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
+ null /* targetOverlayableName */, "data");
+ }
+
DummyDeviceState.PackageBuilder target(String packageName) {
return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
- null /* targetOverlayableName */);
+ null /* targetOverlayableName */, "");
}
DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) {
@@ -114,10 +133,10 @@ class OverlayManagerServiceImplTestsBase {
DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName,
String targetOverlayableName) {
return new DummyDeviceState.PackageBuilder(packageName, targetPackageName,
- targetOverlayableName);
+ targetOverlayableName, "");
}
- void addSystemPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
+ void addPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
mState.add(pkg, userId);
}
@@ -242,15 +261,17 @@ class OverlayManagerServiceImplTestsBase {
private String packageName;
private String targetPackage;
private String certificate = "[default]";
+ private String partition;
private int version = 0;
private ArrayList<String> overlayableNames = new ArrayList<>();
private String targetOverlayableName;
private PackageBuilder(String packageName, String targetPackage,
- String targetOverlayableName) {
+ String targetOverlayableName, String partition) {
this.packageName = packageName;
this.targetPackage = targetPackage;
this.targetOverlayableName = targetOverlayableName;
+ this.partition = partition;
}
PackageBuilder setCertificate(String certificate) {
@@ -269,9 +290,19 @@ class OverlayManagerServiceImplTestsBase {
}
Package build() {
- final String apkPath = String.format("%s/%s/base.apk",
- targetPackage == null ? "/system/app/:" : "/vendor/overlay/:",
- packageName);
+ String path = "";
+ if (TextUtils.isEmpty(partition)) {
+ if (targetPackage == null) {
+ path = "/system/app";
+ } else {
+ path = "/vendor/overlay";
+ }
+ } else {
+ String type = targetPackage == null ? "app" : "overlay";
+ path = String.format("%s/%s", partition, type);
+ }
+
+ final String apkPath = String.format("%s/%s/base.apk", path, packageName);
final Package newPackage = new Package(packageName, targetPackage,
targetOverlayableName, version, apkPath, certificate);
newPackage.overlayableNames.addAll(overlayableNames);
@@ -302,8 +333,7 @@ class OverlayManagerServiceImplTestsBase {
}
}
- static final class DummyPackageManagerHelper implements PackageManagerHelper,
- OverlayableInfoCallback {
+ final class DummyPackageManagerHelper implements PackageManagerHelper {
private final DummyDeviceState mState;
private DummyPackageManagerHelper(DummyDeviceState state) {
@@ -343,6 +373,11 @@ class OverlayManagerServiceImplTestsBase {
.collect(Collectors.toList());
}
+ @Override
+ public @NonNull String getConfigSignaturePackage() {
+ return mConfigSignaturePackageName;
+ }
+
@Nullable
@Override
public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
index 78c708084d38..d888b9258d33 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
@@ -25,7 +25,6 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
-import org.testng.Assert.assertThrows
@RunWith(Parameterized::class)
class OverlayReferenceMapperTests {
@@ -160,9 +159,6 @@ class OverlayReferenceMapperTests {
expected.forEach { (actorPkgName, expectedPkgNames) ->
expectedPkgNames.forEach { expectedPkgName ->
if (deferRebuild) {
- assertThrows(IllegalStateException::class.java) {
- mapper.isValidActor(expectedPkgName, actorPkgName)
- }
mapper.rebuildIfDeferred()
deferRebuild = false
}
@@ -187,7 +183,7 @@ class OverlayReferenceMapperTests {
)
)
) = OverlayReferenceMapper(deferRebuild, object : OverlayReferenceMapper.Provider {
- override fun getActorPkg(actor: String?) =
+ override fun getActorPkg(actor: String) =
OverlayActorEnforcer.getPackageNameForActor(actor, namedActors).first
override fun getTargetToOverlayables(pkg: AndroidPackage) =
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 2d9c6ce40a40..f991dff2797f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -19,7 +19,6 @@ package com.android.server.pm;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.empty;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -70,8 +69,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.function.IntFunction;
-import java.util.stream.Collectors;
@Presubmit
@RunWith(JUnit4.class)
@@ -805,24 +802,24 @@ public class AppsFilterTest {
queriesProviderAppId);
final SparseArray<int[]> systemFilter =
- appsFilter.getVisibilityWhitelist(system, USER_ARRAY, mExisting);
+ appsFilter.getVisibilityAllowList(system, USER_ARRAY, mExisting);
assertThat(toList(systemFilter.get(SYSTEM_USER)),
contains(seesNothingAppId, hasProviderAppId, queriesProviderAppId));
final SparseArray<int[]> seesNothingFilter =
- appsFilter.getVisibilityWhitelist(seesNothing, USER_ARRAY, mExisting);
+ appsFilter.getVisibilityAllowList(seesNothing, USER_ARRAY, mExisting);
assertThat(toList(seesNothingFilter.get(SYSTEM_USER)),
contains(seesNothingAppId));
assertThat(toList(seesNothingFilter.get(SECONDARY_USER)),
contains(seesNothingAppId));
final SparseArray<int[]> hasProviderFilter =
- appsFilter.getVisibilityWhitelist(hasProvider, USER_ARRAY, mExisting);
+ appsFilter.getVisibilityAllowList(hasProvider, USER_ARRAY, mExisting);
assertThat(toList(hasProviderFilter.get(SYSTEM_USER)),
contains(hasProviderAppId, queriesProviderAppId));
SparseArray<int[]> queriesProviderFilter =
- appsFilter.getVisibilityWhitelist(queriesProvider, USER_ARRAY, mExisting);
+ appsFilter.getVisibilityAllowList(queriesProvider, USER_ARRAY, mExisting);
assertThat(toList(queriesProviderFilter.get(SYSTEM_USER)),
contains(queriesProviderAppId));
@@ -831,7 +828,7 @@ public class AppsFilterTest {
// ensure implicit access is included in the filter
queriesProviderFilter =
- appsFilter.getVisibilityWhitelist(queriesProvider, USER_ARRAY, mExisting);
+ appsFilter.getVisibilityAllowList(queriesProvider, USER_ARRAY, mExisting);
assertThat(toList(queriesProviderFilter.get(SYSTEM_USER)),
contains(hasProviderAppId, queriesProviderAppId));
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index fa9ee19cba9d..aa92ba49d190 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -57,6 +57,7 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.permission.persistence.RuntimePermissionsPersistence;
import com.android.server.LocalServices;
import com.android.server.pm.permission.PermissionSettings;
@@ -86,6 +87,8 @@ public class PackageManagerSettingsTests {
@Mock
PermissionSettings mPermissionSettings;
+ @Mock
+ RuntimePermissionsPersistence mRuntimePermissionsPersistence;
@Before
public void initializeMocks() {
@@ -106,7 +109,8 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings, lock);
+ Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ mRuntimePermissionsPersistence, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
}
@@ -119,7 +123,8 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings, lock);
+ Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ mRuntimePermissionsPersistence, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
// write out, read back in and verify the same
@@ -134,7 +139,8 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings, lock);
+ Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ mRuntimePermissionsPersistence, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
assertThat(settings.getPackageLPr(PACKAGE_NAME_3), is(notNullValue()));
assertThat(settings.getPackageLPr(PACKAGE_NAME_1), is(notNullValue()));
@@ -155,12 +161,14 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings, lock);
+ Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ mRuntimePermissionsPersistence, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
settings.writeLPr();
// Create Settings again to make it read from the new files
- settings = new Settings(context.getFilesDir(), mPermissionSettings, lock);
+ settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ mRuntimePermissionsPersistence, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_2);
@@ -183,7 +191,7 @@ public class PackageManagerSettingsTests {
writePackageRestrictions_noSuspendingPackageXml(0);
final Object lock = new Object();
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, lock);
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, lock);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
settingsUnderTest.readPackageRestrictionsLPr(0);
@@ -206,7 +214,7 @@ public class PackageManagerSettingsTests {
writePackageRestrictions_noSuspendParamsMapXml(0);
final Object lock = new Object();
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, lock);
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, lock);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settingsUnderTest.readPackageRestrictionsLPr(0);
@@ -233,7 +241,8 @@ public class PackageManagerSettingsTests {
@Test
public void testReadWritePackageRestrictions_suspendInfo() {
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, new Object());
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
+ new Object());
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
final PackageSetting ps3 = createPackageSetting(PACKAGE_NAME_3);
@@ -330,7 +339,8 @@ public class PackageManagerSettingsTests {
@Test
public void testReadWritePackageRestrictions_distractionFlags() {
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, new Object());
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
+ new Object());
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
final PackageSetting ps3 = createPackageSetting(PACKAGE_NAME_3);
@@ -381,7 +391,8 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings, lock);
+ Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ mRuntimePermissionsPersistence, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
// Enable/Disable a package
@@ -558,8 +569,8 @@ public class PackageManagerSettingsTests {
public void testUpdatePackageSetting03() {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- final Settings testSettings01 =
- new Settings(context.getFilesDir(), mPermissionSettings, lock);
+ final Settings testSettings01 = new Settings(context.getFilesDir(), mPermissionSettings,
+ mRuntimePermissionsPersistence, lock);
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
testSettings01, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
final PackageSetting testPkgSetting01 =
@@ -673,8 +684,8 @@ public class PackageManagerSettingsTests {
public void testCreateNewSetting03() {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- final Settings testSettings01 =
- new Settings(context.getFilesDir(), mPermissionSettings, lock);
+ final Settings testSettings01 = new Settings(context.getFilesDir(), mPermissionSettings,
+ mRuntimePermissionsPersistence, lock);
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
testSettings01, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
final PackageSetting testPkgSetting01 = Settings.createNewSetting(
diff --git a/services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java b/services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java
index a1f105604559..2230ddd8a4a7 100644
--- a/services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/ShutdownCheckPointsTest.java
@@ -72,21 +72,32 @@ public class ShutdownCheckPointsTest {
@Test
public void testSystemServerEntry() {
mTestInjector.setCurrentTime(1000);
- mInstance.recordCheckPointInternal();
+ mInstance.recordCheckPointInternal("reason1");
assertTrue(dumpToString().startsWith(
- "Shutdown request from SYSTEM at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from SYSTEM for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "com.android.server.power.ShutdownCheckPointsTest"
+ ".testSystemServerEntry\n at "));
}
@Test
+ public void testSystemServerEntryWithoutReason() {
+ mTestInjector.setCurrentTime(1000);
+ mInstance.recordCheckPointInternal(null);
+
+ assertTrue(dumpToString().startsWith(
+ "Shutdown request from SYSTEM at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"));
+ }
+
+ @Test
public void testSystemServiceBinderEntry() {
mTestInjector.setCurrentTime(1000);
- mInstance.recordCheckPointInternal(Process.myPid());
+ mInstance.recordCheckPointInternal(Process.myPid(), "reason1");
assertTrue(dumpToString().startsWith(
- "Shutdown request from SYSTEM at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from SYSTEM for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "com.android.server.power.ShutdownCheckPointsTest"
+ ".testSystemServiceBinderEntry\n at "));
}
@@ -99,10 +110,11 @@ public class ShutdownCheckPointsTest {
when(mActivityManager.getRunningAppProcesses()).thenReturn(runningAppProcessInfos);
mTestInjector.setCurrentTime(1000);
- mInstance.recordCheckPointInternal(1);
+ mInstance.recordCheckPointInternal(1, "reason1");
assertEquals(
- "Shutdown request from BINDER at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from BINDER for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "com.android.server.power.ShutdownCheckPointsTest"
+ ".testCallerProcessBinderEntry\n"
+ "From process process_name (pid=1)\n\n",
@@ -114,10 +126,11 @@ public class ShutdownCheckPointsTest {
when(mActivityManager.getRunningAppProcesses()).thenThrow(new RemoteException("Error"));
mTestInjector.setCurrentTime(1000);
- mInstance.recordCheckPointInternal(1);
+ mInstance.recordCheckPointInternal(1, "reason1");
assertEquals(
- "Shutdown request from BINDER at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from BINDER for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "com.android.server.power.ShutdownCheckPointsTest"
+ ".testRemoteExceptionOnBinderEntry\n"
+ "From process ? (pid=1)\n\n",
@@ -127,10 +140,11 @@ public class ShutdownCheckPointsTest {
@Test
public void testUnknownProcessBinderEntry() {
mTestInjector.setCurrentTime(1000);
- mInstance.recordCheckPointInternal(1);
+ mInstance.recordCheckPointInternal(1, "reason1");
assertEquals(
- "Shutdown request from BINDER at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from BINDER for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "com.android.server.power.ShutdownCheckPointsTest"
+ ".testUnknownProcessBinderEntry\n"
+ "From process ? (pid=1)\n\n",
@@ -138,12 +152,22 @@ public class ShutdownCheckPointsTest {
}
@Test
+ public void testBinderEntryWithoutReason() throws RemoteException {
+ mTestInjector.setCurrentTime(1000);
+ mInstance.recordCheckPointInternal(1, null);
+
+ assertTrue(dumpToString().startsWith(
+ "Shutdown request from BINDER at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"));
+ }
+
+ @Test
public void testSystemServiceIntentEntry() {
mTestInjector.setCurrentTime(1000);
- mInstance.recordCheckPointInternal("some.intent", "android");
+ mInstance.recordCheckPointInternal("some.intent", "android", "reason1");
assertTrue(dumpToString().startsWith(
- "Shutdown request from SYSTEM at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from SYSTEM for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "com.android.server.power.ShutdownCheckPointsTest"
+ ".testSystemServiceIntentEntry\n at "));
}
@@ -151,39 +175,47 @@ public class ShutdownCheckPointsTest {
@Test
public void testIntentEntry() {
mTestInjector.setCurrentTime(1000);
- mInstance.recordCheckPointInternal("some.intent", "some.app");
+ mInstance.recordCheckPointInternal("some.intent", "some.app", "reason1");
assertEquals(
- "Shutdown request from INTENT at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from INTENT for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Intent: some.intent\n"
+ "Package: some.app\n\n",
dumpToString());
}
@Test
+ public void testIntentEntryWithoutReason() {
+ mTestInjector.setCurrentTime(1000);
+ mInstance.recordCheckPointInternal("some.intent", "some.app", null);
+
+ assertTrue(dumpToString().startsWith(
+ "Shutdown request from INTENT at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"));
+ }
+
+ @Test
public void testMultipleEntries() {
mTestInjector.setCurrentTime(1000);
- mInstance.recordCheckPointInternal(1);
+ mInstance.recordCheckPointInternal(1, "reason1");
mTestInjector.setCurrentTime(2000);
- mInstance.recordCheckPointInternal(2);
+ mInstance.recordCheckPointInternal(2, "reason2");
mTestInjector.setCurrentTime(3000);
- mInstance.recordCheckPointInternal("intent", "app");
+ mInstance.recordCheckPointInternal("intent", "app", "reason3");
assertEquals(
- "Shutdown request from BINDER at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from BINDER for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "com.android.server.power.ShutdownCheckPointsTest.testMultipleEntries\n"
- + "From process ? (pid=1)\n"
- + "\n"
- + "Shutdown request from BINDER at 1970-01-01 00:00:02.000 UTC (epoch=2000)"
- + "\n"
+ + "From process ? (pid=1)\n\n"
+ + "Shutdown request from BINDER for reason reason2 "
+ + "at 1970-01-01 00:00:02.000 UTC (epoch=2000)\n"
+ "com.android.server.power.ShutdownCheckPointsTest.testMultipleEntries\n"
- + "From process ? (pid=2)\n"
- + "\n"
- + "Shutdown request from INTENT at 1970-01-01 00:00:03.000 UTC (epoch=3000)"
- + "\n"
+ + "From process ? (pid=2)\n\n"
+ + "Shutdown request from INTENT for reason reason3 "
+ + "at 1970-01-01 00:00:03.000 UTC (epoch=3000)\n"
+ "Intent: intent\n"
- + "Package: app\n"
- + "\n",
+ + "Package: app\n\n",
dumpToString());
}
@@ -193,23 +225,22 @@ public class ShutdownCheckPointsTest {
ShutdownCheckPoints limitedInstance = new ShutdownCheckPoints(mTestInjector);
mTestInjector.setCurrentTime(1000);
- limitedInstance.recordCheckPointInternal("intent.1", "app.1");
+ limitedInstance.recordCheckPointInternal("intent.1", "app.1", "reason1");
mTestInjector.setCurrentTime(2000);
- limitedInstance.recordCheckPointInternal("intent.2", "app.2");
+ limitedInstance.recordCheckPointInternal("intent.2", "app.2", "reason2");
mTestInjector.setCurrentTime(3000);
- limitedInstance.recordCheckPointInternal("intent.3", "app.3");
+ limitedInstance.recordCheckPointInternal("intent.3", "app.3", "reason3");
// Drops first intent.
assertEquals(
- "Shutdown request from INTENT at 1970-01-01 00:00:02.000 UTC (epoch=2000)\n"
+ "Shutdown request from INTENT for reason reason2 "
+ + "at 1970-01-01 00:00:02.000 UTC (epoch=2000)\n"
+ "Intent: intent.2\n"
- + "Package: app.2\n"
- + "\n"
- + "Shutdown request from INTENT at 1970-01-01 00:00:03.000 UTC (epoch=3000)"
- + "\n"
+ + "Package: app.2\n\n"
+ + "Shutdown request from INTENT for reason reason3 "
+ + "at 1970-01-01 00:00:03.000 UTC (epoch=3000)\n"
+ "Intent: intent.3\n"
- + "Package: app.3\n"
- + "\n",
+ + "Package: app.3\n\n",
dumpToString(limitedInstance));
}
@@ -219,11 +250,11 @@ public class ShutdownCheckPointsTest {
File baseFile = new File(tempDir, "checkpoints");
mTestInjector.setCurrentTime(1000);
- mInstance.recordCheckPointInternal("first.intent", "first.app");
+ mInstance.recordCheckPointInternal("first.intent", "first.app", "reason1");
dumpToFile(baseFile);
mTestInjector.setCurrentTime(2000);
- mInstance.recordCheckPointInternal("second.intent", "second.app");
+ mInstance.recordCheckPointInternal("second.intent", "second.app", "reason2");
dumpToFile(baseFile);
File[] dumpFiles = tempDir.listFiles();
@@ -231,16 +262,18 @@ public class ShutdownCheckPointsTest {
assertEquals(2, dumpFiles.length);
assertEquals(
- "Shutdown request from INTENT at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from INTENT for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Intent: first.intent\n"
+ "Package: first.app\n\n",
readFileAsString(dumpFiles[0].getAbsolutePath()));
assertEquals(
- "Shutdown request from INTENT at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from INTENT for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Intent: first.intent\n"
+ "Package: first.app\n\n"
- + "Shutdown request from INTENT at 1970-01-01 00:00:02.000 UTC (epoch=2000)"
- + "\n"
+ + "Shutdown request from INTENT for reason reason2 "
+ + "at 1970-01-01 00:00:02.000 UTC (epoch=2000)\n"
+ "Intent: second.intent\n"
+ "Package: second.app\n\n",
readFileAsString(dumpFiles[1].getAbsolutePath()));
@@ -254,21 +287,22 @@ public class ShutdownCheckPointsTest {
File baseFile = new File(tempDir, "checkpoints");
mTestInjector.setCurrentTime(1000);
- instance.recordCheckPointInternal("first.intent", "first.app");
+ instance.recordCheckPointInternal("first.intent", "first.app", "reason1");
dumpToFile(instance, baseFile);
mTestInjector.setCurrentTime(2000);
- instance.recordCheckPointInternal("second.intent", "second.app");
+ instance.recordCheckPointInternal("second.intent", "second.app", "reason2");
dumpToFile(instance, baseFile);
File[] dumpFiles = tempDir.listFiles();
assertEquals(1, dumpFiles.length);
assertEquals(
- "Shutdown request from INTENT at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Shutdown request from INTENT for reason reason1 "
+ + "at 1970-01-01 00:00:01.000 UTC (epoch=1000)\n"
+ "Intent: first.intent\n"
+ "Package: first.app\n\n"
- + "Shutdown request from INTENT at 1970-01-01 00:00:02.000 UTC (epoch=2000)"
- + "\n"
+ + "Shutdown request from INTENT for reason reason2 "
+ + "at 1970-01-01 00:00:02.000 UTC (epoch=2000)\n"
+ "Intent: second.intent\n"
+ "Package: second.app\n\n",
readFileAsString(dumpFiles[0].getAbsolutePath()));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 10976882048a..980772bb08bc 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -166,6 +166,7 @@ import com.android.internal.util.FastXmlSerializer;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.UiServiceTestCase;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;
@@ -178,7 +179,6 @@ import com.android.server.wm.WindowManagerInternal;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -3774,6 +3774,27 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testEnqueuedAdjustmentAppliesAdjustments_MultiNotifications() throws Exception {
+ final NotificationRecord r1 = generateNotificationRecord(mTestNotificationChannel);
+ final NotificationRecord r2 = generateNotificationRecord(mTestNotificationChannel);
+ mService.addEnqueuedNotification(r1);
+ mService.addEnqueuedNotification(r2);
+ when(mAssistants.isSameUser(eq(null), anyInt())).thenReturn(true);
+
+ Bundle signals = new Bundle();
+ signals.putInt(Adjustment.KEY_IMPORTANCE,
+ IMPORTANCE_HIGH);
+ Adjustment adjustment = new Adjustment(
+ r1.getSbn().getPackageName(), r1.getKey(), signals,
+ "", r1.getUser().getIdentifier());
+
+ mBinderService.applyEnqueuedAdjustmentFromAssistant(null, adjustment);
+
+ assertEquals(IMPORTANCE_HIGH, r1.getImportance());
+ assertEquals(IMPORTANCE_HIGH, r2.getImportance());
+ }
+
+ @Test
public void testRestore() throws Exception {
int systemChecks = mService.countSystemChecks;
mBinderService.applyRestore(null, USER_SYSTEM);
@@ -6434,7 +6455,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testOnUnlockUser() {
UserInfo ui = new UserInfo();
ui.id = 10;
- mService.onUnlockUser(ui);
+ mService.onUserUnlocking(new TargetUser(ui));
waitForIdle();
verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserUnlocked(ui.id);
@@ -6444,7 +6465,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testOnStopUser() {
UserInfo ui = new UserInfo();
ui.id = 10;
- mService.onStopUser(ui);
+ mService.onUserStopping(new TargetUser(ui));
waitForIdle();
verify(mHistoryManager, timeout(MAX_POST_DELAY).times(1)).onUserStopped(ui.id);
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 e45ced64c5b6..2f020736d059 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1327,12 +1327,15 @@ public class ActivityRecordTests extends ActivityTestsBase {
public void testRemoveFromHistory() {
final Task stack = mActivity.getRootTask();
final Task task = mActivity.getTask();
+ final WindowProcessController wpc = mActivity.app;
+ assertTrue(wpc.hasActivities());
mActivity.removeFromHistory("test");
assertEquals(DESTROYED, mActivity.getState());
assertNull(mActivity.app);
assertNull(mActivity.getTask());
+ assertFalse(wpc.hasActivities());
assertEquals(0, task.getChildCount());
assertEquals(task.getRootTask(), task);
assertEquals(0, stack.getChildCount());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 775df74f88e0..dfdf686e5502 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -1072,7 +1072,7 @@ public class ActivityStackTests extends ActivityTestsBase {
assertEquals(2, mTask.getChildCount());
- mRootWindowContainer.handleAppDied(secondActivity.app);
+ secondActivity.app.handleAppDied();
assertFalse(mTask.hasChild());
assertFalse(mStack.hasChild());
@@ -1086,7 +1086,7 @@ public class ActivityStackTests extends ActivityTestsBase {
activity.launchCount = 1;
activity.setSavedState(null /* savedState */);
- mRootWindowContainer.handleAppDied(activity.app);
+ activity.app.handleAppDied();
assertEquals(1, mTask.getChildCount());
assertEquals(1, mStack.getChildCount());
@@ -1100,7 +1100,7 @@ public class ActivityStackTests extends ActivityTestsBase {
activity.launchCount = 3;
activity.setSavedState(null /* savedState */);
- mRootWindowContainer.handleAppDied(activity.app);
+ activity.app.handleAppDied();
assertFalse(mTask.hasChild());
assertFalse(mStack.hasChild());
@@ -1114,7 +1114,7 @@ public class ActivityStackTests extends ActivityTestsBase {
activity.launchCount = 1;
activity.setSavedState(null /* savedState */);
- mRootWindowContainer.handleAppDied(activity.app);
+ activity.app.handleAppDied();
assertEquals(1, mTask.getChildCount());
assertEquals(1, mStack.getChildCount());
@@ -1128,7 +1128,7 @@ public class ActivityStackTests extends ActivityTestsBase {
activity.launchCount = 3;
activity.setSavedState(null /* savedState */);
- mRootWindowContainer.handleAppDied(activity.app);
+ activity.app.handleAppDied();
assertFalse(mTask.hasChild());
assertFalse(mStack.hasChild());
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 d7baf8d05bd6..7adceade0b9b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -129,36 +129,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
}
@Test
- public void testGetAnimationTargets_noHierarchicalAnimations() {
- WindowManagerService.sHierarchicalAnimations = false;
-
- // [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (opening, invisible)
- // +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, visible)
- final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(stack1);
- activity1.setVisible(false);
- activity1.mVisibleRequested = true;
-
- final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(stack2);
-
- final ArraySet<ActivityRecord> opening = new ArraySet<>();
- opening.add(activity1);
- final ArraySet<ActivityRecord> closing = new ArraySet<>();
- closing.add(activity2);
-
- // Don't promote when the flag is disabled.
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity2}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
- }
-
- @Test
public void testGetAnimationTargets_visibilityAlreadyUpdated() {
// [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (opening, visible)
// +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, invisible)
@@ -177,17 +147,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// No animation, since visibility of the opening and closing apps are already updated
// outside of AppTransition framework.
- WindowManagerService.sHierarchicalAnimations = false;
- assertEquals(
- new ArraySet<>(),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
-
- WindowManagerService.sHierarchicalAnimations = true;
assertEquals(
new ArraySet<>(),
AppTransitionController.getAnimationTargets(
@@ -221,13 +180,12 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// The visibility are already updated, but since forced transition is requested, it will
// be included.
- WindowManagerService.sHierarchicalAnimations = false;
assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1}),
+ new ArraySet<>(new WindowContainer[]{activity1.getStack()}),
AppTransitionController.getAnimationTargets(
opening, closing, true /* visible */));
assertEquals(
- new ArraySet<>(new WindowContainer[]{activity2}),
+ new ArraySet<>(new WindowContainer[]{activity2.getStack()}),
AppTransitionController.getAnimationTargets(
opening, closing, false /* visible */));
}
@@ -247,13 +205,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// Animate closing apps even if it's not visible when it is exiting before we had a chance
// to play the transition animation.
- WindowManagerService.sHierarchicalAnimations = false;
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity}),
- AppTransitionController.getAnimationTargets(
- new ArraySet<>(), closing, false /* visible */));
-
- WindowManagerService.sHierarchicalAnimations = true;
assertEquals(
new ArraySet<>(new WindowContainer[]{stack}),
AppTransitionController.getAnimationTargets(
@@ -292,17 +243,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// Animate opening apps even if it's already visible in case its windows are being replaced.
// Don't animate closing apps if it's already invisible even though its windows are being
// replaced.
- WindowManagerService.sHierarchicalAnimations = false;
- assertEquals(
- new ArraySet<>(new WindowContainer[]{activity1}),
- AppTransitionController.getAnimationTargets(
- opening, closing, true /* visible */));
- assertEquals(
- new ArraySet<>(new WindowContainer[]{}),
- AppTransitionController.getAnimationTargets(
- opening, closing, false /* visible */));
-
- WindowManagerService.sHierarchicalAnimations = true;
assertEquals(
new ArraySet<>(new WindowContainer[]{stack1}),
AppTransitionController.getAnimationTargets(
@@ -315,8 +255,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_openingClosingInDifferentTask() {
- WindowManagerService.sHierarchicalAnimations = true;
-
// [DisplayContent] -+- [TaskStack1] - [Task1] -+- [ActivityRecord1] (opening, invisible)
// | +- [ActivityRecord2] (invisible)
// |
@@ -361,8 +299,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_openingClosingInSameTask() {
- WindowManagerService.sHierarchicalAnimations = true;
-
// [DisplayContent] - [TaskStack] - [Task] -+- [ActivityRecord1] (opening, invisible)
// +- [ActivityRecord2] (closing, visible)
final Task stack = createTaskStackOnDisplay(mDisplayContent);
@@ -393,8 +329,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_animateOnlyTranslucentApp() {
- WindowManagerService.sHierarchicalAnimations = true;
-
// [DisplayContent] -+- [TaskStack1] - [Task1] -+- [ActivityRecord1] (opening, invisible)
// | +- [ActivityRecord2] (visible)
// |
@@ -439,8 +373,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_animateTranslucentAndOpaqueApps() {
- WindowManagerService.sHierarchicalAnimations = true;
-
// [DisplayContent] -+- [TaskStack1] - [Task1] -+- [ActivityRecord1] (opening, invisible)
// | +- [ActivityRecord2] (opening, invisible)
// |
@@ -489,8 +421,6 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_stackContainsMultipleTasks() {
- WindowManagerService.sHierarchicalAnimations = true;
-
// [DisplayContent] - [TaskStack] -+- [Task1] - [ActivityRecord1] (opening, invisible)
// +- [Task2] - [ActivityRecord2] (closing, visible)
final Task stack = createTaskStackOnDisplay(mDisplayContent);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
index bcd937151046..5828d02948a1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ConfigurationContainerTests.java
@@ -33,6 +33,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.content.res.Configuration;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
@@ -324,6 +325,47 @@ public class ConfigurationContainerTests {
assertEquals(100, listener.mOverrideConfiguration.smallestScreenWidthDp);
}
+ @Test
+ public void testSetMaxBoundsByHierarchy() {
+ final TestConfigurationContainer root =
+ new TestConfigurationContainer(true /* providesMaxBounds */);
+ final Rect bounds = new Rect(0, 0, 10, 10);
+ final TestConfigurationContainer child = new TestConfigurationContainer();
+ root.addChild(child);
+
+ root.setBounds(bounds);
+
+ assertEquals(bounds, root.getBounds());
+ assertEquals(bounds, root.getConfiguration().windowConfiguration.getBounds());
+ assertEquals(bounds, child.getBounds());
+ assertEquals(bounds, child.getConfiguration().windowConfiguration.getBounds());
+
+ assertEquals(bounds, root.getMaxBounds());
+ assertEquals(bounds, root.getConfiguration().windowConfiguration.getMaxBounds());
+ assertEquals(bounds, child.getMaxBounds());
+ assertEquals(bounds, child.getConfiguration().windowConfiguration.getMaxBounds());
+ }
+
+ @Test
+ public void testSetBoundsNotOverrideMaxBounds() {
+ final TestConfigurationContainer root = new TestConfigurationContainer();
+ final Rect bounds = new Rect(0, 0, 10, 10);
+ final TestConfigurationContainer child = new TestConfigurationContainer();
+ root.addChild(child);
+
+ root.setBounds(bounds);
+
+ assertEquals(bounds, root.getBounds());
+ assertEquals(bounds, root.getConfiguration().windowConfiguration.getBounds());
+ assertEquals(bounds, child.getBounds());
+ assertEquals(bounds, child.getConfiguration().windowConfiguration.getBounds());
+
+ assertTrue(root.getMaxBounds().isEmpty());
+ assertTrue(root.getConfiguration().windowConfiguration.getMaxBounds().isEmpty());
+ assertTrue(child.getMaxBounds().isEmpty());
+ assertTrue(child.getConfiguration().windowConfiguration.getMaxBounds().isEmpty());
+ }
+
/**
* Contains minimal implementation of {@link ConfigurationContainer}'s abstract behavior needed
* for testing.
@@ -333,6 +375,14 @@ public class ConfigurationContainerTests {
private List<TestConfigurationContainer> mChildren = new ArrayList<>();
private TestConfigurationContainer mParent;
+ private boolean mProvidesMaxBounds = false;
+
+ TestConfigurationContainer() {}
+
+ TestConfigurationContainer(boolean providesMaxBounds) {
+ mProvidesMaxBounds = providesMaxBounds;
+ }
+
TestConfigurationContainer addChild(TestConfigurationContainer childContainer) {
final ConfigurationContainer oldParent = childContainer.getParent();
childContainer.mParent = this;
@@ -369,6 +419,11 @@ public class ConfigurationContainerTests {
protected ConfigurationContainer getParent() {
return mParent;
}
+
+ @Override
+ public boolean providesMaxBounds() {
+ return mProvidesMaxBounds;
+ }
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
index c8ed87db9d3e..e17601e99010 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -40,8 +41,10 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
+import android.graphics.Rect;
import android.os.Binder;
import android.platform.test.annotations.Presubmit;
+import android.view.SurfaceControl;
import com.google.android.collect.Lists;
@@ -63,7 +66,6 @@ import java.util.function.Function;
*/
@Presubmit
public class DisplayAreaTest {
-
@Rule
public SystemServicesTestRule mWmsRule = new SystemServicesTestRule();
@@ -379,6 +381,42 @@ public class DisplayAreaTest {
assertThat(result).isEqualTo(tda1);
}
+ @Test
+ public void testSetMaxBounds() {
+ final Rect parentBounds = new Rect(0, 0, 100, 100);
+ final Rect childBounds1 = new Rect(parentBounds.left, parentBounds.top,
+ parentBounds.right / 2, parentBounds.bottom);
+ final Rect childBounds2 = new Rect(parentBounds.right / 2, parentBounds.top,
+ parentBounds.right, parentBounds.bottom);
+ TestDisplayArea parentDa = new TestDisplayArea(mWms, parentBounds);
+ TestDisplayArea childDa1 = new TestDisplayArea(mWms, childBounds1);
+ TestDisplayArea childDa2 = new TestDisplayArea(mWms, childBounds2);
+ parentDa.addChild(childDa1, 0);
+ parentDa.addChild(childDa2, 1);
+
+ assertEquals(parentBounds, parentDa.getMaxBounds());
+ assertEquals(childBounds1, childDa1.getMaxBounds());
+ assertEquals(childBounds2, childDa2.getMaxBounds());
+
+ final WindowToken windowToken = createWindowToken(TYPE_APPLICATION);
+ childDa1.addChild(windowToken, 0);
+
+ assertEquals("DisplayArea's children must have the same max bounds as itself",
+ childBounds1, windowToken.getMaxBounds());
+ }
+
+ private static class TestDisplayArea<T extends WindowContainer> extends DisplayArea<T> {
+ private TestDisplayArea(WindowManagerService wms, Rect bounds) {
+ super(wms, ANY, "half display area");
+ setBounds(bounds);
+ }
+
+ @Override
+ SurfaceControl.Builder makeChildSurface(WindowContainer child) {
+ return new MockSurfaceControlBuilder();
+ }
+ }
+
private WindowToken createWindowToken(int type) {
return new WindowToken(mWmsRule.getWindowManagerService(), new Binder(),
type, false /* persist */, null /* displayContent */,
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 96ea64667f6e..edf15361e445 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1354,7 +1354,7 @@ public class DisplayContentTests extends WindowTestsBase {
assertFalse(displayRotation.updateRotationUnchecked(false));
// Rotation can be updated if the recents animation is finished.
- mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(false);
+ mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation();
assertTrue(displayRotation.updateRotationUnchecked(false));
// Rotation can be updated if the recents animation is animating but it is not on top, e.g.
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 695a0e3881ea..8bc8c0b1169f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -362,13 +362,14 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
assertFalse(homeActivity.hasFixedRotationTransform());
}
- @Test
- public void testClearFixedRotationLaunchingAppAfterCleanupAnimation() {
- unblockDisplayRotation(mDefaultDisplay);
+ private ActivityRecord prepareFixedRotationLaunchingAppWithRecentsAnim() {
final ActivityRecord homeActivity = createHomeActivity();
homeActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ // Add a window so it can be animated by the recents.
+ final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
+ activity.addWindow(win);
// Assume an activity is launching to different rotation.
mDefaultDisplay.setFixedRotationLaunchingApp(activity,
(mDefaultDisplay.getRotation() + 1) % 4);
@@ -379,6 +380,14 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
// Before the transition is done, the recents animation is triggered.
initializeRecentsAnimationController(mController, homeActivity);
assertFalse(homeActivity.hasFixedRotationTransform());
+ assertTrue(mController.isAnimatingTask(activity.getTask()));
+
+ return activity;
+ }
+
+ @Test
+ public void testClearFixedRotationLaunchingAppAfterCleanupAnimation() {
+ final ActivityRecord activity = prepareFixedRotationLaunchingAppWithRecentsAnim();
// Simulate giving up the swipe up gesture to keep the original activity as top.
mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
@@ -388,6 +397,21 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
}
@Test
+ public void testKeepFixedRotationWhenMovingRecentsToTop() {
+ final ActivityRecord activity = prepareFixedRotationLaunchingAppWithRecentsAnim();
+ // Assume a transition animation has started running before recents animation. Then the
+ // activity will receive onAnimationFinished that notifies app transition finished when
+ // removing the recents animation of task.
+ activity.getTask().getAnimationSources().add(activity);
+
+ // Simulate swiping to home/recents before the transition is done.
+ mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
+ // The rotation transform should be preserved. In real case, it will be cleared by the next
+ // move-to-top transition.
+ assertTrue(activity.hasFixedRotationTransform());
+ }
+
+ @Test
public void testWallpaperHasFixedRotationApplied() {
unblockDisplayRotation(mDefaultDisplay);
mWm.setRecentsAnimationController(mController);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 2e4c9ea747c5..d9d07d9beb2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -175,23 +175,30 @@ public class RootWindowContainerTests extends WindowTestsBase {
@Test
public void testForceStopPackage() {
final Task task = new ActivityTestsBase.StackBuilder(mWm.mRoot).build();
- final ActivityRecord activity1 = task.getTopMostActivity();
- final ActivityRecord activity2 =
- new ActivityTestsBase.ActivityBuilder(mWm.mAtmService).setStack(task).build();
- final WindowProcessController wpc = activity1.app;
+ final ActivityRecord activity = task.getTopMostActivity();
+ final WindowProcessController wpc = activity.app;
+ final ActivityRecord[] activities = {
+ activity,
+ new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+ .setStack(task).setUseProcess(wpc).build(),
+ new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+ .setStack(task).setUseProcess(wpc).build()
+ };
+ activities[0].detachFromProcess();
+ activities[1].finishing = true;
+ activities[1].destroyImmediately(true /* removeFromApp */, "test");
spyOn(wpc);
- activity1.app = null;
- activity2.setProcess(wpc);
doReturn(true).when(wpc).isRemoved();
mWm.mAtmService.mInternal.onForceStopPackage(wpc.mInfo.packageName, true /* doit */,
false /* evenPersistent */, wpc.mUserId);
// The activity without process should be removed.
- assertEquals(1, task.getChildCount());
+ assertEquals(2, task.getChildCount());
- mWm.mRoot.handleAppDied(wpc);
- // The activity with process should be removed because WindowProcessController#isRemoved.
+ wpc.handleAppDied();
+ // The activities with process should be removed because WindowProcessController#isRemoved.
assertFalse(task.hasChild());
+ assertFalse(wpc.hasActivities());
}
}
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 e8a4e90b1aa1..75ed928b08a0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -79,6 +79,16 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
}
@Test
+ public void testRemoveFinishingInvisibleActivityFromUnknown() {
+ final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
+ mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
+ activity.finishing = true;
+ activity.mVisibleRequested = true;
+ activity.setVisibility(false, false);
+ assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
+ }
+
+ @Test
public void testAppRemoved() {
final ActivityRecord activity = WindowTestUtils.createTestActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
index 6861ad1b2e2d..4986d1883307 100644
--- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java
+++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
@@ -307,7 +307,7 @@ public class AppTimeLimitController {
}
} else {
if (mActives > mObserved.length) {
- // Try to get to a sane state and log the issue
+ // Try to get to a valid state and log the issue
mActives = mObserved.length;
final UserData user = mUserRef.get();
if (user == null) return;
@@ -334,7 +334,7 @@ public class AppTimeLimitController {
cancelCheckTimeoutLocked(this);
} else {
if (mActives < 0) {
- // Try to get to a sane state and log the issue
+ // Try to get to a valid state and log the issue
mActives = 0;
final UserData user = mUserRef.get();
if (user == null) return;
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 9b18ec644ceb..2fd6c4249f99 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -92,6 +92,7 @@ import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.SystemService.TargetUser;
import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
import java.io.BufferedReader;
@@ -291,27 +292,26 @@ public class UsageStatsService extends SystemService implements
}
@Override
- public void onStartUser(UserInfo userInfo) {
+ public void onUserStarting(@NonNull TargetUser user) {
// Create an entry in the user state map to indicate that the user has been started but
// not necessarily unlocked. This will ensure that reported events are flushed to disk
// event if the user is never unlocked (following the logic in #flushToDiskLocked)
- mUserState.put(userInfo.id, null);
- super.onStartUser(userInfo);
+ mUserState.put(user.getUserIdentifier(), null);
}
@Override
- public void onUnlockUser(@NonNull UserInfo userInfo) {
- mHandler.obtainMessage(MSG_UNLOCKED_USER, userInfo.id, 0).sendToTarget();
- super.onUnlockUser(userInfo);
+ public void onUserUnlocking(@NonNull TargetUser user) {
+ mHandler.obtainMessage(MSG_UNLOCKED_USER, user.getUserIdentifier(), 0).sendToTarget();
}
@Override
- public void onStopUser(@NonNull UserInfo userInfo) {
+ public void onUserStopping(@NonNull TargetUser user) {
+ final UserInfo userInfo = user.getUserInfo();
+
synchronized (mLock) {
// User was started but never unlocked so no need to report a user stopped event
if (!mUserUnlockedStates.get(userInfo.id)) {
persistPendingEventsLocked(userInfo.id);
- super.onStopUser(userInfo);
return;
}
@@ -326,7 +326,6 @@ public class UsageStatsService extends SystemService implements
mUserUnlockedStates.put(userInfo.id, false);
mUserState.put(userInfo.id, null); // release the service (mainly for GC)
}
- super.onStopUser(userInfo);
}
private void onUserUnlocked(int userId) {
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 5239d976e66f..22629dd52608 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -64,7 +64,7 @@ public final class UsbAlsaManager {
private UsbAlsaDevice mSelectedDevice;
//
- // Device Blacklist
+ // Device Denylist
//
// This exists due to problems with Sony game controllers which present as an audio device
// even if no headset is connected and have no way to set the volume on the unit.
@@ -73,31 +73,31 @@ public final class UsbAlsaManager {
private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT1 = 0x05C4;
private static final int USB_PRODUCTID_PS4CONTROLLER_ZCT2 = 0x09CC;
- private static final int USB_BLACKLIST_OUTPUT = 0x0001;
- private static final int USB_BLACKLIST_INPUT = 0x0002;
+ private static final int USB_DENYLIST_OUTPUT = 0x0001;
+ private static final int USB_DENYLIST_INPUT = 0x0002;
- private static class BlackListEntry {
+ private static class DenyListEntry {
final int mVendorId;
final int mProductId;
final int mFlags;
- BlackListEntry(int vendorId, int productId, int flags) {
+ DenyListEntry(int vendorId, int productId, int flags) {
mVendorId = vendorId;
mProductId = productId;
mFlags = flags;
}
}
- static final List<BlackListEntry> sDeviceBlacklist = Arrays.asList(
- new BlackListEntry(USB_VENDORID_SONY,
+ static final List<DenyListEntry> sDeviceDenylist = Arrays.asList(
+ new DenyListEntry(USB_VENDORID_SONY,
USB_PRODUCTID_PS4CONTROLLER_ZCT1,
- USB_BLACKLIST_OUTPUT),
- new BlackListEntry(USB_VENDORID_SONY,
+ USB_DENYLIST_OUTPUT),
+ new DenyListEntry(USB_VENDORID_SONY,
USB_PRODUCTID_PS4CONTROLLER_ZCT2,
- USB_BLACKLIST_OUTPUT));
+ USB_DENYLIST_OUTPUT));
- private static boolean isDeviceBlacklisted(int vendorId, int productId, int flags) {
- for (BlackListEntry entry : sDeviceBlacklist) {
+ private static boolean isDeviceDenylisted(int vendorId, int productId, int flags) {
+ for (DenyListEntry entry : sDeviceDenylist) {
if (entry.mVendorId == vendorId && entry.mProductId == productId) {
// see if the type flag is set
return (entry.mFlags & flags) != 0;
@@ -226,11 +226,11 @@ public final class UsbAlsaManager {
// Add it to the devices list
boolean hasInput = parser.hasInput()
- && !isDeviceBlacklisted(usbDevice.getVendorId(), usbDevice.getProductId(),
- USB_BLACKLIST_INPUT);
+ && !isDeviceDenylisted(usbDevice.getVendorId(), usbDevice.getProductId(),
+ USB_DENYLIST_INPUT);
boolean hasOutput = parser.hasOutput()
- && !isDeviceBlacklisted(usbDevice.getVendorId(), usbDevice.getProductId(),
- USB_BLACKLIST_OUTPUT);
+ && !isDeviceDenylisted(usbDevice.getVendorId(), usbDevice.getProductId(),
+ USB_DENYLIST_OUTPUT);
if (DEBUG) {
Slog.d(TAG, "hasInput: " + hasInput + " hasOutput:" + hasOutput);
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 6cf0eecc6352..2269e1d070b1 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -201,22 +201,22 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
private String[] mAccessoryStrings;
private final UEventObserver mUEventObserver;
- private static Set<Integer> sBlackListedInterfaces;
+ private static Set<Integer> sDenyInterfaces;
private HashMap<Long, FileDescriptor> mControlFds;
static {
- sBlackListedInterfaces = new HashSet<>();
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_AUDIO);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_COMM);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_HID);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_PRINTER);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_MASS_STORAGE);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_HUB);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CDC_DATA);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CSCID);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_CONTENT_SEC);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_VIDEO);
- sBlackListedInterfaces.add(UsbConstants.USB_CLASS_WIRELESS_CONTROLLER);
+ sDenyInterfaces = new HashSet<>();
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_AUDIO);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_COMM);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_HID);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_PRINTER);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_MASS_STORAGE);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_HUB);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_CDC_DATA);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_CSCID);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_CONTENT_SEC);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_VIDEO);
+ sDenyInterfaces.add(UsbConstants.USB_CLASS_WIRELESS_CONTROLLER);
}
/*
@@ -960,7 +960,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
while (interfaceCount >= 0) {
UsbInterface intrface = config.getInterface(interfaceCount);
interfaceCount--;
- if (sBlackListedInterfaces.contains(intrface.getInterfaceClass())) {
+ if (sDenyInterfaces.contains(intrface.getInterfaceClass())) {
mHideUsbNotification = true;
break;
}
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 140a95d61100..f33001c9241e 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -62,7 +62,7 @@ public class UsbHostManager {
private final Context mContext;
// USB busses to exclude from USB host support
- private final String[] mHostBlacklist;
+ private final String[] mHostDenyList;
private final UsbAlsaManager mUsbAlsaManager;
private final UsbPermissionManager mPermissionManager;
@@ -235,8 +235,8 @@ public class UsbHostManager {
UsbPermissionManager permissionManager) {
mContext = context;
- mHostBlacklist = context.getResources().getStringArray(
- com.android.internal.R.array.config_usbHostBlacklist);
+ mHostDenyList = context.getResources().getStringArray(
+ com.android.internal.R.array.config_usbHostDenylist);
mUsbAlsaManager = alsaManager;
mPermissionManager = permissionManager;
String deviceConnectionHandler = context.getResources().getString(
@@ -271,10 +271,10 @@ public class UsbHostManager {
}
}
- private boolean isBlackListed(String deviceAddress) {
- int count = mHostBlacklist.length;
+ private boolean isDenyListed(String deviceAddress) {
+ int count = mHostDenyList.length;
for (int i = 0; i < count; i++) {
- if (deviceAddress.startsWith(mHostBlacklist[i])) {
+ if (deviceAddress.startsWith(mHostDenyList[i])) {
return true;
}
}
@@ -282,11 +282,11 @@ public class UsbHostManager {
}
/* returns true if the USB device should not be accessible by applications */
- private boolean isBlackListed(int clazz, int subClass) {
- // blacklist hubs
+ private boolean isDenyListed(int clazz, int subClass) {
+ // deny hubs
if (clazz == UsbConstants.USB_CLASS_HUB) return true;
- // blacklist HID boot devices (mouse and keyboard)
+ // deny HID boot devices (mouse and keyboard)
return clazz == UsbConstants.USB_CLASS_HID
&& subClass == UsbConstants.USB_INTERFACE_SUBCLASS_BOOT;
@@ -355,23 +355,23 @@ public class UsbHostManager {
Slog.d(TAG, "usbDeviceAdded(" + deviceAddress + ") - start");
}
- if (isBlackListed(deviceAddress)) {
+ if (isDenyListed(deviceAddress)) {
if (DEBUG) {
- Slog.d(TAG, "device address is black listed");
+ Slog.d(TAG, "device address is Deny listed");
}
return false;
}
- if (isBlackListed(deviceClass, deviceSubclass)) {
+ if (isDenyListed(deviceClass, deviceSubclass)) {
if (DEBUG) {
- Slog.d(TAG, "device class is black listed");
+ Slog.d(TAG, "device class is deny listed");
}
return false;
}
UsbDescriptorParser parser = new UsbDescriptorParser(deviceAddress, descriptors);
if (deviceClass == UsbConstants.USB_CLASS_PER_INTERFACE
- && !checkUsbInterfacesBlackListed(parser)) {
+ && !checkUsbInterfacesDenyListed(parser)) {
return false;
}
@@ -491,12 +491,12 @@ public class UsbHostManager {
public ParcelFileDescriptor openDevice(String deviceAddress,
UsbUserPermissionManager permissions, String packageName, int pid, int uid) {
synchronized (mLock) {
- if (isBlackListed(deviceAddress)) {
+ if (isDenyListed(deviceAddress)) {
throw new SecurityException("USB device is on a restricted bus");
}
UsbDevice device = mDevices.get(deviceAddress);
if (device == null) {
- // if it is not in mDevices, it either does not exist or is blacklisted
+ // if it is not in mDevices, it either does not exist or is denylisted
throw new IllegalArgumentException(
"device " + deviceAddress + " does not exist or is restricted");
}
@@ -554,23 +554,23 @@ public class UsbHostManager {
}
}
- private boolean checkUsbInterfacesBlackListed(UsbDescriptorParser parser) {
+ private boolean checkUsbInterfacesDenyListed(UsbDescriptorParser parser) {
// Device class needs to be obtained through the device interface. Ignore device only
- // if ALL interfaces are black-listed.
+ // if ALL interfaces are deny-listed.
boolean shouldIgnoreDevice = false;
for (UsbDescriptor descriptor: parser.getDescriptors()) {
if (!(descriptor instanceof UsbInterfaceDescriptor)) {
continue;
}
UsbInterfaceDescriptor iface = (UsbInterfaceDescriptor) descriptor;
- shouldIgnoreDevice = isBlackListed(iface.getUsbClass(), iface.getUsbSubclass());
+ shouldIgnoreDevice = isDenyListed(iface.getUsbClass(), iface.getUsbSubclass());
if (!shouldIgnoreDevice) {
break;
}
}
if (shouldIgnoreDevice) {
if (DEBUG) {
- Slog.d(TAG, "usb interface class is black listed");
+ Slog.d(TAG, "usb interface class is deny listed");
}
return false;
}
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index 1025bf5d67b0..ec7d4bd0d8c0 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -922,7 +922,7 @@ public class UsbPortManager {
contaminantDetectionStatus);
mPorts.put(portId, portInfo);
} else {
- // Sanity check that ports aren't changing definition out from under us.
+ // Validate that ports aren't changing definition out from under us.
if (supportedModes != portInfo.mUsbPort.getSupportedModes()) {
logAndPrint(Log.WARN, pw, "Ignoring inconsistent list of supported modes from "
+ "USB port driver (should be immutable): "
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 6c13cd799bc2..0ea84da54b60 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -221,14 +221,6 @@ public class SoundTriggerService extends SystemService {
}
}
- @Override
- public void onStartUser(int userHandle) {
- }
-
- @Override
- public void onSwitchUser(int userHandle) {
- }
-
private synchronized void initSoundTriggerHelper() {
if (mSoundTriggerHelper == null) {
mSoundTriggerHelper = new SoundTriggerHelper(mContext);
@@ -697,7 +689,7 @@ public class SoundTriggerService extends SystemService {
synchronized (mLock) {
ModuleProperties properties = mSoundTriggerHelper.getModuleProperties();
sEventLogger.log(new SoundTriggerLogger.StringEvent(
- "getModuleProperties(): " + properties.toString()));
+ "getModuleProperties(): " + properties));
return properties;
}
}
@@ -1289,27 +1281,25 @@ public class SoundTriggerService extends SystemService {
attributesBuilder.setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD);
AudioAttributes attributes = attributesBuilder.build();
- // Use same AudioFormat processing as in RecognitionEvent.fromParcel
AudioFormat originalFormat = event.getCaptureFormat();
- AudioFormat captureFormat = (new AudioFormat.Builder())
- .setChannelMask(originalFormat.getChannelMask())
- .setEncoding(originalFormat.getEncoding())
- .setSampleRate(originalFormat.getSampleRate())
- .build();
-
- int bufferSize = AudioRecord.getMinBufferSize(
- captureFormat.getSampleRate() == AudioFormat.SAMPLE_RATE_UNSPECIFIED
- ? AudioFormat.SAMPLE_RATE_HZ_MAX
- : captureFormat.getSampleRate(),
- captureFormat.getChannelCount() == 2
- ? AudioFormat.CHANNEL_IN_STEREO
- : AudioFormat.CHANNEL_IN_MONO,
- captureFormat.getEncoding());
sEventLogger.log(new SoundTriggerLogger.StringEvent("createAudioRecordForEvent"));
- return new AudioRecord(attributes, captureFormat, bufferSize,
- event.getCaptureSession());
+ try {
+ return (new AudioRecord.Builder())
+ .setAudioAttributes(attributes)
+ .setAudioFormat((new AudioFormat.Builder())
+ .setChannelMask(originalFormat.getChannelMask())
+ .setEncoding(originalFormat.getEncoding())
+ .setSampleRate(originalFormat.getSampleRate())
+ .build())
+ .setSessionId(event.getCaptureSession())
+ .build();
+ } catch (IllegalArgumentException | UnsupportedOperationException e) {
+ Slog.w(TAG, mPuuid + ": createAudioRecordForEvent(" + event
+ + "), failed to create AudioRecord");
+ return null;
+ }
}
@Override
@@ -1339,8 +1329,10 @@ public class SoundTriggerService extends SystemService {
// Currently we need to start and release the audio record to reset
// the DSP even if we don't want to process the event
- capturedData.startRecording();
- capturedData.release();
+ if (capturedData != null) {
+ capturedData.startRecording();
+ capturedData.release();
+ }
}
}));
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 9621f68f9d6c..0f898f8e679e 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -189,10 +189,10 @@ public class VoiceInteractionManagerService extends SystemService {
}
@Override
- public void onSwitchUser(@NonNull UserInfo from, @NonNull UserInfo to) {
+ public void onUserSwitching(@Nullable TargetUser from, @NonNull TargetUser to) {
if (DEBUG_USER) Slog.d(TAG, "onSwitchUser(" + from + " > " + to + ")");
- mServiceStub.switchUser(to.id);
+ mServiceStub.switchUser(to.getUserIdentifier());
}
class LocalService extends VoiceInteractionManagerInternal {
diff --git a/telecomm/TEST_MAPPING b/telecomm/TEST_MAPPING
index d58566673eec..c9903f9fa901 100644
--- a/telecomm/TEST_MAPPING
+++ b/telecomm/TEST_MAPPING
@@ -23,6 +23,14 @@
"exclude-annotation": "androidx.test.filters.FlakyTest"
}
]
+ },
+ {
+ "name": "CtsTelecomTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
}
]
}
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 3365ab740cde..0469fa56e648 100755
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -462,15 +462,15 @@ public final class Call {
/**
* Call supports adding participants to the call via
- * {@link #addConferenceParticipants(List)}.
- * @hide
+ * {@link #addConferenceParticipants(List)}. Once participants are added, the call becomes
+ * an adhoc conference call ({@link #PROPERTY_IS_ADHOC_CONFERENCE}).
*/
public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
/**
* When set for a call, indicates that this {@code Call} can be transferred to another
* number.
- * Call supports the blind and assured call transfer feature.
+ * Call supports the confirmed and unconfirmed call transfer feature.
*
* @hide
*/
@@ -599,8 +599,11 @@ public final class Call {
/**
* Indicates that the call is an adhoc conference call. This property can be set for both
- * incoming and outgoing calls.
- * @hide
+ * incoming and outgoing calls. An adhoc conference call is formed using
+ * {@link #addConferenceParticipants(List)},
+ * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}, or
+ * {@link TelecomManager#startConference(List, Bundle)}, rather than by merging existing
+ * call using {@link #conference(Call)}.
*/
public static final int PROPERTY_IS_ADHOC_CONFERENCE = 0x00002000;
@@ -1593,8 +1596,8 @@ public final class Call {
* Instructs this {@code Call} to be transferred to another number.
*
* @param targetNumber The address to which the call will be transferred.
- * @param isConfirmationRequired if {@code true} it will initiate ASSURED transfer,
- * if {@code false}, it will initiate BLIND transfer.
+ * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer,
+ * if {@code false}, it will initiate an unconfirmed transfer.
*
* @hide
*/
@@ -1775,7 +1778,6 @@ public final class Call {
* See {@link Details#CAPABILITY_ADD_PARTICIPANT}.
*
* @param participants participants to be pulled to existing call.
- * @hide
*/
public void addConferenceParticipants(@NonNull List<Uri> participants) {
mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants);
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index d9605522b3b0..39c3ff9e8839 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -181,8 +181,8 @@ public abstract class Conference extends Conferenceable {
/**
* Returns whether this conference is requesting that the system play a ringback tone
- * on its behalf.
- * @hide
+ * on its behalf. A ringback tone may be played when an outgoing conference is in the process of
+ * connecting to give the user an audible indication of that process.
*/
public final boolean isRingbackRequested() {
return mRingbackRequested;
@@ -329,7 +329,6 @@ public abstract class Conference extends Conferenceable {
/**
* Notifies the {@link Conference} of a request to add a new participants to the conference call
* @param participants that will be added to this conference call
- * @hide
*/
public void onAddConferenceParticipants(@NonNull List<Uri> participants) {}
@@ -340,7 +339,6 @@ public abstract class Conference extends Conferenceable {
* the default dialer's {@link InCallService}.
*
* @param videoState The video state in which to answer the connection.
- * @hide
*/
public void onAnswer(int videoState) {}
@@ -360,7 +358,6 @@ public abstract class Conference extends Conferenceable {
* a request to reject.
* For managed {@link ConnectionService}s, this will be called when the user rejects a call via
* the default dialer's {@link InCallService}.
- * @hide
*/
public void onReject() {}
@@ -380,7 +377,6 @@ public abstract class Conference extends Conferenceable {
/**
* Sets state to be ringing.
- * @hide
*/
public final void setRinging() {
setState(Connection.STATE_RINGING);
@@ -506,7 +502,6 @@ public abstract class Conference extends Conferenceable {
* that do not play a ringback tone themselves in the conference's audio stream.
*
* @param ringback Whether the ringback tone is to be played.
- * @hide
*/
public final void setRingbackRequested(boolean ringback) {
if (mRingbackRequested != ringback) {
@@ -773,7 +768,6 @@ public abstract class Conference extends Conferenceable {
*
* @param disconnectCause The disconnect cause, ({@see android.telecomm.DisconnectCause}).
* @return A {@code Conference} which indicates failure.
- * @hide
*/
public @NonNull static Conference createFailedConference(
@NonNull DisconnectCause disconnectCause, @NonNull PhoneAccountHandle phoneAccount) {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index fa9909547fc4..00b711643fe6 100755
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -383,15 +383,17 @@ public abstract class Connection extends Conferenceable {
/**
* When set, indicates that this {@link Connection} supports initiation of a conference call
- * by directly adding participants using {@link #onAddConferenceParticipants(List)}.
- * @hide
+ * by directly adding participants using {@link #onAddConferenceParticipants(List)}. When
+ * participants are added to a {@link Connection}, it will be replaced by a {@link Conference}
+ * instance with {@link #PROPERTY_IS_ADHOC_CONFERENCE} set to indicate that it is an adhoc
+ * conference call.
*/
public static final int CAPABILITY_ADD_PARTICIPANT = 0x04000000;
/**
* Indicates that this {@code Connection} can be transferred to another
* number.
- * Connection supports the blind and assured call transfer feature.
+ * Connection supports the confirmed and unconfirmed call transfer feature.
* @hide
*/
public static final int CAPABILITY_TRANSFER = 0x08000000;
@@ -526,10 +528,9 @@ public abstract class Connection extends Conferenceable {
public static final int PROPERTY_REMOTELY_HOSTED = 1 << 11;
/**
- * Set by the framework to indicate that it is an adhoc conference call.
+ * Set by the framework to indicate that a call is an adhoc conference call.
* <p>
- * This is used for Outgoing and incoming conference calls.
- * @hide
+ * This is used for outgoing and incoming conference calls.
*/
public static final int PROPERTY_IS_ADHOC_CONFERENCE = 1 << 12;
@@ -3034,7 +3035,6 @@ public abstract class Connection extends Conferenceable {
* Supports initiation of a conference call by directly adding participants to an ongoing call.
*
* @param participants with which conference call will be formed.
- * @hide
*/
public void onAddConferenceParticipants(@NonNull List<Uri> participants) {}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 56cba1d3f913..3646647e9734 100755
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -1880,6 +1880,7 @@ public abstract class ConnectionService extends Service {
mConferenceById.put(callId, conference);
mIdByConference.put(conference, callId);
+
conference.addListener(mConferenceListener);
ParcelableConference parcelableConference = new ParcelableConference.Builder(
request.getAccountHandle(), conference.getState())
@@ -2678,15 +2679,15 @@ public abstract class ConnectionService extends Service {
return null;
}
/**
- * Create a {@code Connection} given an incoming request. This is used to attach to existing
- * incoming conference call.
+ * Create a {@code Conference} given an incoming request. This is used to attach to an incoming
+ * conference call initiated via
+ * {@link TelecomManager#addNewIncomingConference(PhoneAccountHandle, Bundle)}.
*
* @param connectionManagerPhoneAccount See description at
* {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
- * @param request Details about the incoming call.
- * @return The {@code Connection} object to satisfy this call, or {@code null} to
+ * @param request Details about the incoming conference call.
+ * @return The {@code Conference} object to satisfy this call, or {@code null} to
* not handle the call.
- * @hide
*/
public @Nullable Conference onCreateIncomingConference(
@Nullable PhoneAccountHandle connectionManagerPhoneAccount,
@@ -2771,7 +2772,6 @@ public abstract class ConnectionService extends Service {
* @param connectionManagerPhoneAccount See description at
* {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
* @param request The incoming connection request.
- * @hide
*/
public void onCreateIncomingConferenceFailed(
@Nullable PhoneAccountHandle connectionManagerPhoneAccount,
@@ -2792,7 +2792,6 @@ public abstract class ConnectionService extends Service {
* @param connectionManagerPhoneAccount See description at
* {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}.
* @param request The outgoing connection request.
- * @hide
*/
public void onCreateOutgoingConferenceFailed(
@Nullable PhoneAccountHandle connectionManagerPhoneAccount,
@@ -2841,7 +2840,8 @@ public abstract class ConnectionService extends Service {
/**
* Create a {@code Conference} given an outgoing request. This is used to initiate new
- * outgoing conference call.
+ * outgoing conference call requested via
+ * {@link TelecomManager#startConference(List, Bundle)}.
*
* @param connectionManagerPhoneAccount The connection manager account to use for managing
* this call.
@@ -2861,7 +2861,6 @@ public abstract class ConnectionService extends Service {
* @param request Details about the outgoing call.
* @return The {@code Conference} object to satisfy this call, or the result of an invocation
* of {@link Connection#createFailedConnection(DisconnectCause)} to not handle the call.
- * @hide
*/
public @Nullable Conference onCreateOutgoingConference(
@Nullable PhoneAccountHandle connectionManagerPhoneAccount,
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index dd6c15311651..ab35affe9099 100755
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -107,8 +107,8 @@ public final class InCallAdapter {
*
* @param callId The identifier of the call to transfer.
* @param targetNumber The address to transfer to.
- * @param isConfirmationRequired if {@code true} it will initiate ASSURED transfer,
- * if {@code false}, it will initiate BLIND transfer.
+ * @param isConfirmationRequired if {@code true} it will initiate a confirmed transfer,
+ * if {@code false}, it will initiate unconfirmed transfer.
*/
public void transferCall(@NonNull String callId, @NonNull Uri targetNumber,
boolean isConfirmationRequired) {
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 8eebbeda9e83..bcb1736f416e 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1867,11 +1867,13 @@ public class TelecomManager {
/**
* Registers a new incoming conference. A {@link ConnectionService} should invoke this method
- * when it has an incoming conference. For managed {@link ConnectionService}s, the specified
- * {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
- * the user must have enabled the corresponding {@link PhoneAccount}. This can be checked using
- * {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
- * {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call.
+ * when it has an incoming conference. An incoming {@link Conference} is an adhoc conference
+ * call initiated on another device which the user is being invited to join in. For managed
+ * {@link ConnectionService}s, the specified {@link PhoneAccountHandle} must have been
+ * registered with {@link #registerPhoneAccount} and the user must have enabled the
+ * corresponding {@link PhoneAccount}. This can be checked using
+ * {@link #getPhoneAccount(PhoneAccountHandle)}. Self-managed {@link ConnectionService}s must
+ * have {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call.
* <p>
* The incoming conference you are adding is assumed to have a video state of
* {@link VideoProfile#STATE_AUDIO_ONLY}, unless the extra value
@@ -1879,8 +1881,9 @@ public class TelecomManager {
* <p>
* Once invoked, this method will cause the system to bind to the {@link ConnectionService}
* associated with the {@link PhoneAccountHandle} and request additional information about the
- * call (See {@link ConnectionService#onCreateIncomingConference}) before starting the incoming
- * call UI.
+ * call (See
+ * {@link ConnectionService#onCreateIncomingConference(PhoneAccountHandle, ConnectionRequest)})
+ * before starting the incoming call UI.
* <p>
* For a managed {@link ConnectionService}, a {@link SecurityException} will be thrown if either
* the {@link PhoneAccountHandle} does not correspond to a registered {@link PhoneAccount} or
@@ -1890,7 +1893,6 @@ public class TelecomManager {
* {@link #registerPhoneAccount}.
* @param extras A bundle that will be passed through to
* {@link ConnectionService#onCreateIncomingConference}.
- * @hide
*/
public void addNewIncomingConference(@NonNull PhoneAccountHandle phoneAccount,
@NonNull Bundle extras) {
@@ -2111,8 +2113,8 @@ public class TelecomManager {
/**
- * Place a new conference call with the provided participants using the system telecom service
- * This method doesn't support placing of emergency calls.
+ * Place a new adhoc conference call with the provided participants using the system telecom
+ * service. This method doesn't support placing of emergency calls.
*
* An adhoc conference call is established by providing a list of addresses to
* {@code TelecomManager#startConference(List<Uri>, int videoState)} where the
@@ -2130,7 +2132,6 @@ public class TelecomManager {
*
* @param participants List of participants to start conference with
* @param extras Bundle of extras to use with the call
- * @hide
*/
@RequiresPermission(android.Manifest.permission.CALL_PHONE)
public void startConference(@NonNull List<Uri> participants,
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index dee5a98e33e9..7c6f1df972f3 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -326,6 +326,8 @@ interface ITelecomService {
*/
void handleCallIntent(in Intent intent, in String callingPackageProxy);
+ void cleanupStuckCalls();
+
void setTestDefaultCallRedirectionApp(String packageName);
void setTestPhoneAcctSuggestionComponent(String flattenedComponentName);
diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt
index ef94c7677a17..09c16595e2c7 100644
--- a/telephony/api/system-current.txt
+++ b/telephony/api/system-current.txt
@@ -316,6 +316,7 @@ package android.telephony {
method @Deprecated public int getDataConnectionApnTypeBitMask();
method @Deprecated public int getDataConnectionFailCause();
method @Deprecated public int getDataConnectionState();
+ method public int getId();
}
public final class PreciseDisconnectCause {
diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
index 48794cb37853..502bfa3749eb 100644
--- a/telephony/common/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -47,7 +47,7 @@ public final class LocationAccessPolicy {
ALLOWED,
/**
* Indicates that the denial is due to a transient device state
- * (e.g. app-ops, location master switch)
+ * (e.g. app-ops, location main switch)
*/
DENIED_SOFT,
/**
@@ -316,7 +316,7 @@ public final class LocationAccessPolicy {
return LocationPermissionResult.ALLOWED;
}
- // Check the system-wide requirements. If the location master switch is off or
+ // Check the system-wide requirements. If the location main switch is off or
// the app's profile isn't in foreground, return a soft denial.
if (!checkSystemLocationAccess(context, query.callingUid, query.callingPid)) {
return LocationPermissionResult.DENIED_SOFT;
@@ -340,7 +340,7 @@ public final class LocationAccessPolicy {
}
// At this point, we're out of location checks to do. If the app bypassed all the previous
- // ones due to the SDK grandfathering schemes, allow it access.
+ // ones due to the SDK backwards compatibility schemes, allow it access.
return LocationPermissionResult.ALLOWED;
}
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 71a1964210b0..0c463949b14a 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -74,7 +74,8 @@ public final class TelephonyPermissions {
* <li>return false: if the caller lacks all of these permissions and doesn't support runtime
* permissions. This implies that the user revoked the ability to read phone state
* manually (via AppOps). In this case we can't throw as it would break app compatibility,
- * so we return false to indicate that the calling function should return dummy data.
+ * so we return false to indicate that the calling function should return placeholder
+ * data.
* </ul>
*
* <p>Note: for simplicity, this method always returns false for callers using legacy
@@ -119,7 +120,8 @@ public final class TelephonyPermissions {
* <li>return false: if the caller lacks all of these permissions and doesn't support runtime
* permissions. This implies that the user revoked the ability to read phone state
* manually (via AppOps). In this case we can't throw as it would break app compatibility,
- * so we return false to indicate that the calling function should return dummy data.
+ * so we return false to indicate that the calling function should return placeholder
+ * data.
* </ul>
*
* <p>Note: for simplicity, this method always returns false for callers using legacy
@@ -225,7 +227,7 @@ public final class TelephonyPermissions {
* <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
* permission. In this case the caller would expect to have access to the device
* identifiers so false is returned instead of throwing a SecurityException to indicate
- * the calling function should return dummy data.
+ * the calling function should return placeholder data.
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context,
@@ -249,7 +251,7 @@ public final class TelephonyPermissions {
* <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
* permission or carrier privileges. In this case the caller would expect to have access
* to the device identifiers so false is returned instead of throwing a SecurityException
- * to indicate the calling function should return dummy data.
+ * to indicate the calling function should return placeholder data.
* </ul>
*/
public static boolean checkCallingOrSelfReadDeviceIdentifiers(Context context, int subId,
@@ -271,7 +273,7 @@ public final class TelephonyPermissions {
* <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
* permission. In this case the caller would expect to have access to the device
* identifiers so false is returned instead of throwing a SecurityException to indicate
- * the calling function should return dummy data.
+ * the calling function should return placeholder data.
* </ul>
*/
public static boolean checkCallingOrSelfReadSubscriberIdentifiers(Context context, int subId,
@@ -295,7 +297,7 @@ public final class TelephonyPermissions {
* <li>return false: if the caller is targeting pre-Q and does have the READ_PHONE_STATE
* permission. In this case the caller would expect to have access to the device
* identifiers so false is returned instead of throwing a SecurityException to indicate
- * the calling function should return dummy data.
+ * the calling function should return placeholder data.
* </ul>
*/
private static boolean checkPrivilegedReadPermissionOrCarrierPrivilegePermission(
diff --git a/telephony/common/com/google/android/mms/pdu/PduComposer.java b/telephony/common/com/google/android/mms/pdu/PduComposer.java
index 5e1f556f4c4a..7af0d1b09eed 100644
--- a/telephony/common/com/google/android/mms/pdu/PduComposer.java
+++ b/telephony/common/com/google/android/mms/pdu/PduComposer.java
@@ -1051,7 +1051,7 @@ public class PduComposer {
}
if (dataLength != (attachment.getLength() - headerLength)) {
- throw new RuntimeException("BUG: Length sanity check failed");
+ throw new RuntimeException("BUG: Length correctness check failed");
}
mStack.pop();
diff --git a/telephony/common/com/google/android/mms/pdu/PduPersister.java b/telephony/common/com/google/android/mms/pdu/PduPersister.java
index fcd5b8ff57a8..b61ad3680c6c 100755
--- a/telephony/common/com/google/android/mms/pdu/PduPersister.java
+++ b/telephony/common/com/google/android/mms/pdu/PduPersister.java
@@ -72,7 +72,7 @@ public class PduPersister {
private static final boolean DEBUG = false;
private static final boolean LOCAL_LOGV = false;
- private static final long DUMMY_THREAD_ID = Long.MAX_VALUE;
+ private static final long PLACEHOLDER_THREAD_ID = Long.MAX_VALUE;
/**
* The uri of temporary drm objects.
@@ -1340,7 +1340,7 @@ public class PduPersister {
// Save parts first to avoid inconsistent message is loaded
// while saving the parts.
- long dummyId = System.currentTimeMillis(); // Dummy ID of the msg.
+ long placeholderId = System.currentTimeMillis(); // Placeholder ID of the msg.
// Figure out if this PDU is a text-only message
boolean textOnly = true;
@@ -1364,7 +1364,7 @@ public class PduPersister {
for (int i = 0; i < partsNum; i++) {
PduPart part = body.getPart(i);
messageSize += part.getDataLength();
- persistPart(part, dummyId, preOpenedFiles);
+ persistPart(part, placeholderId, preOpenedFiles);
// If we've got anything besides text/plain or SMIL part, then we've got
// an mms message with some other type of attachment.
@@ -1395,14 +1395,14 @@ public class PduPersister {
throw new MmsException("persist() failed: return null.");
}
// Get the real ID of the PDU and update all parts which were
- // saved with the dummy ID.
+ // saved with the placeholder ID.
msgId = ContentUris.parseId(res);
}
values = new ContentValues(1);
values.put(Part.MSG_ID, msgId);
SqliteWrapper.update(mContext, mContentResolver,
- Uri.parse("content://mms/" + dummyId + "/part"),
+ Uri.parse("content://mms/" + placeholderId + "/part"),
values, null, null);
// We should return the longest URI of the persisted PDU, for
// example, if input URI is "content://mms/inbox" and the _ID of
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 5ea4c7b5dac9..fa229fb47423 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -772,7 +772,7 @@ public class CarrierConfigManager {
* {@link #KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL}). If false, this device will fallback to
* circuit switch for supplementary services and will disable this capability for IMS entirely.
*
- * The default value for this key is {@code true}.
+ * The default value for this key is {@code false}.
*/
public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL =
"carrier_supports_ss_over_ut_bool";
@@ -1165,15 +1165,14 @@ public class CarrierConfigManager {
/**
* Determines whether adhoc conference calls are supported by a carrier. When {@code true},
* adhoc conference calling is supported, {@code false otherwise}.
- * @hide
*/
public static final String KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL =
"support_adhoc_conference_calls_bool";
/**
- * Determines whether conference participants can be added to existing call. When {@code true},
+ * Determines whether conference participants can be added to existing call to form an adhoc
+ * conference call (in contrast to merging calls to form a conference). When {@code true},
* adding conference participants to existing call is supported, {@code false otherwise}.
- * @hide
*/
public static final String KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL =
"support_add_conference_participants_bool";
diff --git a/telephony/java/android/telephony/CellLocation.java b/telephony/java/android/telephony/CellLocation.java
index aa1230165e13..cdf735195d61 100644
--- a/telephony/java/android/telephony/CellLocation.java
+++ b/telephony/java/android/telephony/CellLocation.java
@@ -33,10 +33,12 @@ import com.android.internal.telephony.PhoneConstants;
public abstract class CellLocation {
/**
- * This method will not do anything.
+ * Request an updated CellLocation for callers targeting SDK 30 or older.
*
- * Whenever location changes, a callback will automatically be be sent to
- * all registrants of {@link PhoneStateListener#LISTEN_CELL_LOCATION}.
+ * Whenever Android is aware of location changes, a callback will automatically be sent to
+ * all registrants of {@link PhoneStateListener#LISTEN_CELL_LOCATION}. This API requests an
+ * additional location update for cases where power saving might cause location updates to be
+ * missed.
*
* <p>This method is a no-op for callers targeting SDK level 31 or greater.
* <p>This method is a no-op for callers that target SDK level 29 or 30 and lack
@@ -44,14 +46,7 @@ public abstract class CellLocation {
* <p>This method is a no-op for callers that target SDK level 28 or below and lack
* {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
*
- * Callers wishing to request a single location update should use
- * {@link TelephonyManager#requestCellInfoUpdate}.
- *
- * @deprecated this method has undesirable side-effects, and it calls into the OS without
- * access to a {@link android.content.Context Context}, meaning that certain safety checks and
- * attribution are error-prone. Given that this method has numerous downsides, and given that
- * there are long-available superior alternatives, callers are strongly discouraged from using
- * this method.
+ * @deprecated use {@link TelephonyManager#requestCellInfoUpdate}.
*/
@Deprecated
public static void requestLocationUpdate() {
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 8e50bba38e84..766019ec382a 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -149,7 +149,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
mCsiRsrq = inRangeOrUnavailable(csiRsrq, -20, -3);
mCsiSinr = inRangeOrUnavailable(csiSinr, -23, 23);
mSsRsrp = inRangeOrUnavailable(ssRsrp, -140, -44);
- mSsRsrq = inRangeOrUnavailable(ssRsrq, -20, -3);
+ mSsRsrq = inRangeOrUnavailable(ssRsrq, -43, 20);
mSsSinr = inRangeOrUnavailable(ssSinr, -23, 40);
updateLevel(null, null);
}
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index 3f671ca2d809..18d6f467ba7b 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -509,7 +509,7 @@ public class MbmsDownloadSession implements AutoCloseable {
* provided directory is the same as what has been previously configured.
*
* The {@link File} supplied as a root temp file directory must already exist. If not, an
- * {@link IllegalArgumentException} will be thrown. In addition, as an additional sanity
+ * {@link IllegalArgumentException} will be thrown. In addition, as an additional correctness
* check, an {@link IllegalArgumentException} will be thrown if you attempt to set the temp
* file root directory to one of your data roots (the value of {@link Context#getDataDir()},
* {@link Context#getFilesDir()}, or {@link Context#getCacheDir()}).
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 3dbbf4138b02..fd9f46011c7e 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -28,11 +28,15 @@ import android.net.LinkProperties;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.DataState;
import android.telephony.Annotation.NetworkType;
import android.telephony.data.ApnSetting;
+import android.telephony.data.DataCallResponse;
+
+import com.android.internal.telephony.util.TelephonyUtils;
import java.util.Objects;
@@ -53,11 +57,11 @@ import java.util.Objects;
*
*/
public final class PreciseDataConnectionState implements Parcelable {
+ private final @TransportType int mTransportType;
+ private final int mId;
private final @DataState int mState;
private final @NetworkType int mNetworkType;
private final @DataFailureCause int mFailCause;
- private final @ApnType int mApnTypes;
- private final String mApn;
private final LinkProperties mLinkProperties;
private final ApnSetting mApnSetting;
@@ -76,35 +80,36 @@ public final class PreciseDataConnectionState implements Parcelable {
@ApnType int apnTypes, @NonNull String apn,
@Nullable LinkProperties linkProperties,
@DataFailureCause int failCause) {
- this(state, networkType, apnTypes, apn, linkProperties, failCause, null);
+ this(AccessNetworkConstants.TRANSPORT_TYPE_INVALID, -1, state, networkType,
+ linkProperties, failCause, new ApnSetting.Builder()
+ .setApnTypeBitmask(apnTypes)
+ .setApnName(apn)
+ .setEntryName(apn)
+ .build());
}
/**
* Constructor of PreciseDataConnectionState
*
+ * @param transportType The transport of the data connection
+ * @param id The id of the data connection
* @param state The state of the data connection
* @param networkType The access network that is/would carry this data connection
- * @param apnTypes The APN types that this data connection carries
- * @param apn The APN of this data connection
* @param linkProperties If the data connection is connected, the properties of the connection
* @param failCause In case a procedure related to this data connection fails, a non-zero error
* code indicating the cause of the failure.
* @param apnSetting If there is a valid APN for this Data Connection, then the APN Settings;
* if there is no valid APN setting for the specific type, then this will be null
- * @hide
*/
- private PreciseDataConnectionState(@DataState int state,
- @NetworkType int networkType,
- @ApnType int apnTypes,
- @NonNull String apn,
- @Nullable LinkProperties linkProperties,
- @DataFailureCause int failCause,
- @Nullable ApnSetting apnSetting) {
+ private PreciseDataConnectionState(@TransportType int transportType, int id,
+ @DataState int state, @NetworkType int networkType,
+ @Nullable LinkProperties linkProperties, @DataFailureCause int failCause,
+ @Nullable ApnSetting apnSetting) {
+ mTransportType = transportType;
+ mId = id;
mState = state;
mNetworkType = networkType;
- mApnTypes = apnTypes;
- mApn = apn;
mLinkProperties = linkProperties;
mFailCause = failCause;
mApnSetting = apnSetting;
@@ -116,13 +121,13 @@ public final class PreciseDataConnectionState implements Parcelable {
* @hide
*/
private PreciseDataConnectionState(Parcel in) {
+ mTransportType = in.readInt();
+ mId = in.readInt();
mState = in.readInt();
mNetworkType = in.readInt();
- mApnTypes = in.readInt();
- mApn = in.readString();
- mLinkProperties = (LinkProperties) in.readParcelable(null);
+ mLinkProperties = in.readParcelable(LinkProperties.class.getClassLoader());
mFailCause = in.readInt();
- mApnSetting = (ApnSetting) in.readParcelable(null);
+ mApnSetting = in.readParcelable(ApnSetting.class.getClassLoader());
}
/**
@@ -152,7 +157,29 @@ public final class PreciseDataConnectionState implements Parcelable {
}
/**
- * Returns the high-level state of this data connection.
+ * @return The transport type of this data connection.
+ */
+ public @TransportType int getTransportType() {
+ return mTransportType;
+ }
+
+ /**
+ * @return The unique id of the data connection
+ *
+ * Note this is the id assigned in {@link DataCallResponse}.
+ * The id remains the same for data connection handover between
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN} and
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN}
+ *
+ * @hide
+ */
+ @SystemApi
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * @return The high-level state of this data connection.
*/
public @DataState int getState() {
return mState;
@@ -181,7 +208,7 @@ public final class PreciseDataConnectionState implements Parcelable {
@Deprecated
@SystemApi
public @ApnType int getDataConnectionApnTypeBitMask() {
- return mApnTypes;
+ return (mApnSetting != null) ? mApnSetting.getApnTypeBitmask() : ApnSetting.TYPE_NONE;
}
/**
@@ -194,7 +221,7 @@ public final class PreciseDataConnectionState implements Parcelable {
@SystemApi
@Deprecated
public String getDataConnectionApn() {
- return mApn;
+ return (mApnSetting != null) ? mApnSetting.getApnName() : "";
}
/**
@@ -230,7 +257,9 @@ public final class PreciseDataConnectionState implements Parcelable {
/**
* Return the APN Settings for this data connection.
*
- * @return the ApnSetting that was used to configure this data connection.
+ * @return the ApnSetting that was used to configure this data connection. Note that a data
+ * connection cannot be established without a valid {@link ApnSetting}. The return value would
+ * never be {@code null} even though it has {@link Nullable} annotation.
*/
public @Nullable ApnSetting getApnSetting() {
return mApnSetting;
@@ -243,10 +272,10 @@ public final class PreciseDataConnectionState implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeInt(mTransportType);
+ out.writeInt(mId);
out.writeInt(mState);
out.writeInt(mNetworkType);
- out.writeInt(mApnTypes);
- out.writeString(mApn);
out.writeParcelable(mLinkProperties, flags);
out.writeInt(mFailCause);
out.writeParcelable(mApnSetting, flags);
@@ -266,8 +295,8 @@ public final class PreciseDataConnectionState implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mState, mNetworkType, mFailCause, mApnTypes, mApn, mLinkProperties,
- mApnSetting);
+ return Objects.hash(mTransportType, mId, mState, mNetworkType, mFailCause,
+ mLinkProperties, mApnSetting);
}
@@ -276,11 +305,11 @@ public final class PreciseDataConnectionState implements Parcelable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PreciseDataConnectionState that = (PreciseDataConnectionState) o;
- return mState == that.mState
+ return mTransportType == that.mTransportType
+ && mId == that.mId
+ && mState == that.mState
&& mNetworkType == that.mNetworkType
&& mFailCause == that.mFailCause
- && mApnTypes == that.mApnTypes
- && Objects.equals(mApn, that.mApn)
&& Objects.equals(mLinkProperties, that.mLinkProperties)
&& Objects.equals(mApnSetting, that.mApnSetting);
}
@@ -290,13 +319,14 @@ public final class PreciseDataConnectionState implements Parcelable {
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("Data Connection state: " + mState);
- sb.append(", Network type: " + mNetworkType);
- sb.append(", APN types: " + ApnSetting.getApnTypesStringFromBitmask(mApnTypes));
- sb.append(", APN: " + mApn);
- sb.append(", Link properties: " + mLinkProperties);
- sb.append(", Fail cause: " + DataFailCause.toString(mFailCause));
- sb.append(", Apn Setting: " + mApnSetting);
+ sb.append(" state: " + TelephonyUtils.dataStateToString(mState));
+ sb.append(", transport: "
+ + AccessNetworkConstants.transportTypeToString(mTransportType));
+ sb.append(", id: " + mId);
+ sb.append(", network type: " + TelephonyManager.getNetworkTypeName(mNetworkType));
+ sb.append(", APN Setting: " + mApnSetting);
+ sb.append(", link properties: " + mLinkProperties);
+ sb.append(", fail cause: " + DataFailCause.toString(mFailCause));
return sb.toString();
}
@@ -307,18 +337,21 @@ public final class PreciseDataConnectionState implements Parcelable {
* @hide
*/
public static final class Builder {
+ /** The transport type of the data connection */
+ private @TransportType int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+
+ /**
+ * The unique ID of the data connection. This is the id assigned in
+ * {@link DataCallResponse)}.
+ */
+ private int mId = -1;
+
/** The state of the data connection */
private @DataState int mState = TelephonyManager.DATA_UNKNOWN;
/** The network type associated with this data connection */
private @NetworkType int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- /** The APN types that this data connection carries */
- private @ApnType int mApnTypes = ApnSetting.TYPE_NONE;
-
- /** The APN of this data connection */
- private @NonNull String mApn = "";
-
/** If the data connection is connected, the properties of the connection */
private @Nullable LinkProperties mLinkProperties = null;
@@ -332,46 +365,46 @@ public final class PreciseDataConnectionState implements Parcelable {
private @Nullable ApnSetting mApnSetting = null;
/**
- * Set the state of the data connection.
+ * Set the transport type of the data connection.
*
- * @param state The state of the data connection
+ * @param transportType The transport type of the data connection
* @return The builder
*/
- public Builder setState(@DataState int state) {
- mState = state;
+ public @NonNull Builder setTransportType(@TransportType int transportType) {
+ mTransportType = transportType;
return this;
}
/**
- * Set the network type associated with this data connection.
+ * Set the id of the data connection.
*
- * @param networkType The network type
+ * @param id The id of the data connection
* @return The builder
*/
- public Builder setNetworkType(@NetworkType int networkType) {
- mNetworkType = networkType;
+ public @NonNull Builder setId(int id) {
+ mId = id;
return this;
}
/**
- * Set the APN types that this data connection carries
+ * Set the state of the data connection.
*
- * @param apnTypes The APN types
+ * @param state The state of the data connection
* @return The builder
*/
- public Builder setApnTypes(@ApnType int apnTypes) {
- mApnTypes = apnTypes;
+ public @NonNull Builder setState(@DataState int state) {
+ mState = state;
return this;
}
/**
- * Set the APN of this data connection
+ * Set the network type associated with this data connection.
*
- * @param apn The APN of this data connection
+ * @param networkType The network type
* @return The builder
*/
- public Builder setApn(@NonNull String apn) {
- mApn = apn;
+ public @NonNull Builder setNetworkType(@NetworkType int networkType) {
+ mNetworkType = networkType;
return this;
}
@@ -381,7 +414,7 @@ public final class PreciseDataConnectionState implements Parcelable {
* @param linkProperties Link properties
* @return The builder
*/
- public Builder setLinkProperties(@NonNull LinkProperties linkProperties) {
+ public @NonNull Builder setLinkProperties(LinkProperties linkProperties) {
mLinkProperties = linkProperties;
return this;
}
@@ -393,7 +426,7 @@ public final class PreciseDataConnectionState implements Parcelable {
* error code indicating the cause of the failure.
* @return The builder
*/
- public Builder setFailCause(@DataFailureCause int failCause) {
+ public @NonNull Builder setFailCause(@DataFailureCause int failCause) {
mFailCause = failCause;
return this;
}
@@ -404,7 +437,7 @@ public final class PreciseDataConnectionState implements Parcelable {
* @param apnSetting APN setting
* @return This builder
*/
- public Builder setApnSetting(@NonNull ApnSetting apnSetting) {
+ public @NonNull Builder setApnSetting(@NonNull ApnSetting apnSetting) {
mApnSetting = apnSetting;
return this;
}
@@ -415,7 +448,7 @@ public final class PreciseDataConnectionState implements Parcelable {
* @return The {@link PreciseDataConnectionState} instance
*/
public PreciseDataConnectionState build() {
- return new PreciseDataConnectionState(mState, mNetworkType, mApnTypes, mApn,
+ return new PreciseDataConnectionState(mTransportType, mId, mState, mNetworkType,
mLinkProperties, mFailCause, mApnSetting);
}
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 183fdcce1ca4..2b2608724e12 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -39,7 +39,9 @@ import android.os.RemoteException;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Pair;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.ISms;
import com.android.internal.telephony.ITelephony;
@@ -74,11 +76,16 @@ import java.util.concurrent.Executor;
public final class SmsManager {
private static final String TAG = "SmsManager";
- /** Singleton object constructed during class initialization. */
- private static final SmsManager sInstance = new SmsManager(
- SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
private static final Object sLockObject = new Object();
+ @GuardedBy("sLockObject")
+ private static final Map<Pair<Context, Integer>, SmsManager> sSubInstances =
+ new ArrayMap<>();
+
+ /** Singleton object constructed during class initialization. */
+ private static final SmsManager DEFAULT_INSTANCE = getSmsManagerForContextAndSubscriptionId(
+ null, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+
/** SMS record length from TS 51.011 10.5.3
* @hide
*/
@@ -89,13 +96,16 @@ public final class SmsManager {
*/
public static final int CDMA_SMS_RECORD_LENGTH = 255;
- private static final Map<Integer, SmsManager> sSubInstances =
- new ArrayMap<Integer, SmsManager>();
-
/** A concrete subscription id, or the pseudo DEFAULT_SUBSCRIPTION_ID */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private int mSubId;
+ /**
+ * Context this SmsManager is for. Can be {@code null} in the case the manager was created via
+ * legacy APIs
+ */
+ private final @Nullable Context mContext;
+
/*
* Key for the various carrier-dependent configuration values.
* Some of the values are used by the system in processing SMS or MMS messages. Others
@@ -325,6 +335,34 @@ public final class SmsManager {
}
/**
+ * Get {@link Context#getOpPackageName()} if this manager has a context, otherwise a dummy
+ * value.
+ *
+ * @return The package name to be used for app-ops checks
+ */
+ private @Nullable String getOpPackageName() {
+ if (mContext == null) {
+ return null;
+ } else {
+ return mContext.getOpPackageName();
+ }
+ }
+
+ /**
+ * Get {@link Context#getAttributionTag()} ()} if this manager has a context, otherwise get the
+ * default attribution tag.
+ *
+ * @return The attribution tag to be used for app-ops checks
+ */
+ private @Nullable String getAttributionTag() {
+ if (mContext == null) {
+ return null;
+ } else {
+ return mContext.getAttributionTag();
+ }
+ }
+
+ /**
* Send a text based SMS.
*
* <p class="note"><strong>Note:</strong> Using this method requires that your app has the
@@ -424,7 +462,8 @@ public final class SmsManager {
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- true /* persistMessage*/, null, null, 0L /* messageId */);
+ true /* persistMessage*/, getOpPackageName(), getAttributionTag(),
+ 0L /* messageId */);
}
@@ -443,7 +482,8 @@ public final class SmsManager {
@Nullable PendingIntent sentIntent, @Nullable PendingIntent deliveryIntent,
long messageId) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- true /* persistMessage*/, null, null, messageId);
+ true /* persistMessage*/, getOpPackageName(), getAttributionTag(),
+ messageId);
}
/**
@@ -653,8 +693,8 @@ public final class SmsManager {
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
- false /* persistMessage */, null, null,
- 0L /* messageId */);
+ false /* persistMessage */, getOpPackageName(),
+ getAttributionTag(), 0L /* messageId */);
}
private void sendTextMessageInternal(
@@ -939,8 +979,8 @@ public final class SmsManager {
String destinationAddress, String scAddress, ArrayList<String> parts,
ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, true /* persistMessage*/, null, null,
- 0L /* messageId */);
+ deliveryIntents, true /* persistMessage*/, getOpPackageName(),
+ getAttributionTag(), 0L /* messageId */);
}
/**
@@ -957,8 +997,8 @@ public final class SmsManager {
@NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents,
@Nullable List<PendingIntent> deliveryIntents, long messageId) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, true /* persistMessage*/, null, null,
- messageId);
+ deliveryIntents, true /* persistMessage*/, getOpPackageName(),
+ getAttributionTag(), messageId);
}
/**
@@ -1088,8 +1128,8 @@ public final class SmsManager {
String destinationAddress, String scAddress, List<String> parts,
List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
- deliveryIntents, false /* persistMessage*/, null, null,
- 0L /* messageId */);
+ deliveryIntents, false /* persistMessage*/, getOpPackageName(),
+ getAttributionTag(), 0L /* messageId */);
}
/**
@@ -1451,9 +1491,37 @@ public final class SmsManager {
* @return the {@link SmsManager} associated with the default subscription id.
*
* @see SubscriptionManager#getDefaultSmsSubscriptionId()
+ *
+ * @deprecated Use {@link Context#getSystemService Context.getSystemService(SmsManager.class)}
+ * instead
*/
+ @Deprecated
public static SmsManager getDefault() {
- return sInstance;
+ return DEFAULT_INSTANCE;
+ }
+
+ /**
+ * Get the instance of the SmsManager associated with a particular context and subscription ID.
+ *
+ * @param context The context the manager belongs to
+ * @param subId an SMS subscription ID, typically accessed using {@link SubscriptionManager}
+ *
+ * @return the instance of the SmsManager associated with subscription
+ *
+ * @hide
+ */
+ public static @NonNull SmsManager getSmsManagerForContextAndSubscriptionId(
+ @Nullable Context context, int subId) {
+ synchronized(sLockObject) {
+ Pair<Context, Integer> key = new Pair<>(context, subId);
+
+ SmsManager smsManager = sSubInstances.get(key);
+ if (smsManager == null) {
+ smsManager = new SmsManager(context, subId);
+ sSubInstances.put(key, smsManager);
+ }
+ return smsManager;
+ }
}
/**
@@ -1468,19 +1536,33 @@ public final class SmsManager {
*
* @see SubscriptionManager#getActiveSubscriptionInfoList()
* @see SubscriptionManager#getDefaultSmsSubscriptionId()
+ * @deprecated Use {@link Context#getSystemService Context.getSystemService(SmsManager.class)}
+ * .{@link #createForSubscriptionId createForSubscriptionId(subId)} instead
*/
+ @Deprecated
public static SmsManager getSmsManagerForSubscriptionId(int subId) {
- synchronized(sLockObject) {
- SmsManager smsManager = sSubInstances.get(subId);
- if (smsManager == null) {
- smsManager = new SmsManager(subId);
- sSubInstances.put(subId, smsManager);
- }
- return smsManager;
- }
+ return getSmsManagerForContextAndSubscriptionId(null, subId);
+ }
+
+ /**
+ * Get the instance of the SmsManager associated with a particular subscription ID.
+ *
+ * <p class="note"><strong>Note:</strong> Constructing an {@link SmsManager} in this manner will
+ * never cause an SMS disambiguation dialog to appear, unlike {@link #getDefault()}.
+ * </p>
+ *
+ * @param subId an SMS subscription ID, typically accessed using {@link SubscriptionManager}
+ * @return the instance of the SmsManager associated with subscription
+ *
+ * @see SubscriptionManager#getActiveSubscriptionInfoList()
+ * @see SubscriptionManager#getDefaultSmsSubscriptionId()
+ */
+ public @NonNull SmsManager createForSubscriptionId(int subId) {
+ return getSmsManagerForContextAndSubscriptionId(mContext, subId);
}
- private SmsManager(int subId) {
+ private SmsManager(@Nullable Context context, int subId) {
+ mContext = context;
mSubId = subId;
}
@@ -1715,8 +1797,7 @@ public final class SmsManager {
* operation is performed on the correct subscription.
* </p>
*
- * @param messageIndex This is the same index used to access a message
- * from {@link #getMessagesFromIcc()}.
+ * @param messageIndex the message index of the message in the ICC (1-based index).
* @return true for success, false if the operation fails. Failure can be due to IPC failure,
* RIL/modem error which results in SMS failed to be deleted on SIM
*
@@ -1798,7 +1879,7 @@ public final class SmsManager {
* operation is performed on the correct subscription.
* </p>
*
- * @return <code>List</code> of <code>SmsMessage</code> objects
+ * @return <code>List</code> of <code>SmsMessage</code> objects for valid records only.
*
* {@hide}
*/
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 4ad52ae5e077..a71a965b1bdb 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -94,10 +94,9 @@ public class SubscriptionManager {
/** An invalid subscription identifier */
public static final int INVALID_SUBSCRIPTION_ID = -1;
- /** Base value for Dummy SUBSCRIPTION_ID's. */
- /** FIXME: Remove DummySubId's, but for now have them map just below INVALID_SUBSCRIPTION_ID
- /** @hide */
- public static final int DUMMY_SUBSCRIPTION_ID_BASE = INVALID_SUBSCRIPTION_ID - 1;
+ /** Base value for placeholder SUBSCRIPTION_ID's. */
+ /** @hide */
+ public static final int PLACEHOLDER_SUBSCRIPTION_ID_BASE = INVALID_SUBSCRIPTION_ID - 1;
/** An invalid phone identifier */
/** @hide */
diff --git a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
index c9540fb5f467..8308821b59ff 100644
--- a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
+++ b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
@@ -92,6 +92,12 @@ public class TelephonyFrameworkInitializer {
ImsManager.class,
context -> new ImsManager(context)
);
+ SystemServiceRegistry.registerContextAwareService(
+ Context.SMS_SERVICE,
+ SmsManager.class,
+ context -> SmsManager.getSmsManagerForContextAndSubscriptionId(context,
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
+ );
}
/** @hide */
diff --git a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
index e8f3f1ebb6cf..eadb726bf63b 100644
--- a/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
+++ b/telephony/java/android/telephony/VisualVoicemailSmsFilterSettings.java
@@ -92,8 +92,8 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable {
}
/**
- * Sets the originating number whitelist for the visual voicemail SMS filter. If the list is
- * not null only the SMS messages from a number in the list can be considered as a visual
+ * Sets the originating number allow list for the visual voicemail SMS filter. If the list
+ * is not null only the SMS messages from a number in the list can be considered as a visual
* voicemail SMS. Otherwise, messages from any address will be considered.
*/
public Builder setOriginatingNumbers(List<String> originatingNumbers) {
@@ -133,7 +133,7 @@ public final class VisualVoicemailSmsFilterSettings implements Parcelable {
public final String clientPrefix;
/**
- * The originating number whitelist for the visual voicemail SMS filter of a phone account. If
+ * The originating number allow list for the visual voicemail SMS filter of a phone account. If
* the list is not null only the SMS messages from a number in the list can be considered as a
* visual voicemail SMS. Otherwise, messages from any address will be considered.
*/
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index bfb54b008cd8..ff9329ef9742 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1214,12 +1214,16 @@ public class ApnSetting implements Parcelable {
return false;
}
- // TODO - if we have this function we should also have hashCode.
- // Also should handle changes in type order and perhaps case-insensitivity.
+ @Override
+ public int hashCode() {
+ return Objects.hash(mApnName, mProxyAddress, mProxyPort, mMmsc, mMmsProxyAddress,
+ mMmsProxyPort, mUser, mPassword, mAuthType, mApnTypeBitmask, mId, mOperatorNumeric,
+ mProtocol, mRoamingProtocol, mMtu, mCarrierEnabled, mNetworkTypeBitmask, mProfileId,
+ mPersistent, mMaxConns, mWaitTime, mMaxConnsTime, mMvnoType, mMvnoMatchData,
+ mApnSetId, mCarrierId, mSkip464Xlat);
+ }
- /**
- * @hide
- */
+ @Override
public boolean equals(Object o) {
if (o instanceof ApnSetting == false) {
return false;
@@ -1643,7 +1647,7 @@ public class ApnSetting implements Parcelable {
*
* <pre><code>
* // Create an MMS proxy address with a hostname. A network might not be
- * // available, so supply a dummy (0.0.0.0) IPv4 address to avoid DNS lookup.
+ * // available, so supply a placeholder (0.0.0.0) IPv4 address to avoid DNS lookup.
* String host = "mms.example.com";
* byte[] ipAddress = new byte[4];
* InetAddress mmsProxy;
@@ -1828,7 +1832,8 @@ public class ApnSetting implements Parcelable {
* {@link java.net.InetAddress#getAllByName getAllByName()} require DNS for hostname
* resolution. To avoid this requirement when setting a hostname, call
* {@link java.net.InetAddress#getByAddress(java.lang.String, byte[])} with both the
- * hostname and a dummy IP address. See {@link ApnSetting.Builder above} for an example.
+ * hostname and a placeholder IP address. See {@link ApnSetting.Builder above} for an
+ * example.
*
* @param proxy the proxy address to set for the APN
* @deprecated use {@link #setProxyAddress(String)} instead.
@@ -1882,7 +1887,8 @@ public class ApnSetting implements Parcelable {
* {@link java.net.InetAddress#getAllByName getAllByName()} require DNS for hostname
* resolution. To avoid this requirement when setting a hostname, call
* {@link java.net.InetAddress#getByAddress(java.lang.String, byte[])} with both the
- * hostname and a dummy IP address. See {@link ApnSetting.Builder above} for an example.
+ * hostname and a placeholder IP address. See {@link ApnSetting.Builder above} for an
+ * example.
*
* @param mmsProxy the MMS proxy address to set for the APN
* @deprecated use {@link #setMmsProxyAddress(String)} instead.
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index 80c38cbfc39a..8857b9b36d0c 100755
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -815,7 +815,7 @@ public class ImsCallSession {
* Transfers an ongoing call.
*
* @param number number to be transferred to.
- * @param isConfirmationRequired indicates blind or assured transfer.
+ * @param isConfirmationRequired indicates whether confirmation of the transfer is required.
*/
public void transfer(@NonNull String number, boolean isConfirmationRequired) {
if (mClosed) {
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 0d6b31d349e1..30389a290368 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -27,7 +27,8 @@ import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-
+import java.util.HashMap;
+import java.util.Map;
/**
* Provides details on why an IMS call failed. Applications can use the methods in this class to
* get local or network fault behind an IMS services failure. For example, if the code is
@@ -1095,6 +1096,196 @@ public final class ImsReasonInfo implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
public @interface ImsCode {}
+
+ private static final Map<Integer, String> sImsCodeMap;
+ static {
+ sImsCodeMap = new HashMap<>();
+ sImsCodeMap.put(CODE_UNSPECIFIED, "CODE_UNSPECIFIED");
+ sImsCodeMap.put(CODE_LOCAL_ILLEGAL_ARGUMENT, "CODE_LOCAL_ILLEGAL_ARGUMENT");
+ sImsCodeMap.put(CODE_LOCAL_ILLEGAL_STATE, "CODE_LOCAL_ILLEGAL_STATE");
+ sImsCodeMap.put(CODE_LOCAL_INTERNAL_ERROR, "CODE_LOCAL_INTERNAL_ERROR");
+ sImsCodeMap.put(CODE_LOCAL_IMS_SERVICE_DOWN, "CODE_LOCAL_IMS_SERVICE_DOWN");
+ sImsCodeMap.put(CODE_LOCAL_NO_PENDING_CALL, "CODE_LOCAL_NO_PENDING_CALL");
+ sImsCodeMap.put(CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE,
+ "CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE");
+ sImsCodeMap.put(CODE_LOCAL_POWER_OFF, "CODE_LOCAL_POWER_OFF");
+ sImsCodeMap.put(CODE_LOCAL_LOW_BATTERY, "CODE_LOCAL_LOW_BATTERY");
+ sImsCodeMap.put(CODE_LOCAL_NETWORK_NO_SERVICE, "CODE_LOCAL_NETWORK_NO_SERVICE");
+ sImsCodeMap.put(CODE_LOCAL_NETWORK_NO_LTE_COVERAGE, "CODE_LOCAL_NETWORK_NO_LTE_COVERAGE");
+ sImsCodeMap.put(CODE_LOCAL_NETWORK_ROAMING, "CODE_LOCAL_NETWORK_ROAMING");
+ sImsCodeMap.put(CODE_LOCAL_NETWORK_IP_CHANGED, "CODE_LOCAL_NETWORK_IP_CHANGED");
+ sImsCodeMap.put(CODE_LOCAL_SERVICE_UNAVAILABLE, "CODE_LOCAL_SERVICE_UNAVAILABLE");
+ sImsCodeMap.put(CODE_LOCAL_NOT_REGISTERED, "CODE_LOCAL_NOT_REGISTERED");
+ sImsCodeMap.put(CODE_LOCAL_CALL_EXCEEDED, "CODE_LOCAL_CALL_EXCEEDED");
+ sImsCodeMap.put(CODE_LOCAL_CALL_BUSY, "CODE_LOCAL_CALL_BUSY");
+ sImsCodeMap.put(CODE_LOCAL_CALL_DECLINE, "CODE_LOCAL_CALL_DECLINE");
+ sImsCodeMap.put(CODE_LOCAL_CALL_VCC_ON_PROGRESSING, "CODE_LOCAL_CALL_VCC_ON_PROGRESSING");
+ sImsCodeMap.put(CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED,
+ "CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED");
+ sImsCodeMap.put(CODE_LOCAL_CALL_CS_RETRY_REQUIRED, "CODE_LOCAL_CALL_CS_RETRY_REQUIRED");
+ sImsCodeMap.put(CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED,
+ "CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED");
+ sImsCodeMap.put(CODE_LOCAL_CALL_TERMINATED, "CODE_LOCAL_CALL_TERMINATED");
+ sImsCodeMap.put(CODE_LOCAL_HO_NOT_FEASIBLE, "CODE_LOCAL_HO_NOT_FEASIBLE");
+ sImsCodeMap.put(CODE_TIMEOUT_1XX_WAITING, "CODE_TIMEOUT_1XX_WAITING");
+ sImsCodeMap.put(CODE_TIMEOUT_NO_ANSWER, "CODE_TIMEOUT_NO_ANSWER");
+ sImsCodeMap.put(CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE, "CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE");
+ sImsCodeMap.put(CODE_CALL_BARRED, "CODE_CALL_BARRED");
+ sImsCodeMap.put(CODE_FDN_BLOCKED, "CODE_FDN_BLOCKED");
+ sImsCodeMap.put(CODE_IMEI_NOT_ACCEPTED, "CODE_IMEI_NOT_ACCEPTED");
+ sImsCodeMap.put(CODE_DIAL_MODIFIED_TO_USSD, "CODE_DIAL_MODIFIED_TO_USSD");
+ sImsCodeMap.put(CODE_DIAL_MODIFIED_TO_SS, "CODE_DIAL_MODIFIED_TO_SS");
+ sImsCodeMap.put(CODE_DIAL_MODIFIED_TO_DIAL, "CODE_DIAL_MODIFIED_TO_DIAL");
+ sImsCodeMap.put(CODE_DIAL_MODIFIED_TO_DIAL_VIDEO, "CODE_DIAL_MODIFIED_TO_DIAL_VIDEO");
+ sImsCodeMap.put(CODE_DIAL_VIDEO_MODIFIED_TO_DIAL, "CODE_DIAL_VIDEO_MODIFIED_TO_DIAL");
+ sImsCodeMap.put(CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO,
+ "CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO");
+ sImsCodeMap.put(CODE_DIAL_VIDEO_MODIFIED_TO_SS, "CODE_DIAL_VIDEO_MODIFIED_TO_SS");
+ sImsCodeMap.put(CODE_DIAL_VIDEO_MODIFIED_TO_USSD, "CODE_DIAL_VIDEO_MODIFIED_TO_USSD");
+ sImsCodeMap.put(CODE_SIP_REDIRECTED, "CODE_SIP_REDIRECTED");
+ sImsCodeMap.put(CODE_SIP_BAD_REQUEST, "CODE_SIP_BAD_REQUEST");
+ sImsCodeMap.put(CODE_SIP_FORBIDDEN, "CODE_SIP_FORBIDDEN");
+ sImsCodeMap.put(CODE_SIP_NOT_FOUND, "CODE_SIP_NOT_FOUND");
+ sImsCodeMap.put(CODE_SIP_NOT_SUPPORTED, "CODE_SIP_NOT_SUPPORTED");
+ sImsCodeMap.put(CODE_SIP_REQUEST_TIMEOUT, "CODE_SIP_REQUEST_TIMEOUT");
+ sImsCodeMap.put(CODE_SIP_TEMPRARILY_UNAVAILABLE, "CODE_SIP_TEMPRARILY_UNAVAILABLE");
+ sImsCodeMap.put(CODE_SIP_BAD_ADDRESS, "CODE_SIP_BAD_ADDRESS");
+ sImsCodeMap.put(CODE_SIP_BUSY, "CODE_SIP_BUSY");
+ sImsCodeMap.put(CODE_SIP_REQUEST_CANCELLED, "CODE_SIP_REQUEST_CANCELLED");
+ sImsCodeMap.put(CODE_SIP_NOT_ACCEPTABLE, "CODE_SIP_NOT_ACCEPTABLE");
+ sImsCodeMap.put(CODE_SIP_NOT_REACHABLE, "CODE_SIP_NOT_REACHABLE");
+ sImsCodeMap.put(CODE_SIP_CLIENT_ERROR, "CODE_SIP_CLIENT_ERROR");
+ sImsCodeMap.put(CODE_SIP_TRANSACTION_DOES_NOT_EXIST, "CODE_SIP_TRANSACTION_DOES_NOT_EXIST");
+ sImsCodeMap.put(CODE_SIP_SERVER_INTERNAL_ERROR, "CODE_SIP_SERVER_INTERNAL_ERROR");
+ sImsCodeMap.put(CODE_SIP_SERVICE_UNAVAILABLE, "CODE_SIP_SERVICE_UNAVAILABLE");
+ sImsCodeMap.put(CODE_SIP_SERVER_TIMEOUT, "CODE_SIP_SERVER_TIMEOUT");
+ sImsCodeMap.put(CODE_SIP_SERVER_ERROR, "CODE_SIP_SERVER_ERROR");
+ sImsCodeMap.put(CODE_SIP_USER_REJECTED, "CODE_SIP_USER_REJECTED");
+ sImsCodeMap.put(CODE_SIP_GLOBAL_ERROR, "CODE_SIP_GLOBAL_ERROR");
+ sImsCodeMap.put(CODE_EMERGENCY_TEMP_FAILURE, "CODE_EMERGENCY_TEMP_FAILURE");
+ sImsCodeMap.put(CODE_EMERGENCY_PERM_FAILURE, "CODE_EMERGENCY_PERM_FAILURE");
+ sImsCodeMap.put(CODE_SIP_USER_MARKED_UNWANTED, "CODE_SIP_USER_MARKED_UNWANTED");
+ sImsCodeMap.put(CODE_SIP_METHOD_NOT_ALLOWED, "CODE_SIP_METHOD_NOT_ALLOWED");
+ sImsCodeMap.put(CODE_SIP_PROXY_AUTHENTICATION_REQUIRED,
+ "CODE_SIP_PROXY_AUTHENTICATION_REQUIRED");
+ sImsCodeMap.put(CODE_SIP_REQUEST_ENTITY_TOO_LARGE, "CODE_SIP_REQUEST_ENTITY_TOO_LARGE");
+ sImsCodeMap.put(CODE_SIP_REQUEST_URI_TOO_LARGE, "CODE_SIP_REQUEST_URI_TOO_LARGE");
+ sImsCodeMap.put(CODE_SIP_EXTENSION_REQUIRED, "CODE_SIP_EXTENSION_REQUIRED");
+ sImsCodeMap.put(CODE_SIP_INTERVAL_TOO_BRIEF, "CODE_SIP_INTERVAL_TOO_BRIEF");
+ sImsCodeMap.put(CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST,
+ "CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST");
+ sImsCodeMap.put(CODE_SIP_LOOP_DETECTED, "CODE_SIP_LOOP_DETECTED");
+ sImsCodeMap.put(CODE_SIP_TOO_MANY_HOPS, "CODE_SIP_TOO_MANY_HOPS");
+ sImsCodeMap.put(CODE_SIP_AMBIGUOUS, "CODE_SIP_AMBIGUOUS");
+ sImsCodeMap.put(CODE_SIP_REQUEST_PENDING, "CODE_SIP_REQUEST_PENDING");
+ sImsCodeMap.put(CODE_SIP_UNDECIPHERABLE, "CODE_SIP_UNDECIPHERABLE");
+ sImsCodeMap.put(CODE_MEDIA_INIT_FAILED, "CODE_MEDIA_INIT_FAILED");
+ sImsCodeMap.put(CODE_MEDIA_NO_DATA, "CODE_MEDIA_NO_DATA");
+ sImsCodeMap.put(CODE_MEDIA_NOT_ACCEPTABLE, "CODE_MEDIA_NOT_ACCEPTABLE");
+ sImsCodeMap.put(CODE_MEDIA_UNSPECIFIED, "CODE_MEDIA_UNSPECIFIED");
+ sImsCodeMap.put(CODE_USER_TERMINATED, "CODE_USER_TERMINATED");
+ sImsCodeMap.put(CODE_USER_NOANSWER, "CODE_USER_NOANSWER");
+ sImsCodeMap.put(CODE_USER_IGNORE, "CODE_USER_IGNORE");
+ sImsCodeMap.put(CODE_USER_DECLINE, "CODE_USER_DECLINE");
+ sImsCodeMap.put(CODE_LOW_BATTERY, "CODE_LOW_BATTERY");
+ sImsCodeMap.put(CODE_BLACKLISTED_CALL_ID, "CODE_BLACKLISTED_CALL_ID");
+ sImsCodeMap.put(CODE_USER_TERMINATED_BY_REMOTE, "CODE_USER_TERMINATED_BY_REMOTE");
+ sImsCodeMap.put(CODE_USER_REJECTED_SESSION_MODIFICATION,
+ "CODE_USER_REJECTED_SESSION_MODIFICATION");
+ sImsCodeMap.put(CODE_USER_CANCELLED_SESSION_MODIFICATION,
+ "CODE_USER_CANCELLED_SESSION_MODIFICATION");
+ sImsCodeMap.put(CODE_SESSION_MODIFICATION_FAILED, "CODE_SESSION_MODIFICATION_FAILED");
+ sImsCodeMap.put(CODE_UT_NOT_SUPPORTED, "CODE_UT_NOT_SUPPORTED");
+ sImsCodeMap.put(CODE_UT_SERVICE_UNAVAILABLE, "CODE_UT_SERVICE_UNAVAILABLE");
+ sImsCodeMap.put(CODE_UT_OPERATION_NOT_ALLOWED, "CODE_UT_OPERATION_NOT_ALLOWED");
+ sImsCodeMap.put(CODE_UT_NETWORK_ERROR, "CODE_UT_NETWORK_ERROR");
+ sImsCodeMap.put(CODE_UT_CB_PASSWORD_MISMATCH, "CODE_UT_CB_PASSWORD_MISMATCH");
+ sImsCodeMap.put(CODE_UT_SS_MODIFIED_TO_DIAL, "CODE_UT_SS_MODIFIED_TO_DIAL");
+ sImsCodeMap.put(CODE_UT_SS_MODIFIED_TO_USSD, "CODE_UT_SS_MODIFIED_TO_USSD");
+ sImsCodeMap.put(CODE_UT_SS_MODIFIED_TO_SS, "CODE_UT_SS_MODIFIED_TO_SS");
+ sImsCodeMap.put(CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO, "CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO");
+ sImsCodeMap.put(CODE_ECBM_NOT_SUPPORTED, "CODE_ECBM_NOT_SUPPORTED");
+ sImsCodeMap.put(CODE_MULTIENDPOINT_NOT_SUPPORTED, "CODE_MULTIENDPOINT_NOT_SUPPORTED");
+ sImsCodeMap.put(CODE_REGISTRATION_ERROR, "CODE_REGISTRATION_ERROR");
+ sImsCodeMap.put(CODE_ANSWERED_ELSEWHERE, "CODE_ANSWERED_ELSEWHERE");
+ sImsCodeMap.put(CODE_CALL_PULL_OUT_OF_SYNC, "CODE_CALL_PULL_OUT_OF_SYNC");
+ sImsCodeMap.put(CODE_CALL_END_CAUSE_CALL_PULL, "CODE_CALL_END_CAUSE_CALL_PULL");
+ sImsCodeMap.put(CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE,
+ "CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE");
+ sImsCodeMap.put(CODE_REJECTED_ELSEWHERE, "CODE_REJECTED_ELSEWHERE");
+ sImsCodeMap.put(CODE_SUPP_SVC_FAILED, "CODE_SUPP_SVC_FAILED");
+ sImsCodeMap.put(CODE_SUPP_SVC_CANCELLED, "CODE_SUPP_SVC_CANCELLED");
+ sImsCodeMap.put(CODE_SUPP_SVC_REINVITE_COLLISION, "CODE_SUPP_SVC_REINVITE_COLLISION");
+ sImsCodeMap.put(CODE_IWLAN_DPD_FAILURE, "CODE_IWLAN_DPD_FAILURE");
+ sImsCodeMap.put(CODE_EPDG_TUNNEL_ESTABLISH_FAILURE, "CODE_EPDG_TUNNEL_ESTABLISH_FAILURE");
+ sImsCodeMap.put(CODE_EPDG_TUNNEL_REKEY_FAILURE, "CODE_EPDG_TUNNEL_REKEY_FAILURE");
+ sImsCodeMap.put(CODE_EPDG_TUNNEL_LOST_CONNECTION, "CODE_EPDG_TUNNEL_LOST_CONNECTION");
+ sImsCodeMap.put(CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED,
+ "CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED");
+ sImsCodeMap.put(CODE_REMOTE_CALL_DECLINE, "CODE_REMOTE_CALL_DECLINE");
+ sImsCodeMap.put(CODE_DATA_LIMIT_REACHED, "CODE_DATA_LIMIT_REACHED");
+ sImsCodeMap.put(CODE_DATA_DISABLED, "CODE_DATA_DISABLED");
+ sImsCodeMap.put(CODE_WIFI_LOST, "CODE_WIFI_LOST");
+ sImsCodeMap.put(CODE_IKEV2_AUTH_FAILURE, "CODE_IKEV2_AUTH_FAILURE");
+ sImsCodeMap.put(CODE_RADIO_OFF, "CODE_RADIO_OFF");
+ sImsCodeMap.put(CODE_NO_VALID_SIM, "CODE_NO_VALID_SIM");
+ sImsCodeMap.put(CODE_RADIO_INTERNAL_ERROR, "CODE_RADIO_INTERNAL_ERROR");
+ sImsCodeMap.put(CODE_NETWORK_RESP_TIMEOUT, "CODE_NETWORK_RESP_TIMEOUT");
+ sImsCodeMap.put(CODE_NETWORK_REJECT, "CODE_NETWORK_REJECT");
+ sImsCodeMap.put(CODE_RADIO_ACCESS_FAILURE, "CODE_RADIO_ACCESS_FAILURE");
+ sImsCodeMap.put(CODE_RADIO_LINK_FAILURE, "CODE_RADIO_LINK_FAILURE");
+ sImsCodeMap.put(CODE_RADIO_LINK_LOST, "CODE_RADIO_LINK_LOST");
+ sImsCodeMap.put(CODE_RADIO_UPLINK_FAILURE, "CODE_RADIO_UPLINK_FAILURE");
+ sImsCodeMap.put(CODE_RADIO_SETUP_FAILURE, "CODE_RADIO_SETUP_FAILURE");
+ sImsCodeMap.put(CODE_RADIO_RELEASE_NORMAL, "CODE_RADIO_RELEASE_NORMAL");
+ sImsCodeMap.put(CODE_RADIO_RELEASE_ABNORMAL, "CODE_RADIO_RELEASE_ABNORMAL");
+ sImsCodeMap.put(CODE_ACCESS_CLASS_BLOCKED, "CODE_ACCESS_CLASS_BLOCKED");
+ sImsCodeMap.put(CODE_NETWORK_DETACH, "CODE_NETWORK_DETACH");
+ sImsCodeMap.put(CODE_SIP_ALTERNATE_EMERGENCY_CALL, "CODE_SIP_ALTERNATE_EMERGENCY_CALL");
+ sImsCodeMap.put(CODE_UNOBTAINABLE_NUMBER, "CODE_UNOBTAINABLE_NUMBER");
+ sImsCodeMap.put(CODE_NO_CSFB_IN_CS_ROAM, "CODE_NO_CSFB_IN_CS_ROAM");
+ sImsCodeMap.put(CODE_REJECT_UNKNOWN, "CODE_REJECT_UNKNOWN");
+ sImsCodeMap.put(CODE_REJECT_ONGOING_CALL_WAITING_DISABLED,
+ "CODE_REJECT_ONGOING_CALL_WAITING_DISABLED");
+ sImsCodeMap.put(CODE_REJECT_CALL_ON_OTHER_SUB, "CODE_REJECT_CALL_ON_OTHER_SUB");
+ sImsCodeMap.put(CODE_REJECT_1X_COLLISION, "CODE_REJECT_1X_COLLISION");
+ sImsCodeMap.put(CODE_REJECT_SERVICE_NOT_REGISTERED, "CODE_REJECT_SERVICE_NOT_REGISTERED");
+ sImsCodeMap.put(CODE_REJECT_CALL_TYPE_NOT_ALLOWED, "CODE_REJECT_CALL_TYPE_NOT_ALLOWED");
+ sImsCodeMap.put(CODE_REJECT_ONGOING_E911_CALL, "CODE_REJECT_ONGOING_E911_CALL");
+ sImsCodeMap.put(CODE_REJECT_ONGOING_CALL_SETUP, "CODE_REJECT_ONGOING_CALL_SETUP");
+ sImsCodeMap.put(CODE_REJECT_MAX_CALL_LIMIT_REACHED, "CODE_REJECT_MAX_CALL_LIMIT_REACHED");
+ sImsCodeMap.put(CODE_REJECT_UNSUPPORTED_SIP_HEADERS, "CODE_REJECT_UNSUPPORTED_SIP_HEADERS");
+ sImsCodeMap.put(CODE_REJECT_UNSUPPORTED_SDP_HEADERS, "CODE_REJECT_UNSUPPORTED_SDP_HEADERS");
+ sImsCodeMap.put(CODE_REJECT_ONGOING_CALL_TRANSFER, "CODE_REJECT_ONGOING_CALL_TRANSFER");
+ sImsCodeMap.put(CODE_REJECT_INTERNAL_ERROR, "CODE_REJECT_INTERNAL_ERROR");
+ sImsCodeMap.put(CODE_REJECT_QOS_FAILURE, "CODE_REJECT_QOS_FAILURE");
+ sImsCodeMap.put(CODE_REJECT_ONGOING_HANDOVER, "CODE_REJECT_ONGOING_HANDOVER");
+ sImsCodeMap.put(CODE_REJECT_VT_TTY_NOT_ALLOWED, "CODE_REJECT_VT_TTY_NOT_ALLOWED");
+ sImsCodeMap.put(CODE_REJECT_ONGOING_CALL_UPGRADE, "CODE_REJECT_ONGOING_CALL_UPGRADE");
+ sImsCodeMap.put(CODE_REJECT_CONFERENCE_TTY_NOT_ALLOWED,
+ "CODE_REJECT_CONFERENCE_TTY_NOT_ALLOWED");
+ sImsCodeMap.put(CODE_REJECT_ONGOING_CONFERENCE_CALL, "CODE_REJECT_ONGOING_CONFERENCE_CALL");
+ sImsCodeMap.put(CODE_REJECT_VT_AVPF_NOT_ALLOWED, "CODE_REJECT_VT_AVPF_NOT_ALLOWED");
+ sImsCodeMap.put(CODE_REJECT_ONGOING_ENCRYPTED_CALL, "CODE_REJECT_ONGOING_ENCRYPTED_CALL");
+ sImsCodeMap.put(CODE_REJECT_ONGOING_CS_CALL, "CODE_REJECT_ONGOING_CS_CALL");
+ sImsCodeMap.put(CODE_RETRY_ON_IMS_WITHOUT_RTT, "CODE_RETRY_ON_IMS_WITHOUT_RTT");
+ sImsCodeMap.put(CODE_OEM_CAUSE_1, "CODE_OEM_CAUSE_1");
+ sImsCodeMap.put(CODE_OEM_CAUSE_2, "CODE_OEM_CAUSE_2");
+ sImsCodeMap.put(CODE_OEM_CAUSE_3, "CODE_OEM_CAUSE_3");
+ sImsCodeMap.put(CODE_OEM_CAUSE_4, "CODE_OEM_CAUSE_4");
+ sImsCodeMap.put(CODE_OEM_CAUSE_5, "CODE_OEM_CAUSE_5");
+ sImsCodeMap.put(CODE_OEM_CAUSE_6, "CODE_OEM_CAUSE_6");
+ sImsCodeMap.put(CODE_OEM_CAUSE_7, "CODE_OEM_CAUSE_7");
+ sImsCodeMap.put(CODE_OEM_CAUSE_8, "CODE_OEM_CAUSE_8");
+ sImsCodeMap.put(CODE_OEM_CAUSE_9, "CODE_OEM_CAUSE_9");
+ sImsCodeMap.put(CODE_OEM_CAUSE_10, "CODE_OEM_CAUSE_10");
+ sImsCodeMap.put(CODE_OEM_CAUSE_11, "CODE_OEM_CAUSE_11");
+ sImsCodeMap.put(CODE_OEM_CAUSE_12, "CODE_OEM_CAUSE_12");
+ sImsCodeMap.put(CODE_OEM_CAUSE_13, "CODE_OEM_CAUSE_13");
+ sImsCodeMap.put(CODE_OEM_CAUSE_14, "CODE_OEM_CAUSE_14");
+ sImsCodeMap.put(CODE_OEM_CAUSE_15, "CODE_OEM_CAUSE_15");
+ }
+
/**
* Network string error messages.
* mExtraMessage may have these values.
@@ -1203,7 +1394,9 @@ public final class ImsReasonInfo implements Parcelable {
@NonNull
@Override
public String toString() {
- return "ImsReasonInfo :: {" + mCode + ", " + mExtraCode + ", " + mExtraMessage + "}";
+ String imsCode = (sImsCodeMap.containsKey(mCode)) ? sImsCodeMap.get(mCode) : "UNKNOWN_CODE";
+ return "ImsReasonInfo :: {" + mCode + " : " + imsCode + ", "
+ + mExtraCode + ", " + mExtraMessage + "}";
}
@Override
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
index aae6f9214c70..0c7264697cd3 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsConfigImplBase.java
@@ -89,7 +89,7 @@ public class ImsConfigImplBase {
/**
* Sets the value for IMS service/capabilities parameters by the operator device
* management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived. Synchronous blocking call.
+ * from which the main value is derived. Synchronous blocking call.
*
* @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
* @param value in Integer format.
@@ -102,7 +102,7 @@ public class ImsConfigImplBase {
/**
* Sets the value for IMS service/capabilities parameters by the operator device
* management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived. Synchronous blocking call.
+ * from which the main value is derived. Synchronous blocking call.
*
* @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
* @param value in String format.
@@ -114,7 +114,7 @@ public class ImsConfigImplBase {
/**
* Gets the value of the specified IMS feature item for specified network type.
- * This operation gets the feature config value from the master storage (i.e. final
+ * This operation gets the feature config value from the main storage (i.e. final
* value). Asynchronous non-blocking call.
*
* @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
@@ -127,7 +127,7 @@ public class ImsConfigImplBase {
/**
* Sets the value for IMS feature item for specified network type.
- * This operation stores the user setting in setting db from which master db
+ * This operation stores the user setting in setting db from which main db
* is derived.
*
* @param feature as defined in com.android.ims.ImsConfig#FeatureConstants.
@@ -268,7 +268,7 @@ public class ImsConfigImplBase {
/**
* Sets the value for IMS service/capabilities parameters by the operator device
* management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived, and write it into local cache.
+ * from which the main value is derived, and write it into local cache.
* Synchronous blocking call.
*
* @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
@@ -292,7 +292,7 @@ public class ImsConfigImplBase {
/**
* Sets the value for IMS service/capabilities parameters by the operator device
* management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived, and write it into local cache.
+ * from which the main value is derived, and write it into local cache.
* Synchronous blocking call.
*
* @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index 73ba0e393e78..8f738d216cbe 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -439,8 +439,8 @@ public class ImsCallSessionImplBase implements AutoCloseable {
* Transfer an established call to given number
*
* @param number number to transfer the call
- * @param isConfirmationRequired if {@code True}, indicates Assured transfer,
- * if {@code False} it indicates Blind transfer.
+ * @param isConfirmationRequired if {@code True}, indicates a confirmed transfer,
+ * if {@code False} it indicates an unconfirmed transfer.
* @hide
*/
public void transfer(@NonNull String number, boolean isConfirmationRequired) {
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 6a2638bc7221..4ef44d3ec9ef 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -142,7 +142,7 @@ public class ImsConfigImplBase {
/**
* Sets the value for IMS service/capabilities parameters by the operator device
* management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived, and write it into local cache.
+ * from which the main value is derived, and write it into local cache.
* Synchronous blocking call.
*
* @param item integer key
@@ -167,7 +167,7 @@ public class ImsConfigImplBase {
/**
* Sets the value for IMS service/capabilities parameters by the operator device
* management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived, and write it into local cache.
+ * from which the main value is derived, and write it into local cache.
* Synchronous blocking call.
*
* @param item as defined in com.android.ims.ImsConfig#ConfigConstants.
diff --git a/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java b/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java
index 689becd7169a..17adede86c51 100644
--- a/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java
+++ b/telephony/java/android/telephony/mbms/MbmsTempFileProvider.java
@@ -91,7 +91,7 @@ public class MbmsTempFileProvider extends ContentProvider {
public void attachInfo(Context context, ProviderInfo info) {
super.attachInfo(context, info);
- // Sanity check our security
+ // Correctness check our security
if (info.exported) {
throw new SecurityException("Provider must not be exported");
}
diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
index 0466efc2f6c6..ab14e82b7087 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
@@ -153,8 +153,8 @@ interface IImsCallSession {
* Transfer an established call to given number
*
* @param number number to transfer the call
- * @param isConfirmationRequired if {@code True}, indicates Assured transfer,
- * if {@code False} it indicates Blind transfer.
+ * @param isConfirmationRequired if {@code True}, indicates a confirmed transfer,
+ * if {@code False} it indicates an unconfirmed transfer.
*/
void transfer(String number, boolean isConfirmationRequired);
diff --git a/telephony/java/com/android/ims/internal/IImsConfig.aidl b/telephony/java/com/android/ims/internal/IImsConfig.aidl
index 7324814ae5a4..1a14e8780664 100644
--- a/telephony/java/com/android/ims/internal/IImsConfig.aidl
+++ b/telephony/java/com/android/ims/internal/IImsConfig.aidl
@@ -49,7 +49,7 @@ interface IImsConfig {
/**
* Sets the value for IMS service/capabilities parameters by the operator device
* management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived. Synchronous blocking call.
+ * from which the main value is derived. Synchronous blocking call.
*
* @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
* @param value in Integer format.
@@ -60,7 +60,7 @@ interface IImsConfig {
/**
* Sets the value for IMS service/capabilities parameters by the operator device
* management entity. It sets the config item value in the provisioned storage
- * from which the master value is derived. Synchronous blocking call.
+ * from which the main value is derived. Synchronous blocking call.
*
* @param item, as defined in com.android.ims.ImsConfig#ConfigConstants.
* @param value in String format.
@@ -70,7 +70,7 @@ interface IImsConfig {
/**
* Gets the value of the specified IMS feature item for specified network type.
- * This operation gets the feature config value from the master storage (i.e. final
+ * This operation gets the feature config value from the main storage (i.e. final
* value). Asynchronous non-blocking call.
*
* @param feature. as defined in com.android.ims.ImsConfig#FeatureConstants.
@@ -82,7 +82,7 @@ interface IImsConfig {
/**
* Sets the value for IMS feature item for specified network type.
- * This operation stores the user setting in setting db from which master db
+ * This operation stores the user setting in setting db from which main db
* is dervied.
*
* @param feature. as defined in com.android.ims.ImsConfig#FeatureConstants.
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 542e08d743ab..a34e474e666e 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -479,7 +479,7 @@ public class SmsMessage extends SmsMessageBase {
length = dis.readUnsignedByte();
addr.numberOfDigits = length;
- // sanity check on the length
+ // Correctness check on the length
if (length > pdu.length) {
throw new RuntimeException(
"createFromPdu: Invalid pdu, addr.numberOfDigits " + length
@@ -496,7 +496,7 @@ public class SmsMessage extends SmsMessageBase {
//encoded BearerData:
bearerDataLength = dis.readInt();
- // sanity check on the length
+ // Correctness check on the length
if (bearerDataLength > pdu.length) {
throw new RuntimeException(
"createFromPdu: Invalid pdu, bearerDataLength " + bearerDataLength
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index 7e31c4633050..e3df903b7f4f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -353,7 +353,7 @@ public class SmsMessage extends SmsMessageBase {
statusReportRequested, ret);
// Skip encoding pdu if error occurs when create pdu head and the error will be handled
- // properly later on encodedMessage sanity check.
+ // properly later on encodedMessage correctness check.
if (bo == null) return ret;
// User Data (and length)
@@ -535,7 +535,7 @@ public class SmsMessage extends SmsMessageBase {
scAddress, destinationAddress, (byte) 0x41, /* TP-MTI=SMS-SUBMIT, TP-UDHI=true */
statusReportRequested, ret);
// Skip encoding pdu if error occurs when create pdu head and the error will be handled
- // properly later on encodedMessage sanity check.
+ // properly later on encodedMessage correctness check.
if (bo == null) return ret;
// TP-Data-Coding-Scheme
diff --git a/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java b/tests/BlobStoreTestUtils/src/com/android/utils/blob/FakeBlobData.java
index 2df0024bdea9..56db4f98e160 100644
--- a/tests/BlobStoreTestUtils/src/com/android/utils/blob/DummyBlobData.java
+++ b/tests/BlobStoreTestUtils/src/com/android/utils/blob/FakeBlobData.java
@@ -35,7 +35,7 @@ import java.security.MessageDigest;
import java.util.Random;
import java.util.concurrent.TimeUnit;
-public class DummyBlobData {
+public class FakeBlobData {
private static final long DEFAULT_SIZE_BYTES = 10 * 1024L * 1024L;
private final Random mRandom;
@@ -47,7 +47,7 @@ public class DummyBlobData {
byte[] mFileDigest;
long mExpiryTimeMs;
- private DummyBlobData(Builder builder) {
+ private FakeBlobData(Builder builder) {
mRandom = new Random(builder.getRandomSeed());
mFile = new File(builder.getContext().getFilesDir(), builder.getFileName());
mFileSize = builder.getFileSize();
@@ -116,8 +116,8 @@ public class DummyBlobData {
return mExpiryDurationMs;
}
- public DummyBlobData build() {
- return new DummyBlobData(this);
+ public FakeBlobData build() {
+ return new FakeBlobData(this);
}
}
diff --git a/tests/BootImageProfileTest/OWNERS b/tests/BootImageProfileTest/OWNERS
index 657b3f2add2e..7ee0d9a5e77e 100644
--- a/tests/BootImageProfileTest/OWNERS
+++ b/tests/BootImageProfileTest/OWNERS
@@ -1,4 +1,4 @@
-mathieuc@google.com
calin@google.com
+mathieuc@google.com
+ngeoffray@google.com
yawanng@google.com
-sehr@google.com
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 5161fba026db..952997efa0d4 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -24,6 +24,7 @@ android_test {
test_suites: ["device-tests"],
libs: ["android.test.runner"],
static_libs: [
+ "androidx.test.ext.junit",
"flickertestapplib",
"flickerlib",
"truth-prebuilt",
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
new file mode 100644
index 000000000000..c1a3ed695096
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -0,0 +1,153 @@
+/*
+ * 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.wm.flicker
+
+import com.android.server.wm.flicker.dsl.EventLogAssertion
+import com.android.server.wm.flicker.dsl.LayersAssertion
+import com.android.server.wm.flicker.dsl.WmAssertion
+import com.android.server.wm.flicker.helpers.WindowUtils
+
+@JvmOverloads
+fun WmAssertion.statusBarWindowIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("statusBarWindowIsAlwaysVisible", enabled, bugId) {
+ this.showsAboveAppWindow(FlickerTestBase.STATUS_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun WmAssertion.navBarWindowIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("navBarWindowIsAlwaysVisible", enabled, bugId) {
+ this.showsAboveAppWindow(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.noUncoveredRegions(
+ beginRotation: Int,
+ endRotation: Int = beginRotation,
+ allStates: Boolean = true,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
+ val endingBounds = WindowUtils.getDisplayBounds(endRotation)
+ if (allStates) {
+ all("noUncoveredRegions", enabled, bugId) {
+ if (startingBounds == endingBounds) {
+ this.coversAtLeastRegion(startingBounds)
+ } else {
+ this.coversAtLeastRegion(startingBounds)
+ .then()
+ .coversAtLeastRegion(endingBounds)
+ }
+ }
+ } else {
+ start("noUncoveredRegions_StartingPos") {
+ this.coversAtLeastRegion(startingBounds)
+ }
+ end("noUncoveredRegions_EndingPos") {
+ this.coversAtLeastRegion(endingBounds)
+ }
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.navBarLayerIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("navBarLayerIsAlwaysVisible", enabled, bugId) {
+ this.showsLayer(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.statusBarLayerIsAlwaysVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("statusBarLayerIsAlwaysVisible", enabled, bugId) {
+ this.showsLayer(FlickerTestBase.STATUS_BAR_WINDOW_TITLE)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.navBarLayerRotatesAndScales(
+ beginRotation: Int,
+ endRotation: Int = beginRotation,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ val startingPos = WindowUtils.getNavigationBarPosition(beginRotation)
+ val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
+
+ start("navBarLayerRotatesAndScales_StartingPos", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, startingPos)
+ }
+ end("navBarLayerRotatesAndScales_EndingPost", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, endingPos)
+ }
+
+ if (startingPos == endingPos) {
+ all("navBarLayerRotatesAndScales", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, startingPos)
+ }
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.statusBarLayerRotatesScales(
+ beginRotation: Int,
+ endRotation: Int = beginRotation,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ val startingPos = WindowUtils.getStatusBarPosition(beginRotation)
+ val endingPos = WindowUtils.getStatusBarPosition(endRotation)
+
+ start("statusBarLayerRotatesScales_StartingPos", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.STATUS_BAR_WINDOW_TITLE, startingPos)
+ }
+ end("statusBarLayerRotatesScales_EndingPos", enabled, bugId) {
+ this.hasVisibleRegion(FlickerTestBase.STATUS_BAR_WINDOW_TITLE, endingPos)
+ }
+}
+
+fun EventLogAssertion.focusChanges(
+ vararg windows: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all(enabled = enabled, bugId = bugId) {
+ this.focusChanges(windows)
+ }
+}
+
+fun EventLogAssertion.focusDoesNotChange(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all(enabled = enabled, bugId = bugId) {
+ this.focusDoesNotChange()
+ }
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.kt
deleted file mode 100644
index b69e6a9736a3..000000000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonTransitions.kt
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * 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.wm.flicker
-
-import android.app.Instrumentation
-import android.content.Context
-import android.content.Intent
-import android.os.RemoteException
-import android.os.SystemClock
-import android.platform.helpers.IAppHelper
-import android.util.Rational
-import android.view.Surface
-import androidx.test.uiautomator.By
-import androidx.test.uiautomator.UiDevice
-import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.helpers.AutomationUtils
-import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.helpers.PipAppHelper
-
-/**
- * Collection of common transitions which can be used to test different apps or scenarios.
- */
-internal object CommonTransitions {
- private const val ITERATIONS = 1
- private const val APP_LAUNCH_TIMEOUT: Long = 10000
- private fun setRotation(device: UiDevice, rotation: Int) {
- try {
- when (rotation) {
- Surface.ROTATION_270 -> device.setOrientationLeft()
- Surface.ROTATION_90 -> device.setOrientationRight()
- Surface.ROTATION_0 -> device.setOrientationNatural()
- else -> device.setOrientationNatural()
- }
- // Wait for animation to complete
- SystemClock.sleep(1000)
- } catch (e: RemoteException) {
- throw RuntimeException(e)
- }
- }
-
- /**
- * Build a test tag for the test
- * @param testName Name of the transition(s) being tested
- * @param app App being launcher
- * @param rotation Initial screen rotation
- *
- * @return test tag with pattern <NAME>__<APP>__<ROTATION>
- </ROTATION></APP></NAME> */
- private fun buildTestTag(testName: String, app: IAppHelper, rotation: Int): String {
- return buildTestTag(
- testName, app, rotation, rotation, app2 = null, extraInfo = "")
- }
-
- /**
- * Build a test tag for the test
- * @param testName Name of the transition(s) being tested
- * @param app App being launcher
- * @param beginRotation Initial screen rotation
- * @param endRotation End screen rotation (if any, otherwise use same as initial)
- *
- * @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
- </END_ROTATION></BEGIN_ROTATION></APP></NAME> */
- private fun buildTestTag(
- testName: String,
- app: IAppHelper,
- beginRotation: Int,
- endRotation: Int
- ): String {
- return buildTestTag(
- testName, app, beginRotation, endRotation, app2 = null, extraInfo = "")
- }
-
- /**
- * Build a test tag for the test
- * @param testName Name of the transition(s) being tested
- * @param app App being launcher
- * @param app2 Second app being launched (if any)
- * @param beginRotation Initial screen rotation
- * @param endRotation End screen rotation (if any, otherwise use same as initial)
- * @param extraInfo Additional information to append to the tag
- *
- * @return test tag with pattern <NAME>__<APP></APP>(S)>__<ROTATION></ROTATION>(S)>[__<EXTRA>]
- </EXTRA></NAME> */
- private fun buildTestTag(
- testName: String,
- app: IAppHelper,
- beginRotation: Int,
- endRotation: Int,
- app2: IAppHelper?,
- extraInfo: String
- ): String {
- val testTag = StringBuilder()
- testTag.append(testName)
- .append("__")
- .append(app.launcherName)
- if (app2 != null) {
- testTag.append("-")
- .append(app2.launcherName)
- }
- testTag.append("__")
- .append(Surface.rotationToString(beginRotation))
- if (endRotation != beginRotation) {
- testTag.append("-")
- .append(Surface.rotationToString(endRotation))
- }
- if (extraInfo.isNotEmpty()) {
- testTag.append("__")
- .append(extraInfo)
- }
- return testTag.toString()
- }
-
- fun openAppWarm(
- testApp: IAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("openAppWarm", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBeforeAll { setRotation(device, beginRotation) }
- .runBeforeAll { testApp.open() }
- .runBefore { device.pressHome() }
- .runBefore { device.waitForIdle() }
- .runBefore { setRotation(device, beginRotation) }
- .run { testApp.open() }
- .runAfterAll { testApp.exit() }
- .runAfterAll { AutomationUtils.setDefaultWait() }
- .repeat(ITERATIONS)
- }
-
- fun closeAppWithBackKey(
- testApp: IAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("closeAppWithBackKey", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBefore { testApp.open() }
- .runBefore { device.waitForIdle() }
- .run { device.pressBack() }
- .run { device.waitForIdle() }
- .runAfterAll { testApp.exit() }
- .runAfterAll { AutomationUtils.setDefaultWait() }
- .repeat(ITERATIONS)
- }
-
- fun closeAppWithHomeKey(
- testApp: IAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("closeAppWithHomeKey", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBefore { testApp.open() }
- .runBefore { device.waitForIdle() }
- .run { device.pressHome() }
- .run { device.waitForIdle() }
- .runAfterAll { testApp.exit() }
- .runAfterAll { AutomationUtils.setDefaultWait() }
- .repeat(ITERATIONS)
- }
-
- fun openAppCold(
- testApp: IAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("openAppCold", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBefore { device.pressHome() }
- .runBeforeAll { setRotation(device, beginRotation) }
- .runBefore { testApp.exit() }
- .runBefore { device.waitForIdle() }
- .run { testApp.open() }
- .runAfterAll { testApp.exit() }
- .runAfterAll { setRotation(device, Surface.ROTATION_0) }
- .repeat(ITERATIONS)
- }
-
- fun changeAppRotation(
- testApp: IAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int,
- endRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("changeAppRotation", testApp, beginRotation, endRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBeforeAll { testApp.open() }
- .runBefore { setRotation(device, beginRotation) }
- .run { setRotation(device, endRotation) }
- .runAfterAll { testApp.exit() }
- .runAfterAll { setRotation(device, Surface.ROTATION_0) }
- .repeat(ITERATIONS)
- }
-
- fun changeAppRotation(
- intent: Intent,
- intentId: String,
- context: Context,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int,
- endRotation: Int
- ): TransitionRunner.TransitionBuilder {
- val testTag = "changeAppRotation_" + intentId + "_" +
- Surface.rotationToString(beginRotation) + "_" +
- Surface.rotationToString(endRotation)
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(testTag)
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBeforeAll {
- context.startActivity(intent)
- device.wait(Until.hasObject(By.pkg(intent.component?.packageName)
- .depth(0)), APP_LAUNCH_TIMEOUT)
- }
- .runBefore { setRotation(device, beginRotation) }
- .run { setRotation(device, endRotation) }
- .runAfterAll { AutomationUtils.stopPackage(context, intent.component?.packageName) }
- .runAfterAll { setRotation(device, Surface.ROTATION_0) }
- .repeat(ITERATIONS)
- }
-
- fun appToSplitScreen(
- testApp: IAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("appToSplitScreen", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBeforeAll { setRotation(device, beginRotation) }
- .runBefore { testApp.open() }
- .runBefore { device.waitForIdle() }
- .runBefore { SystemClock.sleep(500) }
- .run { AutomationUtils.launchSplitScreen(device) }
- .runAfter { AutomationUtils.exitSplitScreen(device) }
- .runAfterAll { testApp.exit() }
- .repeat(ITERATIONS)
- }
-
- fun splitScreenToLauncher(
- testApp: IAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("splitScreenToLauncher", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBefore { testApp.open() }
- .runBefore { device.waitForIdle() }
- .runBefore { AutomationUtils.launchSplitScreen(device) }
- .run { AutomationUtils.exitSplitScreen(device) }
- .runAfterAll { testApp.exit() }
- .repeat(ITERATIONS)
- }
-
- fun editTextSetFocus(
- testApp: ImeAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("editTextSetFocus", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBefore { device.pressHome() }
- .runBefore { setRotation(device, beginRotation) }
- .runBefore { testApp.open() }
- .run { testApp.openIME(device) }
- .runAfterAll { testApp.exit() }
- .repeat(ITERATIONS)
- }
-
- fun resizeSplitScreen(
- testAppTop: IAppHelper,
- testAppBottom: ImeAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int,
- startRatio: Rational,
- stopRatio: Rational
- ): TransitionRunner.TransitionBuilder {
- val description = (startRatio.toString().replace("/", "-") + "_to_" +
- stopRatio.toString().replace("/", "-"))
- val testTag = buildTestTag("resizeSplitScreen", testAppTop, beginRotation,
- beginRotation, testAppBottom, description)
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(testTag)
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBeforeAll { setRotation(device, beginRotation) }
- .runBeforeAll { AutomationUtils.clearRecents(instrumentation) }
- .runBefore { testAppBottom.open() }
- .runBefore { device.pressHome() }
- .runBefore { testAppTop.open() }
- .runBefore { device.waitForIdle() }
- .runBefore { AutomationUtils.launchSplitScreen(device) }
- .runBefore {
- val snapshot = device.findObject(
- By.res(device.launcherPackageName, "snapshot"))
- snapshot.click()
- }
- .runBefore { testAppBottom.openIME(device) }
- .runBefore { device.pressBack() }
- .runBefore { AutomationUtils.resizeSplitScreen(device, startRatio) }
- .run { AutomationUtils.resizeSplitScreen(device, stopRatio) }
- .runAfter { AutomationUtils.exitSplitScreen(device) }
- .runAfter { device.pressHome() }
- .runAfterAll { testAppTop.exit() }
- .runAfterAll { testAppBottom.exit() }
- .repeat(ITERATIONS)
- }
-
- fun editTextLoseFocusToHome(
- testApp: ImeAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("editTextLoseFocusToHome", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBefore { device.pressHome() }
- .runBefore { setRotation(device, beginRotation) }
- .runBefore { testApp.open() }
- .runBefore { testApp.openIME(device) }
- .run { device.pressHome() }
- .run { device.waitForIdle() }
- .runAfterAll { testApp.exit() }
- .repeat(ITERATIONS)
- }
-
- fun editTextLoseFocusToApp(
- testApp: ImeAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("editTextLoseFocusToApp", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBefore { device.pressHome() }
- .runBefore { setRotation(device, beginRotation) }
- .runBefore { testApp.open() }
- .runBefore { testApp.openIME(device) }
- .run { device.pressBack() }
- .run { device.waitForIdle() }
- .runAfterAll { testApp.exit() }
- .repeat(ITERATIONS)
- }
-
- fun enterPipMode(
- testApp: PipAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("enterPipMode", testApp, beginRotation))
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBefore { device.pressHome() }
- .runBefore { setRotation(device, beginRotation) }
- .runBefore { testApp.open() }
- .run { testApp.clickEnterPipButton(device) }
- .runAfter { testApp.closePipWindow(device) }
- .runAfterAll { testApp.exit() }
- .repeat(ITERATIONS)
- }
-
- fun exitPipModeToHome(
- testApp: PipAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("exitPipModeToHome", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .runBefore { device.pressHome() }
- .runBefore { setRotation(device, beginRotation) }
- .runBefore { testApp.open() }
- .run { testApp.clickEnterPipButton(device) }
- .run { testApp.closePipWindow(device) }
- .run { device.waitForIdle() }
- .run { testApp.exit() }
- .repeat(ITERATIONS)
- }
-
- fun exitPipModeToApp(
- testApp: PipAppHelper,
- instrumentation: Instrumentation,
- device: UiDevice,
- beginRotation: Int
- ): TransitionRunner.TransitionBuilder {
- return TransitionRunner.TransitionBuilder(instrumentation)
- .withTag(buildTestTag("exitPipModeToApp", testApp, beginRotation))
- .recordAllRuns()
- .runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
- .run { device.pressHome() }
- .run { setRotation(device, beginRotation) }
- .run { testApp.open() }
- .run { testApp.clickEnterPipButton(device) }
- .run { AutomationUtils.expandPipWindow(device) }
- .run { device.waitForIdle() }
- .run { testApp.exit() }
- .repeat(ITERATIONS)
- }
-} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.kt
deleted file mode 100644
index 43cfdffb6efb..000000000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/DebugTest.kt
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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.wm.flicker
-
-import android.platform.helpers.IAppHelper
-import android.util.Rational
-import android.view.Surface
-import androidx.test.InstrumentationRegistry
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.LargeTest
-import androidx.test.runner.AndroidJUnit4
-import androidx.test.uiautomator.UiDevice
-import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.android.server.wm.flicker.helpers.PipAppHelper
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-
-/**
- * Tests to help debug individual transitions, capture video recordings and create test cases.
- *
- * Not actual tests
- */
-@LargeTest
-@FlakyTest
-@RunWith(AndroidJUnit4::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class DebugTest {
- private val instrumentation = InstrumentationRegistry.getInstrumentation()
- private val testApp: IAppHelper = StandardAppHelper(instrumentation,
- "com.android.server.wm.flicker.testapp", "SimpleApp")
- private val uiDevice = UiDevice.getInstance(instrumentation)
-
- /**
- * atest FlickerTests:DebugTest#openAppCold
- */
- @Test
- fun openAppCold() {
- CommonTransitions.openAppCold(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
- .recordAllRuns().build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#openAppWarm
- */
- @Test
- fun openAppWarm() {
- CommonTransitions.openAppWarm(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
- .recordAllRuns().build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#changeOrientationFromNaturalToLeft
- */
- @Test
- fun changeOrientationFromNaturalToLeft() {
- CommonTransitions.changeAppRotation(testApp, instrumentation, uiDevice, Surface.ROTATION_0,
- Surface.ROTATION_270).recordAllRuns().build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#closeAppWithBackKey
- */
- @Test
- fun closeAppWithBackKey() {
- CommonTransitions.closeAppWithBackKey(testApp, instrumentation, uiDevice,
- Surface.ROTATION_0).recordAllRuns().build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#closeAppWithHomeKey
- */
- @Test
- fun closeAppWithHomeKey() {
- CommonTransitions.closeAppWithHomeKey(testApp, instrumentation, uiDevice,
- Surface.ROTATION_0).recordAllRuns().build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#openAppToSplitScreen
- */
- @Test
- fun openAppToSplitScreen() {
- CommonTransitions.appToSplitScreen(testApp, instrumentation, uiDevice,
- Surface.ROTATION_0).includeJankyRuns().recordAllRuns()
- .build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#splitScreenToLauncher
- */
- @Test
- fun splitScreenToLauncher() {
- CommonTransitions.splitScreenToLauncher(testApp, instrumentation, uiDevice,
- Surface.ROTATION_0).includeJankyRuns().recordAllRuns().build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#resizeSplitScreen
- */
- @Test
- fun resizeSplitScreen() {
- val bottomApp = ImeAppHelper(instrumentation)
- CommonTransitions.resizeSplitScreen(
- testApp,
- bottomApp,
- instrumentation,
- uiDevice,
- Surface.ROTATION_0,
- Rational(1, 3), Rational(2, 3)
- ).includeJankyRuns().build().run()
- }
- // IME tests
- /**
- * atest FlickerTests:DebugTest#editTextSetFocus
- */
- @Test
- fun editTextSetFocus() {
- val testApp = ImeAppHelper(instrumentation)
- CommonTransitions.editTextSetFocus(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
- .includeJankyRuns()
- .build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#editTextLoseFocusToHome
- */
- @Test
- fun editTextLoseFocusToHome() {
- val testApp = ImeAppHelper(instrumentation)
- CommonTransitions.editTextLoseFocusToHome(testApp, instrumentation, uiDevice,
- Surface.ROTATION_0).includeJankyRuns().build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#editTextLoseFocusToApp
- */
- @Test
- fun editTextLoseFocusToApp() {
- val testApp = ImeAppHelper(instrumentation)
- CommonTransitions.editTextLoseFocusToHome(testApp, instrumentation, uiDevice,
- Surface.ROTATION_0).includeJankyRuns().build().run()
- }
- // PIP tests
- /**
- * atest FlickerTests:DebugTest#enterPipMode
- */
- @Test
- fun enterPipMode() {
- val testApp = PipAppHelper(instrumentation)
- CommonTransitions.enterPipMode(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
- .includeJankyRuns().build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#exitPipModeToHome
- */
- @Test
- fun exitPipModeToHome() {
- val testApp = PipAppHelper(instrumentation)
- CommonTransitions.exitPipModeToHome(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
- .includeJankyRuns()
- .build().run()
- }
-
- /**
- * atest FlickerTests:DebugTest#exitPipModeToApp
- */
- @Test
- fun exitPipModeToApp() {
- val testApp = PipAppHelper(instrumentation)
- CommonTransitions.exitPipModeToApp(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
- .includeJankyRuns().build().run()
- }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.kt
index d7586d0db915..abe7dbc57002 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/FlickerTestBase.kt
@@ -16,15 +16,12 @@
package com.android.server.wm.flicker
+import android.os.RemoteException
+import android.os.SystemClock
import android.platform.helpers.IAppHelper
-import android.util.Log
-import androidx.test.InstrumentationRegistry
+import android.view.Surface
+import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
-import com.android.server.wm.flicker.helpers.AutomationUtils
-import com.google.common.truth.Truth
-import org.junit.After
-import org.junit.AfterClass
-import org.junit.Before
/**
* Base class of all Flicker test that performs common functions for all flicker tests:
@@ -37,101 +34,96 @@ import org.junit.Before
* - Fails tests if results are not available for any test due to jank.
*/
abstract class FlickerTestBase {
- lateinit var testApp: IAppHelper
- open val instrumentation by lazy {
+ val instrumentation by lazy {
InstrumentationRegistry.getInstrumentation()
}
val uiDevice by lazy {
UiDevice.getInstance(instrumentation)
}
- lateinit var tesults: List<TransitionResult>
- private var lastResult: TransitionResult? = null
/**
- * Runs a transition, returns a cached result if the transition has run before.
- */
- fun run(transition: TransitionRunner) {
- if (transitionResults.containsKey(transition.testTag)) {
- tesults = transitionResults[transition.testTag]
- ?: throw IllegalStateException("Results do not contain test tag " +
- transition.testTag)
- return
- }
- tesults = transition.run().results
- /* Fail if we don't have any results due to jank */
- Truth.assertWithMessage("No results to test because all transition runs were invalid " +
- "because of Jank").that(tesults).isNotEmpty()
- transitionResults[transition.testTag] = tesults
+ * Build a test tag for the test
+ * @param testName Name of the transition(s) being tested
+ * @param app App being launcher
+ * @param rotation Initial screen rotation
+ *
+ * @return test tag with pattern <NAME>__<APP>__<ROTATION>
+ </ROTATION></APP></NAME> */
+ protected fun buildTestTag(testName: String, app: IAppHelper, rotation: Int): String {
+ return buildTestTag(
+ testName, app, rotation, rotation, app2 = null, extraInfo = "")
}
/**
- * Runs a transition, returns a cached result if the transition has run before.
- */
- @Before
- fun runTransition() {
- run(transitionToRun)
+ * Build a test tag for the test
+ * @param testName Name of the transition(s) being tested
+ * @param app App being launcher
+ * @param beginRotation Initial screen rotation
+ * @param endRotation End screen rotation (if any, otherwise use same as initial)
+ *
+ * @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
+ </END_ROTATION></BEGIN_ROTATION></APP></NAME> */
+ protected fun buildTestTag(
+ testName: String,
+ app: IAppHelper,
+ beginRotation: Int,
+ endRotation: Int
+ ): String {
+ return buildTestTag(
+ testName, app, beginRotation, endRotation, app2 = null, extraInfo = "")
}
/**
- * Gets the transition that will be executed
- */
- abstract val transitionToRun: TransitionRunner
-
- /**
- * Goes through a list of transition results and checks assertions on each result.
- */
- fun checkResults(assertion: (TransitionResult) -> Unit) {
- for (result in tesults) {
- lastResult = result
- assertion(result)
+ * Build a test tag for the test
+ * @param testName Name of the transition(s) being tested
+ * @param app App being launcher
+ * @param app2 Second app being launched (if any)
+ * @param beginRotation Initial screen rotation
+ * @param endRotation End screen rotation (if any, otherwise use same as initial)
+ * @param extraInfo Additional information to append to the tag
+ *
+ * @return test tag with pattern <NAME>__<APP></APP>(S)>__<ROTATION></ROTATION>(S)>[__<EXTRA>]
+ </EXTRA></NAME> */
+ protected fun buildTestTag(
+ testName: String,
+ app: IAppHelper,
+ beginRotation: Int,
+ endRotation: Int,
+ app2: IAppHelper?,
+ extraInfo: String
+ ): String {
+ var testTag = "${testName}__${app.launcherName}"
+ if (app2 != null) {
+ testTag += "-${app2.launcherName}"
+ }
+ testTag += "__${Surface.rotationToString(beginRotation)}"
+ if (endRotation != beginRotation) {
+ testTag += "-${Surface.rotationToString(endRotation)}"
+ }
+ if (extraInfo.isNotEmpty()) {
+ testTag += "__$extraInfo"
}
- lastResult = null
+ return testTag
}
- /**
- * Kludge to mark a file for saving. If `checkResults` fails, the last result is not
- * cleared. This indicates the assertion failed for the result, so mark it for saving.
- */
- @After
- fun markArtifactsForSaving() {
- lastResult?.flagForSaving()
+ protected fun Flicker.setRotation(rotation: Int) {
+ try {
+ when (rotation) {
+ Surface.ROTATION_270 -> device.setOrientationLeft()
+ Surface.ROTATION_90 -> device.setOrientationRight()
+ Surface.ROTATION_0 -> device.setOrientationNatural()
+ else -> device.setOrientationNatural()
+ }
+ // Wait for animation to complete
+ SystemClock.sleep(1000)
+ } catch (e: RemoteException) {
+ throw RuntimeException(e)
+ }
}
companion object {
- const val TAG = "FLICKER"
const val NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar"
const val STATUS_BAR_WINDOW_TITLE = "StatusBar"
const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
- private val transitionResults = mutableMapOf<String, List<TransitionResult>>()
-
- /**
- * Teardown any system settings and clean up test artifacts from the file system.
- *
- * Note: test artifacts for failed tests will remain on the device.
- */
- @AfterClass
- @JvmStatic
- fun teardown() {
- AutomationUtils.setDefaultWait()
- transitionResults.values
- .flatten()
- .forEach {
- if (it.canDelete()) {
- it.delete()
- } else {
- if (it.layersTraceExists()) {
- Log.e(TAG, "Layers trace saved to ${it.layersTracePath}")
- }
- if (it.windowManagerTraceExists()) {
- Log.e(TAG,
- "WindowManager trace saved to ${it.windowManagerTracePath}")
- }
- if (it.screenCaptureVideoExists()) {
- Log.e(TAG,
- "Screen capture video saved to ${it.screenCaptureVideoPath()}")
- }
- }
- }
- }
}
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/NonRotationTestBase.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/NonRotationTestBase.kt
index 1f8150c0977b..e7d1f8e94dba 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/NonRotationTestBase.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/NonRotationTestBase.kt
@@ -17,52 +17,20 @@
package com.android.server.wm.flicker
import android.view.Surface
-import androidx.test.filters.FlakyTest
-import org.junit.Test
import org.junit.runners.Parameterized
abstract class NonRotationTestBase(
- beginRotationName: String,
- protected val beginRotation: Int
+ protected val rotationName: String,
+ protected val rotation: Int
) : FlickerTestBase() {
- @FlakyTest(bugId = 141361128)
- @Test
- fun checkCoveredRegion_noUncoveredRegions() {
- val displayBounds = WindowUtils.getDisplayBounds(beginRotation)
- checkResults {
- LayersTraceSubject.assertThat(it).coversRegion(
- displayBounds).forAllEntries()
- }
- }
-
- @FlakyTest(bugId = 141361128)
- @Test
- fun checkVisibility_navBarLayerIsAlwaysVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
- }
- }
-
- @FlakyTest(bugId = 141361128)
- @Test
- fun checkVisibility_statusBarLayerIsAlwaysVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries()
- }
- }
-
companion object {
+ const val SCREENSHOT_LAYER = "RotationLayer"
+
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<Array<Any>> {
val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90)
- val params: MutableCollection<Array<Any>> = ArrayList()
- for (begin in supportedRotations) {
- params.add(arrayOf(Surface.rotationToString(begin), begin))
- }
- return params
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
}
}
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/RotationTestBase.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/RotationTestBase.kt
index dfc3c07d5417..3b6772779029 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/RotationTestBase.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/RotationTestBase.kt
@@ -17,8 +17,6 @@
package com.android.server.wm.flicker
import android.view.Surface
-import androidx.test.filters.FlakyTest
-import org.junit.Test
import org.junit.runners.Parameterized
abstract class RotationTestBase(
@@ -27,82 +25,7 @@ abstract class RotationTestBase(
protected val beginRotation: Int,
protected val endRotation: Int
) : FlickerTestBase() {
- @FlakyTest(bugId = 140855415)
- @Test
- fun checkVisibility_navBarWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
- }
- }
-
- @FlakyTest(bugId = 140855415)
- @Test
- fun checkVisibility_statusBarWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries()
- }
- }
-
- @Test
- fun checkPosition_navBarLayerRotatesAndScales() {
- val startingPos = WindowUtils.getNavigationBarPosition(beginRotation)
- val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
- if (startingPos == endingPos) {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
- .forAllEntries()
- }
- } else {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
- .inTheBeginning()
- }
- checkResults {
- LayersTraceSubject.assertThat(it)
- .hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, endingPos)
- .atTheEnd()
- }
- }
- }
-
- @Test
- fun checkPosition_statusBarLayerRotatesScales() {
- val startingPos = WindowUtils.getStatusBarPosition(beginRotation)
- val endingPos = WindowUtils.getStatusBarPosition(endRotation)
- checkResults {
- LayersTraceSubject.assertThat(it)
- .hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, startingPos)
- .inTheBeginning()
- LayersTraceSubject.assertThat(it)
- .hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, endingPos).atTheEnd()
- }
- }
-
- @FlakyTest(bugId = 140855415)
- @Test
- fun checkVisibility_navBarLayerIsAlwaysVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
- }
- }
-
- @FlakyTest(bugId = 140855415)
- @Test
- fun checkVisibility_statusBarLayerIsAlwaysVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries()
- }
- }
-
companion object {
- const val SCREENSHOT_LAYER = "RotationLayer"
-
@Parameterized.Parameters(name = "{0}-{1}")
@JvmStatic
fun getParams(): Collection<Array<Any>> {
@@ -123,4 +46,4 @@ abstract class RotationTestBase(
return params
}
}
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt
index e579533d2bb7..71475774343a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt
@@ -17,14 +17,15 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.support.test.launcherhelper.ILauncherStrategy
import com.android.server.wm.flicker.StandardAppHelper
abstract class FlickerAppHelper(
instr: Instrumentation,
- launcherName: String
-) : StandardAppHelper(instr, sFlickerPackage, launcherName) {
+ launcherName: String,
+ launcherStrategy: ILauncherStrategy
+) : StandardAppHelper(instr, sFlickerPackage, launcherName, launcherStrategy) {
companion object {
- var sFindTimeout = 10000
var sFlickerPackage = "com.android.server.wm.flicker.testapp"
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index 979cbeaca539..c1b765790ce5 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -17,6 +17,8 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.support.test.launcherhelper.ILauncherStrategy
+import android.support.test.launcherhelper.LauncherStrategyFactory
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
@@ -24,17 +26,26 @@ import org.junit.Assert
open class ImeAppHelper(
instr: Instrumentation,
- launcherName: String = "ImeApp"
-) : FlickerAppHelper(instr, launcherName) {
+ launcherName: String = "ImeApp",
+ launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
+ .getInstance(instr)
+ .launcherStrategy
+) : FlickerAppHelper(instr, launcherName, launcherStrategy) {
open fun openIME(device: UiDevice) {
val editText = device.wait(
Until.findObject(By.res(getPackage(), "plain_text_input")),
- AutomationUtils.FIND_TIMEOUT)
+ FIND_TIMEOUT)
Assert.assertNotNull("Text field not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)", editText)
editText.click()
- if (!AutomationUtils.waitForIME(device)) {
+ if (!device.waitForIME()) {
Assert.fail("IME did not appear")
}
}
+
+ open fun closeIME(device: UiDevice) {
+ device.pressBack()
+ // Using only the AccessibilityInfo it is not possible to identify if the IME is active
+ device.waitForIdle(1000)
+ }
} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index daee810b6899..d10bb1ef3ee7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -17,20 +17,27 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
+import android.support.test.launcherhelper.ILauncherStrategy
+import android.support.test.launcherhelper.LauncherStrategyFactory
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import org.junit.Assert
-class PipAppHelper(instr: Instrumentation) : FlickerAppHelper(instr, "PipApp") {
+class PipAppHelper(
+ instr: Instrumentation,
+ launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
+ .getInstance(instr)
+ .launcherStrategy
+) : FlickerAppHelper(instr, "PipApp", launcherStrategy) {
fun clickEnterPipButton(device: UiDevice) {
val enterPipButton = device.findObject(By.res(getPackage(), "enter_pip"))
Assert.assertNotNull("Pip button not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)", enterPipButton)
enterPipButton.click()
- AutomationUtils.hasPipWindow(device)
+ device.hasPipWindow()
}
fun closePipWindow(device: UiDevice) {
- AutomationUtils.closePipWindow(device)
+ device.closePipWindow()
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
index 814cdcf5e114..80d039475fab 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
@@ -16,11 +16,19 @@
package com.android.server.wm.flicker.ime
-import androidx.test.filters.FlakyTest
+import android.view.Surface
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.TransitionRunner
+import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -35,33 +43,52 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class CloseImeAutoOpenWindowToAppTest(
- beginRotationName: String,
- beginRotation: Int
-) : CloseImeWindowToAppTest(beginRotationName, beginRotation) {
- init {
- testApp = ImeAppAutoFocusHelper(instrumentation)
- }
-
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.editTextLoseFocusToApp(testApp as ImeAppAutoFocusHelper,
- instrumentation, uiDevice, beginRotation)
- .includeJankyRuns().build()
+ rotationName: String,
+ rotation: Int
+) : CloseImeWindowToAppTest(rotationName, rotation) {
+ override val testApp: ImeAppHelper
+ get() = ImeAppAutoFocusHelper(instrumentation)
- @FlakyTest(bugId = 141458352)
@Test
- override fun checkVisibility_imeLayerBecomesInvisible() {
- super.checkVisibility_imeLayerBecomesInvisible()
- }
+ override fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("imeToAppAutoOpen", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ eachRun {
+ device.wakeUpAndGoToHomeScreen()
+ this.setRotation(rotation)
+ testApp.open()
+ testApp.openIME(device)
+ }
+ }
+ teardown {
+ eachRun {
+ testApp.exit()
+ this.setRotation(Surface.ROTATION_0)
+ }
+ }
+ transitions {
+ device.pressBack()
+ device.waitForIdle()
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ imeAppWindowIsAlwaysVisible(testApp, bugId = 141458352)
+ }
- @FlakyTest(bugId = 141458352)
- @Test
- override fun checkVisibility_imeAppLayerIsAlwaysVisible() {
- super.checkVisibility_imeAppLayerIsAlwaysVisible()
- }
-
- @FlakyTest(bugId = 141458352)
- @Test
- override fun checkVisibility_imeAppWindowIsAlwaysVisible() {
- super.checkVisibility_imeAppWindowIsAlwaysVisible()
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation)
+ navBarLayerRotatesAndScales(rotation)
+ statusBarLayerRotatesScales(rotation)
+ imeLayerBecomesInvisible(bugId = 141458352)
+ imeAppLayerIsAlwaysVisible(testApp, bugId = 141458352)
+ }
+ }
+ }
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
index c2025b6da204..2e4d390ceb60 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
@@ -16,11 +16,19 @@
package com.android.server.wm.flicker.ime
-import androidx.test.filters.FlakyTest
+import android.view.Surface
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.TransitionRunner
+import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -35,33 +43,53 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class CloseImeAutoOpenWindowToHomeTest(
- beginRotationName: String,
- beginRotation: Int
-) : CloseImeWindowToHomeTest(beginRotationName, beginRotation) {
- init {
- testApp = ImeAppAutoFocusHelper(instrumentation)
- }
-
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.editTextLoseFocusToHome(testApp as ImeAppAutoFocusHelper,
- instrumentation, uiDevice, beginRotation)
- .includeJankyRuns().build()
+ rotationName: String,
+ rotation: Int
+) : CloseImeWindowToHomeTest(rotationName, rotation) {
+ override val testApp: ImeAppHelper
+ get() = ImeAppAutoFocusHelper(instrumentation)
- @FlakyTest(bugId = 141458352)
@Test
- override fun checkVisibility_imeWindowBecomesInvisible() {
- super.checkVisibility_imeWindowBecomesInvisible()
- }
+ override fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("imeToHomeAutoOpen", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ eachRun {
+ device.wakeUpAndGoToHomeScreen()
+ this.setRotation(rotation)
+ testApp.open()
+ testApp.openIME(device)
+ }
+ }
+ teardown {
+ eachRun {
+ testApp.exit()
+ this.setRotation(Surface.ROTATION_0)
+ }
+ }
+ transitions {
+ device.pressHome()
+ device.waitForIdle()
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ imeWindowBecomesInvisible(bugId = 141458352)
+ imeAppWindowBecomesInvisible(testApp, bugId = 157449248)
+ }
- @FlakyTest(bugId = 141458352)
- @Test
- override fun checkVisibility_imeLayerBecomesInvisible() {
- super.checkVisibility_imeLayerBecomesInvisible()
- }
-
- @FlakyTest(bugId = 157449248)
- @Test
- override fun checkVisibility_imeAppWindowBecomesInvisible() {
- super.checkVisibility_imeAppWindowBecomesInvisible()
+ layersTrace {
+ navBarLayerIsAlwaysVisible(bugId = 140855415)
+ statusBarLayerIsAlwaysVisible(bugId = 140855415)
+ noUncoveredRegions(rotation, Surface.ROTATION_0, allStates = false)
+ navBarLayerRotatesAndScales(rotation, Surface.ROTATION_0)
+ statusBarLayerRotatesScales(rotation, Surface.ROTATION_0)
+ imeLayerBecomesInvisible(bugId = 141458352)
+ imeAppLayerBecomesInvisible(testApp, bugId = 153739621)
+ }
+ }
+ }
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
index b38262e9f298..67c46d3f4722 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
@@ -16,14 +16,19 @@
package com.android.server.wm.flicker.ime
-import androidx.test.filters.FlakyTest
+import android.view.Surface
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WmTraceSubject
+import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -38,49 +43,51 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
open class CloseImeWindowToAppTest(
- beginRotationName: String,
- beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
- init {
- testApp = ImeAppHelper(instrumentation)
- }
-
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.editTextLoseFocusToApp(testApp as ImeAppHelper,
- instrumentation, uiDevice, beginRotation)
- .includeJankyRuns().build()
+ rotationName: String,
+ rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+ open val testApp = ImeAppHelper(instrumentation)
- @FlakyTest
@Test
- open fun checkVisibility_imeLayerBecomesInvisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(IME_WINDOW_TITLE)
- .then()
- .hidesLayer(IME_WINDOW_TITLE)
- .forAllEntries()
- }
- }
+ open fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("imeToApp", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ eachRun {
+ device.wakeUpAndGoToHomeScreen()
+ this.setRotation(rotation)
+ testApp.open()
+ testApp.openIME(device)
+ }
+ }
+ teardown {
+ eachRun {
+ testApp.exit()
+ this.setRotation(Surface.ROTATION_0)
+ }
+ }
+ transitions {
+ device.pressBack()
+ device.waitForIdle()
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ imeAppWindowIsAlwaysVisible(testApp)
+ }
- @Test
- open fun checkVisibility_imeAppLayerIsAlwaysVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(testApp.getPackage())
- .forAllEntries()
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation)
+ navBarLayerRotatesAndScales(rotation)
+ statusBarLayerRotatesScales(rotation)
+ imeLayerBecomesInvisible(enabled = false)
+ imeAppLayerIsAlwaysVisible(testApp)
+ }
+ }
}
}
-
- @Test
- open fun checkVisibility_imeAppWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAppWindowOnTop(testApp.getPackage())
- .forAllEntries()
- }
- }
-
- companion object {
- const val IME_WINDOW_TITLE = "InputMethod"
- }
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
index ca04babfa0f1..1c0da4f920bb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
@@ -16,20 +16,26 @@
package com.android.server.wm.flicker.ime
-import androidx.test.filters.FlakyTest
+import android.view.Surface
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WmTraceSubject
+import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.openQuickstep
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
-
/**
* Test IME window closing to home transitions.
* To run this test: `atest FlickerTests:CloseImeWindowToHomeTest`
@@ -38,67 +44,60 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
open class CloseImeWindowToHomeTest(
- beginRotationName: String,
- beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
- init {
- testApp = ImeAppHelper(instrumentation)
- }
-
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.editTextLoseFocusToHome(testApp as ImeAppHelper,
- instrumentation, uiDevice, beginRotation)
- .includeJankyRuns().build()
-
- @Test
- open fun checkVisibility_imeWindowBecomesInvisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsNonAppWindow(IME_WINDOW_TITLE)
- .then()
- .hidesNonAppWindow(IME_WINDOW_TITLE)
- .forAllEntries()
- }
- }
-
- @FlakyTest(bugId = 153739621)
- @Test
- open fun checkVisibility_imeLayerBecomesInvisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .skipUntilFirstAssertion()
- .showsLayer(IME_WINDOW_TITLE)
- .then()
- .hidesLayer(IME_WINDOW_TITLE)
- .forAllEntries()
- }
- }
+ rotationName: String,
+ rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+ open val testApp = ImeAppHelper(instrumentation)
- @FlakyTest(bugId = 153739621)
@Test
- fun checkVisibility_imeAppLayerBecomesInvisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .skipUntilFirstAssertion()
- .showsLayer(testApp.getPackage())
- .then()
- .hidesLayer(testApp.getPackage())
- .forAllEntries()
- }
- }
+ open fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("imeToHome", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ this.setRotation(rotation)
+ testApp.open()
+ }
+ eachRun {
+ device.openQuickstep()
+ device.reopenAppFromOverview()
+ this.setRotation(rotation)
+ testApp.openIME(device)
+ }
+ }
+ transitions {
+ device.pressHome()
+ device.waitForIdle()
+ }
+ teardown {
+ eachRun {
+ device.pressHome()
+ }
+ test {
+ testApp.exit()
+ this.setRotation(Surface.ROTATION_0)
+ }
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ imeWindowBecomesInvisible()
+ imeAppWindowBecomesInvisible(testApp)
+ }
- @Test
- open fun checkVisibility_imeAppWindowBecomesInvisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAppWindowOnTop(testApp.getPackage())
- .then()
- .appWindowNotOnTop(testApp.getPackage())
- .forAllEntries()
+ layersTrace {
+ navBarLayerIsAlwaysVisible(bugId = 140855415)
+ statusBarLayerIsAlwaysVisible(bugId = 140855415)
+ noUncoveredRegions(rotation, Surface.ROTATION_0, allStates = false)
+ navBarLayerRotatesAndScales(rotation, Surface.ROTATION_0)
+ statusBarLayerRotatesScales(rotation, Surface.ROTATION_0)
+ imeLayerBecomesInvisible(bugId = 153739621)
+ imeAppLayerBecomesInvisible(testApp, bugId = 153739621)
+ }
+ }
}
}
-
- companion object {
- const val IME_WINDOW_TITLE: String = "InputMethod"
- }
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ImeAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ImeAssertions.kt
new file mode 100644
index 000000000000..b2be54fe068a
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ImeAssertions.kt
@@ -0,0 +1,102 @@
+/*
+ * 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.wm.flicker.ime
+
+import android.platform.helpers.IAppHelper
+import com.android.server.wm.flicker.dsl.LayersAssertion
+import com.android.server.wm.flicker.dsl.WmAssertion
+
+const val IME_WINDOW_TITLE = "InputMethod"
+
+@JvmOverloads
+fun LayersAssertion.imeLayerBecomesVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("imeLayerBecomesVisible", enabled, bugId) {
+ this.hidesLayer(IME_WINDOW_TITLE)
+ .then()
+ .showsLayer(IME_WINDOW_TITLE)
+ }
+}
+
+fun LayersAssertion.imeLayerBecomesInvisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("imeLayerBecomesInvisible", enabled, bugId) {
+ this.showsLayer(IME_WINDOW_TITLE)
+ .then()
+ .hidesLayer(IME_WINDOW_TITLE)
+ }
+}
+
+fun LayersAssertion.imeAppLayerIsAlwaysVisible(
+ testApp: IAppHelper,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("imeAppLayerIsAlwaysVisible", enabled, bugId) {
+ this.showsLayer(testApp.getPackage())
+ }
+}
+
+fun WmAssertion.imeAppWindowIsAlwaysVisible(
+ testApp: IAppHelper,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("imeAppWindowIsAlwaysVisible", enabled, bugId) {
+ this.showsAppWindowOnTop(testApp.getPackage())
+ }
+}
+
+fun WmAssertion.imeWindowBecomesInvisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("imeWindowBecomesInvisible", enabled, bugId) {
+ this.showsNonAppWindow(IME_WINDOW_TITLE)
+ .then()
+ .hidesNonAppWindow(IME_WINDOW_TITLE)
+ }
+}
+
+fun WmAssertion.imeAppWindowBecomesInvisible(
+ testApp: IAppHelper,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("imeAppWindowBecomesInvisible", enabled, bugId) {
+ this.showsAppWindowOnTop(testApp.getPackage())
+ .then()
+ .appWindowNotOnTop(testApp.getPackage())
+ }
+}
+
+fun LayersAssertion.imeAppLayerBecomesInvisible(
+ testApp: IAppHelper,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("imeAppLayerBecomesInvisible", enabled, bugId) {
+ this.skipUntilFirstAssertion()
+ .showsLayer(testApp.getPackage())
+ .then()
+ .hidesLayer(testApp.getPackage())
+ }
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
index c7731f330aeb..5874a0736d85 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
@@ -16,13 +16,19 @@
package com.android.server.wm.flicker.ime
+import android.view.Surface
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WmTraceSubject
+import com.android.server.wm.flicker.dsl.flicker
import com.android.server.wm.flicker.helpers.ImeAppHelper
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,38 +43,58 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class OpenImeWindowTest(
- beginRotationName: String,
- beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
- init {
- testApp = ImeAppHelper(instrumentation)
- }
+ rotationName: String,
+ rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+ @Test
+ fun test() {
+ val testApp = ImeAppHelper(instrumentation)
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.editTextSetFocus(testApp as ImeAppHelper,
- instrumentation, uiDevice, beginRotation)
- .includeJankyRuns().build()
+ flicker(instrumentation) {
+ withTag { buildTestTag("openIme", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ this.setRotation(rotation)
+ testApp.open()
+ }
+ }
+ transitions {
+ testApp.openIME(device)
+ }
+ teardown {
+ eachRun {
+ testApp.closeIME(device)
+ }
+ test {
+ testApp.exit()
+ this.setRotation(Surface.ROTATION_0)
+ }
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
- @Test
- fun checkVisibility_imeWindowBecomesVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .skipUntilFirstAssertion()
- .hidesNonAppWindow(IME_WINDOW_TITLE)
- .then()
- .showsNonAppWindow(IME_WINDOW_TITLE)
- .forAllEntries()
- }
- }
+ all("imeWindowBecomesVisible") {
+ this.skipUntilFirstAssertion()
+ .hidesNonAppWindow(IME_WINDOW_TITLE)
+ .then()
+ .showsNonAppWindow(IME_WINDOW_TITLE)
+ }
+ }
- @Test
- fun checkVisibility_imeLayerBecomesVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .hidesLayer(IME_WINDOW_TITLE)
- .then()
- .showsLayer(IME_WINDOW_TITLE)
- .forAllEntries()
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation)
+ navBarLayerRotatesAndScales(rotation)
+ statusBarLayerRotatesScales(rotation)
+
+ imeLayerBecomesVisible()
+ }
+ }
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index 88b885407935..62337e9bff34 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -16,14 +16,18 @@
package com.android.server.wm.flicker.launch
-import androidx.test.filters.FlakyTest
+import android.view.Surface
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.LayersTraceSubject
-import com.android.server.wm.flicker.NonRotationTestBase
-import com.android.server.wm.flicker.StandardAppHelper
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WmTraceSubject
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.focusChanges
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -38,50 +42,53 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class OpenAppColdTest(
- beginRotationName: String,
- beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
- init {
- testApp = StandardAppHelper(instrumentation,
- "com.android.server.wm.flicker.testapp", "SimpleApp")
- }
-
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.openAppCold(testApp, instrumentation, uiDevice, beginRotation)
- .includeJankyRuns().build()
-
+ rotationName: String,
+ rotation: Int
+) : OpenAppTestBase(rotationName, rotation) {
@Test
- fun checkVisibility_wallpaperWindowBecomesInvisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsBelowAppWindow("Wallpaper")
- .then()
- .hidesBelowAppWindow("Wallpaper")
- .forAllEntries()
- }
- }
+ fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("openAppCold", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ eachRun {
+ this.setRotation(rotation)
+ }
+ }
+ transitions {
+ testApp.open()
+ }
+ teardown {
+ eachRun {
+ testApp.exit()
+ this.setRotation(Surface.ROTATION_0)
+ }
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ appWindowReplacesLauncherAsTopWindow()
+ wallpaperWindowBecomesInvisible()
+ }
- @FlakyTest(bugId = 140855415)
- @Test
- fun checkZOrder_appWindowReplacesLauncherAsTopWindow() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAppWindowOnTop(
- "com.android.launcher3/.Launcher")
- .then()
- .showsAppWindowOnTop(testApp.getPackage())
- .forAllEntries()
- }
- }
+ layersTrace {
+ // During testing the launcher is always in portrait mode
+ noUncoveredRegions(Surface.ROTATION_0, rotation, bugId = 141361128)
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation)
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible(enabled = false)
+ wallpaperLayerBecomesInvisible()
+ }
- @Test
- fun checkVisibility_wallpaperLayerBecomesInvisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer("Wallpaper")
- .then()
- .replaceVisibleLayer("Wallpaper", testApp.getPackage())
- .forAllEntries()
+ eventLog {
+ focusChanges("NexusLauncherActivity", testApp.`package`)
+ }
+ }
}
}
} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt
new file mode 100644
index 000000000000..7d70812a22f2
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt
@@ -0,0 +1,63 @@
+/*
+ * 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.wm.flicker.launch
+
+import com.android.server.wm.flicker.NonRotationTestBase
+import com.android.server.wm.flicker.StandardAppHelper
+import com.android.server.wm.flicker.dsl.LayersAssertion
+import com.android.server.wm.flicker.dsl.WmAssertion
+
+abstract class OpenAppTestBase(
+ rotationName: String,
+ rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+ protected val testApp = StandardAppHelper(instrumentation,
+ "com.android.server.wm.flicker.testapp", "SimpleApp")
+
+ protected fun WmAssertion.wallpaperWindowBecomesInvisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+ ) {
+ all("wallpaperWindowBecomesInvisible", enabled, bugId) {
+ this.showsBelowAppWindow("Wallpaper")
+ .then()
+ .hidesBelowAppWindow("Wallpaper")
+ }
+ }
+
+ protected fun WmAssertion.appWindowReplacesLauncherAsTopWindow(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+ ) {
+ all("appWindowReplacesLauncherAsTopWindow", enabled, bugId) {
+ this.showsAppWindowOnTop("Launcher")
+ .then()
+ .showsAppWindowOnTop("Snapshot", testApp.getPackage())
+ }
+ }
+
+ protected fun LayersAssertion.wallpaperLayerBecomesInvisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+ ) {
+ all("appWindowReplacesLauncherAsTopWindow", enabled, bugId) {
+ this.showsLayer("Wallpaper")
+ .then()
+ .replaceVisibleLayer("Wallpaper", testApp.getPackage())
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index f0bc3f00338a..9a8e37b19e56 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -16,14 +16,19 @@
package com.android.server.wm.flicker.launch
-import androidx.test.filters.FlakyTest
+import android.view.Surface
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.LayersTraceSubject
-import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.StandardAppHelper
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WmTraceSubject
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.focusChanges
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -38,50 +43,60 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class OpenAppWarmTest(
- beginRotationName: String,
- beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
- init {
- testApp = StandardAppHelper(instrumentation,
+ rotationName: String,
+ rotation: Int
+) : OpenAppTestBase(rotationName, rotation) {
+ @Test
+ fun test() {
+ val testApp = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
- }
-
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.openAppWarm(testApp, instrumentation, uiDevice, beginRotation)
- .includeJankyRuns().build()
- @Test
- fun checkVisibility_wallpaperBecomesInvisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsBelowAppWindow("Wallpaper")
- .then()
- .hidesBelowAppWindow("Wallpaper")
- .forAllEntries()
- }
- }
+ flicker(instrumentation) {
+ withTag { buildTestTag("openAppWarm", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ testApp.open()
+ }
+ eachRun {
+ device.pressHome()
+ this.setRotation(rotation)
+ }
+ }
+ transitions {
+ testApp.open()
+ }
+ teardown {
+ eachRun {
+ this.setRotation(Surface.ROTATION_0)
+ }
+ test {
+ testApp.exit()
+ }
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ appWindowReplacesLauncherAsTopWindow()
+ wallpaperWindowBecomesInvisible(enabled = false)
+ }
- @FlakyTest(bugId = 140855415)
- @Test
- fun checkZOrder_appWindowReplacesLauncherAsTopWindow() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAppWindowOnTop(
- "com.android.launcher3/.Launcher")
- .then()
- .showsAppWindowOnTop(testApp.getPackage())
- .forAllEntries()
- }
- }
+ layersTrace {
+ // During testing the launcher is always in portrait mode
+ noUncoveredRegions(Surface.ROTATION_0, rotation, bugId = 141361128)
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation)
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible(enabled = false)
+ wallpaperLayerBecomesInvisible()
+ }
- @Test
- fun checkVisibility_wallpaperLayerBecomesInvisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer("Wallpaper")
- .then()
- .replaceVisibleLayer("Wallpaper", testApp.getPackage())
- .forAllEntries()
+ eventLog {
+ focusChanges("NexusLauncherActivity", testApp.`package`)
+ }
+ }
}
}
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/pip/EnterPipTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/pip/EnterPipTest.kt
new file mode 100644
index 000000000000..4acd97553bc0
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/pip/EnterPipTest.kt
@@ -0,0 +1,121 @@
+/*
+ * 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.wm.flicker.pip
+
+import android.view.Surface
+import androidx.test.filters.FlakyTest
+import androidx.test.filters.LargeTest
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.helpers.closePipWindow
+import com.android.server.wm.flicker.helpers.expandPipWindow
+import com.android.server.wm.flicker.helpers.hasPipWindow
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip launch.
+ * To run this test: `atest FlickerTests:PipToAppTest`
+ */
+@LargeTest
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 152738416)
+class EnterPipTest(
+ rotationName: String,
+ rotation: Int
+) : PipTestBase(rotationName, rotation) {
+ @Test
+ fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("enterPip", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ eachRun {
+ device.pressHome()
+ testApp.open()
+ this.setRotation(rotation)
+ }
+ }
+ teardown {
+ eachRun {
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ testApp.exit()
+ this.setRotation(Surface.ROTATION_0)
+ }
+ test {
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ }
+ }
+ transitions {
+ testApp.clickEnterPipButton(device)
+ device.expandPipWindow()
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ all("pipWindowBecomesVisible") {
+ this.showsAppWindow(testApp.`package`)
+ .then()
+ .showsAppWindow(sPipWindowTitle)
+ }
+ }
+
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation, Surface.ROTATION_0, allStates = false)
+ navBarLayerRotatesAndScales(rotation, Surface.ROTATION_0)
+ statusBarLayerRotatesScales(rotation, Surface.ROTATION_0)
+
+ all("pipLayerBecomesVisible") {
+ this.showsLayer(testApp.launcherName)
+ .then()
+ .showsLayer(sPipWindowTitle)
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_0)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipTestBase.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipTestBase.kt
index 79321f9488ad..691db7fbac5c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipTestBase.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipTestBase.kt
@@ -16,66 +16,16 @@
package com.android.server.wm.flicker.pip
-import androidx.test.InstrumentationRegistry
-import androidx.test.filters.LargeTest
-import androidx.test.uiautomator.UiDevice
-import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
-import com.android.server.wm.flicker.WmTraceSubject
-import com.android.server.wm.flicker.helpers.AutomationUtils
import com.android.server.wm.flicker.helpers.PipAppHelper
-import org.junit.AfterClass
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-@LargeTest
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
abstract class PipTestBase(
- beginRotationName: String,
- beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
- init {
- testApp = PipAppHelper(instrumentation)
- }
-
- @Test
- fun checkVisibility_pipWindowBecomesVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .skipUntilFirstAssertion()
- .showsAppWindowOnTop(sPipWindowTitle)
- .then()
- .hidesAppWindow(sPipWindowTitle)
- .forAllEntries()
- }
- }
-
- @Test
- fun checkVisibility_pipLayerBecomesVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .skipUntilFirstAssertion()
- .showsLayer(sPipWindowTitle)
- .then()
- .hidesLayer(sPipWindowTitle)
- .forAllEntries()
- }
- }
+ rotationName: String,
+ rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+ protected val testApp = PipAppHelper(instrumentation)
companion object {
const val sPipWindowTitle = "PipMenuActivity"
-
- @AfterClass
- @JvmStatic
- fun teardown() {
- val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
- if (AutomationUtils.hasPipWindow(device)) {
- AutomationUtils.closePipWindow(device)
- }
- }
}
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToAppTest.kt
index 89ffb7a57b73..04c2f59118bd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToAppTest.kt
@@ -16,12 +16,22 @@
package com.android.server.wm.flicker.pip
+import android.view.Surface
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WmTraceSubject
-import com.android.server.wm.flicker.helpers.PipAppHelper
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.focusChanges
+import com.android.server.wm.flicker.helpers.closePipWindow
+import com.android.server.wm.flicker.helpers.expandPipWindow
+import com.android.server.wm.flicker.helpers.hasPipWindow
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,27 +47,73 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 152738416)
class PipToAppTest(
- beginRotationName: String,
- beginRotation: Int
-) : PipTestBase(beginRotationName, beginRotation) {
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.exitPipModeToApp(testApp as PipAppHelper, instrumentation,
- uiDevice, beginRotation)
- .includeJankyRuns().build()
-
+ rotationName: String,
+ rotation: Int
+) : PipTestBase(rotationName, rotation) {
@Test
- fun checkVisibility_backgroundWindowVisibleBehindPipLayer() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .skipUntilFirstAssertion()
- .showsAppWindowOnTop(sPipWindowTitle)
- .then()
- .showsBelowAppWindow("Wallpaper")
- .then()
- .showsAppWindowOnTop(testApp.getPackage())
- .then()
- .appWindowNotOnTop(testApp.getPackage())
- .forAllEntries()
+ fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("exitPipModeToApp", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ device.pressHome()
+ testApp.open()
+ }
+ eachRun {
+ this.setRotation(rotation)
+ testApp.clickEnterPipButton(device)
+ device.hasPipWindow()
+ }
+ }
+ teardown {
+ eachRun {
+ this.setRotation(Surface.ROTATION_0)
+ }
+ test {
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ testApp.exit()
+ }
+ }
+ transitions {
+ device.expandPipWindow()
+ device.waitForIdle()
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+
+ all("appReplacesPipWindow") {
+ this.showsAppWindow(sPipWindowTitle)
+ .then()
+ .showsAppWindowOnTop(testApp.launcherName)
+ }
+ }
+
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation)
+ navBarLayerRotatesAndScales(rotation)
+ statusBarLayerRotatesScales(rotation)
+
+ all("appReplacesPipLayer") {
+ this.showsLayer(sPipWindowTitle)
+ .then()
+ .showsLayer(testApp.launcherName)
+ }
+ }
+
+ eventLog {
+ focusChanges(
+ "NexusLauncherActivity", testApp.launcherName, "NexusLauncherActivity",
+ bugId = 151179149)
+ }
+ }
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToHomeTest.kt
index 8591360cff60..b6074cd7033b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/pip/PipToHomeTest.kt
@@ -16,12 +16,21 @@
package com.android.server.wm.flicker.pip
+import android.view.Surface
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WmTraceSubject
-import com.android.server.wm.flicker.helpers.PipAppHelper
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.focusChanges
+import com.android.server.wm.flicker.helpers.closePipWindow
+import com.android.server.wm.flicker.helpers.hasPipWindow
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,24 +46,83 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 152738416)
class PipToHomeTest(
- beginRotationName: String,
- beginRotation: Int
-) : PipTestBase(beginRotationName, beginRotation) {
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.exitPipModeToHome(testApp as PipAppHelper, instrumentation,
- uiDevice, beginRotation)
- .includeJankyRuns().build()
-
+ rotationName: String,
+ rotation: Int
+) : PipTestBase(rotationName, rotation) {
@Test
- fun checkVisibility_backgroundWindowVisibleBehindPipLayer() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAppWindowOnTop(sPipWindowTitle)
- .then()
- .showsBelowAppWindow("Wallpaper")
- .then()
- .showsAppWindowOnTop("Wallpaper")
- .forAllEntries()
+ fun test() {
+ flicker(instrumentation) {
+ withTag { buildTestTag("exitPipModeToApp", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ device.pressHome()
+ }
+ eachRun {
+ testApp.open()
+ this.setRotation(rotation)
+ testApp.clickEnterPipButton(device)
+ device.hasPipWindow()
+ }
+ }
+ teardown {
+ eachRun {
+ this.setRotation(Surface.ROTATION_0)
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ }
+ test {
+ if (device.hasPipWindow()) {
+ device.closePipWindow()
+ }
+ testApp.exit()
+ }
+ }
+ transitions {
+ testApp.closePipWindow(device)
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+
+ all("pipWindowBecomesInvisible") {
+ this.showsAppWindow(sPipWindowTitle)
+ .then()
+ .hidesAppWindow(sPipWindowTitle)
+ }
+ }
+
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ // The final state is the launcher, so always in portrait mode
+ noUncoveredRegions(rotation, Surface.ROTATION_0, allStates = false)
+ navBarLayerRotatesAndScales(rotation)
+ statusBarLayerRotatesScales(rotation)
+
+ all("pipLayerBecomesInvisible") {
+ this.showsLayer(sPipWindowTitle)
+ .then()
+ .hidesLayer(sPipWindowTitle)
+ }
+ }
+
+ eventLog {
+ focusChanges(testApp.launcherName, "NexusLauncherActivity", bugId = 151179149)
+ }
+ }
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_0)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
}
}
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index fb1cb399e8bc..5e75e4a144bf 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -16,15 +16,22 @@
package com.android.server.wm.flicker.rotation
-import android.util.Log
-import androidx.test.filters.FlakyTest
+import android.view.Surface
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.LayersTraceSubject
+import com.android.server.wm.flicker.NonRotationTestBase.Companion.SCREENSHOT_LAYER
import com.android.server.wm.flicker.RotationTestBase
import com.android.server.wm.flicker.StandardAppHelper
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WindowUtils
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.focusDoesNotChange
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -44,42 +51,75 @@ class ChangeAppRotationTest(
beginRotation: Int,
endRotation: Int
) : RotationTestBase(beginRotationName, endRotationName, beginRotation, endRotation) {
- init {
- testApp = StandardAppHelper(instrumentation,
+ @Test
+ fun test() {
+ val testApp = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
- }
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.changeAppRotation(testApp, instrumentation, uiDevice,
- beginRotation, endRotation)
- .includeJankyRuns().build()
+ flicker(instrumentation) {
+ withTag {
+ buildTestTag("changeAppRotation", testApp, beginRotation, endRotation)
+ }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ testApp.open()
+ }
+ eachRun {
+ this.setRotation(beginRotation)
+ }
+ }
+ teardown {
+ eachRun {
+ this.setRotation(Surface.ROTATION_0)
+ }
+ test {
+ testApp.exit()
+ }
+ }
+ transitions {
+ this.setRotation(endRotation)
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ }
- @Test
- fun checkPosition_appLayerRotates() {
- val startingPos = WindowUtils.getAppPosition(beginRotation)
- val endingPos = WindowUtils.getAppPosition(endRotation)
- Log.e(TAG, "startingPos=$startingPos endingPos=$endingPos")
- checkResults {
- LayersTraceSubject.assertThat(it)
- .hasVisibleRegion(testApp.getPackage(), startingPos).inTheBeginning()
- LayersTraceSubject.assertThat(it)
- .hasVisibleRegion(testApp.getPackage(), endingPos).atTheEnd()
- }
- }
+ layersTrace {
+ navBarLayerIsAlwaysVisible(bugId = 140855415)
+ statusBarLayerIsAlwaysVisible(bugId = 140855415)
+ noUncoveredRegions(beginRotation, endRotation, allStates = false)
+ navBarLayerRotatesAndScales(beginRotation, endRotation)
+ statusBarLayerRotatesScales(beginRotation, endRotation)
+ }
- @FlakyTest
- @Test
- fun checkVisibility_screenshotLayerBecomesInvisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(testApp.getPackage())
- .then()
- .replaceVisibleLayer(testApp.getPackage(), SCREENSHOT_LAYER)
- .then()
- .showsLayer(testApp.getPackage()).and().showsLayer(SCREENSHOT_LAYER)
- .then()
- .replaceVisibleLayer(SCREENSHOT_LAYER, testApp.getPackage())
- .forAllEntries()
+ layersTrace {
+ val startingPos = WindowUtils.getDisplayBounds(beginRotation)
+ val endingPos = WindowUtils.getDisplayBounds(endRotation)
+
+ start("appLayerRotates_StartingPos") {
+ this.hasVisibleRegion(testApp.getPackage(), startingPos)
+ }
+
+ end("appLayerRotates_EndingPos") {
+ this.hasVisibleRegion(testApp.getPackage(), endingPos)
+ }
+
+ all("screenshotLayerBecomesInvisible") {
+ this.showsLayer(testApp.getPackage())
+ .then()
+ .showsLayer(SCREENSHOT_LAYER)
+ .then()
+ showsLayer(testApp.getPackage())
+ }
+ }
+
+ eventLog {
+ focusDoesNotChange(bugId = 151179149)
+ }
+ }
}
}
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index 1cd19983f3b1..de87b412fc90 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -17,15 +17,26 @@
package com.android.server.wm.flicker.rotation
import android.content.Intent
+import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.view.Surface
-import androidx.test.InstrumentationRegistry
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.LayersTraceSubject
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.RotationTestBase
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WindowUtils
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.focusDoesNotChange
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.helpers.stopPackage
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.testapp.ActivityOptions
import org.junit.FixMethodOrder
import org.junit.Test
@@ -42,67 +53,101 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 147659548)
class SeamlessAppRotationTest(
+ testId: String,
private val intent: Intent,
beginRotationName: String,
endRotationName: String,
beginRotation: Int,
endRotation: Int
) : RotationTestBase(beginRotationName, endRotationName, beginRotation, endRotation) {
- override val transitionToRun: TransitionRunner
- get() {
- var intentId = ""
- if (intent.extras?.getBoolean(ActivityOptions.EXTRA_STARVE_UI_THREAD) == true) {
- intentId = "BUSY_UI_THREAD"
- }
- return CommonTransitions.changeAppRotation(intent, intentId,
- InstrumentationRegistry.getContext(), instrumentation, uiDevice,
- beginRotation, endRotation).build()
+ @Test
+ fun test() {
+ var intentId = ""
+ if (intent.extras?.getBoolean(ActivityOptions.EXTRA_STARVE_UI_THREAD) == true) {
+ intentId = "BUSY_UI_THREAD"
}
- @Test
- fun checkPosition_appLayerRotates() {
- val startingPos = WindowUtils.getAppPosition(beginRotation)
- val endingPos = WindowUtils.getAppPosition(endRotation)
- if (startingPos == endingPos) {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .hasVisibleRegion(intent.component?.packageName ?: "", startingPos)
- .forAllEntries()
+ flicker(instrumentation) {
+ withTag {
+ "changeAppRotation_" + intentId + "_" +
+ Surface.rotationToString(beginRotation) + "_" +
+ Surface.rotationToString(endRotation)
}
- } else {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .hasVisibleRegion(intent.component?.packageName ?: "", startingPos)
- .then()
- .hasVisibleRegion(intent.component?.packageName ?: "", endingPos)
- .forAllEntries()
+ repeat { 1 }
+ setup {
+ eachRun {
+ device.wakeUpAndGoToHomeScreen()
+ instrumentation.targetContext.startActivity(intent)
+ device.wait(Until.hasObject(By.pkg(intent.component?.packageName)
+ .depth(0)), APP_LAUNCH_TIMEOUT)
+ this.setRotation(beginRotation)
+ }
}
- }
- }
-
- @Test
- fun checkCoveredRegion_noUncoveredRegions() {
- val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
- val endingBounds = WindowUtils.getDisplayBounds(endRotation)
- if (startingBounds == endingBounds) {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .coversRegion(startingBounds)
- .forAllEntries()
+ teardown {
+ eachRun {
+ stopPackage(
+ instrumentation.targetContext,
+ intent.component?.packageName
+ ?: error("Unable to determine package name for intent"))
+ this.setRotation(Surface.ROTATION_0)
+ }
}
- } else {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .coversRegion(startingBounds)
- .then()
- .coversRegion(endingBounds)
- .forAllEntries()
+ transitions {
+ this.setRotation(endRotation)
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible(bugId = 140855415)
+ statusBarWindowIsAlwaysVisible(bugId = 140855415)
+ }
+
+ layersTrace {
+ navBarLayerIsAlwaysVisible(bugId = 140855415)
+ statusBarLayerIsAlwaysVisible(bugId = 140855415)
+ noUncoveredRegions(beginRotation, endRotation, allStates = true)
+ navBarLayerRotatesAndScales(beginRotation, endRotation)
+ statusBarLayerRotatesScales(beginRotation, endRotation, enabled = false)
+ }
+
+ layersTrace {
+ all("appLayerRotates"/*, bugId = 147659548*/) {
+ val startingPos = WindowUtils.getDisplayBounds(beginRotation)
+ val endingPos = WindowUtils.getDisplayBounds(endRotation)
+
+ if (startingPos == endingPos) {
+ this.hasVisibleRegion(
+ intent.component?.packageName ?: "",
+ startingPos)
+ } else {
+ this.hasVisibleRegion(intent.component?.packageName ?: "", startingPos)
+ .then()
+ .hasVisibleRegion(intent.component?.packageName
+ ?: "", endingPos)
+ }
+ }
+
+ all("noUncoveredRegions"/*, bugId = 147659548*/) {
+ val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
+ val endingBounds = WindowUtils.getDisplayBounds(endRotation)
+ if (startingBounds == endingBounds) {
+ this.coversAtLeastRegion(startingBounds)
+ } else {
+ this.coversAtLeastRegion(startingBounds)
+ .then()
+ .coversAtLeastRegion(endingBounds)
+ }
+ }
+ }
+
+ eventLog {
+ focusDoesNotChange(bugId = 151179149)
+ }
}
}
}
companion object {
- // launch test activity that supports seamless rotation
+ private const val APP_LAUNCH_TIMEOUT: Long = 10000
// launch test activity that supports seamless rotation with a busy UI thread to miss frames
// when the app is asked to redraw
@@ -110,18 +155,20 @@ class SeamlessAppRotationTest(
@JvmStatic
fun getParams(): Collection<Array<Any>> {
val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90)
- val params: MutableCollection<Array<Any>> = ArrayList()
- val testIntents = ArrayList<Intent>()
+ val params = mutableListOf<Array<Any>>()
+ val testIntents = mutableListOf<Intent>()
// launch test activity that supports seamless rotation
var intent = Intent(Intent.ACTION_MAIN)
intent.component = ActivityOptions.SEAMLESS_ACTIVITY_COMPONENT_NAME
+ intent.flags = FLAG_ACTIVITY_NEW_TASK
testIntents.add(intent)
// launch test activity that supports seamless rotation with a busy UI thread to miss frames
// when the app is asked to redraw
intent = Intent(intent)
intent.putExtra(ActivityOptions.EXTRA_STARVE_UI_THREAD, true)
+ intent.flags = FLAG_ACTIVITY_NEW_TASK
testIntents.add(intent)
for (testIntent in testIntents) {
for (begin in supportedRotations) {
@@ -133,7 +180,13 @@ class SeamlessAppRotationTest(
ActivityOptions.EXTRA_STARVE_UI_THREAD) == true) {
testId += "_" + "BUSY_UI_THREAD"
}
- params.add(arrayOf(testId, testIntent, begin, end))
+ params.add(arrayOf(
+ testId,
+ testIntent,
+ Surface.rotationToString(begin),
+ Surface.rotationToString(end),
+ begin,
+ end))
}
}
}
@@ -141,4 +194,4 @@ class SeamlessAppRotationTest(
return params
}
}
-}
+} \ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt
index b5611a45a2e7..e078f266e5ed 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt
@@ -16,13 +16,23 @@
package com.android.server.wm.flicker.splitscreen
+import android.view.Surface
import androidx.test.filters.LargeTest
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.StandardAppHelper
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WmTraceSubject
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.focusChanges
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,42 +47,73 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class OpenAppToSplitScreenTest(
- beginRotationName: String,
- beginRotation: Int
-) : NonRotationTestBase(beginRotationName, beginRotation) {
- init {
- testApp = StandardAppHelper(instrumentation,
- "com.android.server.wm.flicker.testapp", "SimpleApp")
- }
+ rotationName: String,
+ rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+ @Test
+ fun test() {
+ val testApp = StandardAppHelper(instrumentation,
+ "com.android.server.wm.flicker.testapp", "SimpleApp")
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.appToSplitScreen(testApp, instrumentation, uiDevice,
- beginRotation).includeJankyRuns().build()
+ flicker(instrumentation) {
+ withTag { buildTestTag("appToSplitScreen", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ eachRun {
+ testApp.open()
+ this.setRotation(rotation)
+ }
+ }
+ teardown {
+ eachRun {
+ if (device.isInSplitScreen()) {
+ device.exitSplitScreen()
+ }
+ }
+ test {
+ testApp.exit()
+ }
+ }
+ transitions {
+ device.launchSplitScreen()
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ }
- @Test
- fun checkVisibility_navBarWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
- }
- }
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation)
+ navBarLayerRotatesAndScales(rotation)
+ statusBarLayerRotatesScales(rotation)
- @Test
- fun checkVisibility_statusBarWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries()
+ all("dividerLayerBecomesVisible") {
+ this.hidesLayer(DOCKED_STACK_DIVIDER)
+ .then()
+ .showsLayer(DOCKED_STACK_DIVIDER)
+ }
+ }
+
+ eventLog {
+ focusChanges(testApp.`package`,
+ "recents_animation_input_consumer", "NexusLauncherActivity")
+ }
+ }
}
}
- @Test
- fun checkVisibility_dividerLayerBecomesVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .hidesLayer(DOCKED_STACK_DIVIDER)
- .then()
- .showsLayer(DOCKED_STACK_DIVIDER)
- .forAllEntries()
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_0)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt
index 6b597e5807ea..a08b2bfdf1fe 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt
@@ -19,24 +19,28 @@ package com.android.server.wm.flicker.splitscreen
import android.graphics.Region
import android.util.Rational
import android.view.Surface
-import androidx.test.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
-import androidx.test.runner.AndroidJUnit4
-import androidx.test.uiautomator.UiDevice
-import com.android.server.wm.flicker.CommonTransitions
+import androidx.test.uiautomator.By
import com.android.server.wm.flicker.FlickerTestBase
-import com.android.server.wm.flicker.LayersTrace
-import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.StandardAppHelper
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.TransitionResult
-import com.android.server.wm.flicker.WindowUtils
-import com.android.server.wm.flicker.WmTraceSubject
-import com.android.server.wm.flicker.helpers.AutomationUtils
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.focusDoesNotChange
import com.android.server.wm.flicker.helpers.ImeAppHelper
-import com.google.common.truth.Truth
-import org.junit.AfterClass
+import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.resizeSplitScreen
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -53,146 +57,134 @@ import org.junit.runners.MethodSorters
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 159096424)
class ResizeSplitScreenTest : FlickerTestBase() {
- init {
- testApp = StandardAppHelper(instrumentation,
+ @Test
+ fun test() {
+ val testAppTop = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
- }
+ val testAppBottom = ImeAppHelper(instrumentation)
- override val transitionToRun: TransitionRunner
- get() {
- val bottomApp = ImeAppHelper(instrumentation)
- return CommonTransitions.resizeSplitScreen(testApp, bottomApp, instrumentation,
- uiDevice, Surface.ROTATION_0,
- Rational(1, 3), Rational(2, 3))
- .includeJankyRuns().build()
- }
+ flicker(instrumentation) {
+ withTag {
+ val description = (startRatio.toString().replace("/", "-") + "_to_" +
+ stopRatio.toString().replace("/", "-"))
+ buildTestTag("resizeSplitScreen", testAppTop, rotation,
+ rotation, testAppBottom, description)
+ }
+ repeat { 1 }
+ setup {
+ eachRun {
+ device.wakeUpAndGoToHomeScreen()
+ this.setRotation(rotation)
+ this.launcherStrategy.clearRecentAppsFromOverview()
+ testAppBottom.open()
+ device.pressHome()
+ testAppTop.open()
+ device.waitForIdle()
+ device.launchSplitScreen()
+ val snapshot = device.findObject(By.res(device.launcherPackageName, "snapshot"))
+ snapshot.click()
+ testAppBottom.openIME(device)
+ device.pressBack()
+ device.resizeSplitScreen(startRatio)
+ }
+ }
+ teardown {
+ eachRun {
+ device.exitSplitScreen()
+ device.pressHome()
+ testAppTop.exit()
+ testAppBottom.exit()
+ }
+ test {
+ if (device.isInSplitScreen()) {
+ device.exitSplitScreen()
+ }
+ }
+ }
+ transitions {
+ device.resizeSplitScreen(stopRatio)
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
- @Test
- fun checkVisibility_topAppLayerIsAlwaysVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(sSimpleActivity)
- .forAllEntries()
- }
- }
+ all("topAppWindowIsAlwaysVisible", bugId = 156223549) {
+ this.showsAppWindow(sSimpleActivity)
+ }
- @Test
- fun checkVisibility_bottomAppLayerIsAlwaysVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(sImeActivity)
- .forAllEntries()
- }
- }
+ all("bottomAppWindowIsAlwaysVisible", bugId = 156223549) {
+ this.showsAppWindow(sImeActivity)
+ }
+ }
- @Test
- fun checkVisibility_dividerLayerIsAlwaysVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(DOCKED_STACK_DIVIDER)
- .forAllEntries()
- }
- }
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation)
+ navBarLayerRotatesAndScales(rotation)
+ statusBarLayerRotatesScales(rotation)
- @Test
- @FlakyTest
- fun checkPosition_appsStartingBounds() {
- val displayBounds = WindowUtils.getDisplayBounds()
- checkResults { result: TransitionResult ->
- val entries = LayersTrace.parseFrom(result.layersTrace,
- result.layersTracePath, result.layersTraceChecksum)
- Truth.assertThat(entries.entries).isNotEmpty()
- val startingDividerBounds = entries.entries[0].getVisibleBounds(
- DOCKED_STACK_DIVIDER).bounds
- val startingTopAppBounds = Region(0, 0, startingDividerBounds.right,
- startingDividerBounds.top + WindowUtils.getDockedStackDividerInset())
- val startingBottomAppBounds = Region(0,
- startingDividerBounds.bottom - WindowUtils.getDockedStackDividerInset(),
- displayBounds.right,
- displayBounds.bottom - WindowUtils.getNavigationBarHeight())
- LayersTraceSubject.assertThat(result)
- .hasVisibleRegion("SimpleActivity", startingTopAppBounds)
- .inTheBeginning()
- LayersTraceSubject.assertThat(result)
- .hasVisibleRegion("ImeActivity", startingBottomAppBounds)
- .inTheBeginning()
- }
- }
+ all("topAppLayerIsAlwaysVisible") {
+ this.showsLayer(sSimpleActivity)
+ }
- @Test
- @FlakyTest
- fun checkPosition_appsEndingBounds() {
- val displayBounds = WindowUtils.getDisplayBounds()
- checkResults { result: TransitionResult ->
- val entries = LayersTrace.parseFrom(result.layersTrace,
- result.layersTracePath, result.layersTraceChecksum)
- Truth.assertThat(entries.entries).isNotEmpty()
- val endingDividerBounds = entries.entries[entries.entries.size - 1].getVisibleBounds(
- DOCKED_STACK_DIVIDER).bounds
- val startingTopAppBounds = Region(0, 0, endingDividerBounds.right,
- endingDividerBounds.top + WindowUtils.getDockedStackDividerInset())
- val startingBottomAppBounds = Region(0,
- endingDividerBounds.bottom - WindowUtils.getDockedStackDividerInset(),
- displayBounds.right,
- displayBounds.bottom - WindowUtils.getNavigationBarHeight())
- LayersTraceSubject.assertThat(result)
- .hasVisibleRegion(sSimpleActivity, startingTopAppBounds)
- .atTheEnd()
- LayersTraceSubject.assertThat(result)
- .hasVisibleRegion(sImeActivity, startingBottomAppBounds)
- .atTheEnd()
- }
- }
+ all("bottomAppLayerIsAlwaysVisible") {
+ this.showsLayer(sImeActivity)
+ }
- @Test
- fun checkVisibility_navBarWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE)
- .forAllEntries()
- }
- }
+ all("dividerLayerIsAlwaysVisible") {
+ this.showsLayer(DOCKED_STACK_DIVIDER)
+ }
- @Test
- fun checkVisibility_statusBarWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE)
- .forAllEntries()
- }
- }
+ start("appsStartingBounds", enabled = false) {
+ val displayBounds = WindowUtils.displayBounds
+ val entry = this.trace.entries.firstOrNull()
+ ?: throw IllegalStateException("Trace is empty")
+ val dividerBounds = entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
- @Test
- @FlakyTest(bugId = 156223549)
- fun checkVisibility_topAppWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAppWindow(sSimpleActivity)
- .forAllEntries()
- }
- }
+ val topAppBounds = Region(0, 0, dividerBounds.right,
+ dividerBounds.top + WindowUtils.dockedStackDividerInset)
+ val bottomAppBounds = Region(0,
+ dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
+ displayBounds.right,
+ displayBounds.bottom - WindowUtils.navigationBarHeight)
+ this.hasVisibleRegion("SimpleActivity", topAppBounds)
+ .and()
+ .hasVisibleRegion("ImeActivity", bottomAppBounds)
+ }
- @Test
- @FlakyTest(bugId = 156223549)
- fun checkVisibility_bottomAppWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAppWindow(sImeActivity)
- .forAllEntries()
+ end("appsEndingBounds", enabled = false) {
+ val displayBounds = WindowUtils.displayBounds
+ val entry = this.trace.entries.lastOrNull()
+ ?: throw IllegalStateException("Trace is empty")
+ val dividerBounds = entry.getVisibleBounds(DOCKED_STACK_DIVIDER).bounds
+
+ val topAppBounds = Region(0, 0, dividerBounds.right,
+ dividerBounds.top + WindowUtils.dockedStackDividerInset)
+ val bottomAppBounds = Region(0,
+ dividerBounds.bottom - WindowUtils.dockedStackDividerInset,
+ displayBounds.right,
+ displayBounds.bottom - WindowUtils.navigationBarHeight)
+
+ this.hasVisibleRegion(sSimpleActivity, topAppBounds)
+ .and()
+ .hasVisibleRegion(sImeActivity, bottomAppBounds)
+ }
+ }
+
+ eventLog {
+ focusDoesNotChange()
+ }
+ }
}
}
companion object {
private const val sSimpleActivity = "SimpleActivity"
private const val sImeActivity = "ImeActivity"
-
- @AfterClass
- @JvmStatic
- fun teardown() {
- val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
- if (AutomationUtils.isInSplitScreen(device)) {
- AutomationUtils.exitSplitScreen(device)
- }
- }
+ private val rotation = Surface.ROTATION_0
+ private val startRatio = Rational(1, 3)
+ private val stopRatio = Rational(2, 3)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt
index fdcafdb12a78..e2d78399b35b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt
@@ -17,95 +17,112 @@
package com.android.server.wm.flicker.splitscreen
import android.view.Surface
-import androidx.test.InstrumentationRegistry
import androidx.test.filters.LargeTest
-import androidx.test.runner.AndroidJUnit4
-import androidx.test.uiautomator.UiDevice
-import com.android.server.wm.flicker.CommonTransitions
-import com.android.server.wm.flicker.FlickerTestBase
-import com.android.server.wm.flicker.LayersTraceSubject
+import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.StandardAppHelper
-import com.android.server.wm.flicker.TransitionRunner
-import com.android.server.wm.flicker.WindowUtils
-import com.android.server.wm.flicker.WmTraceSubject
-import com.android.server.wm.flicker.helpers.AutomationUtils
-import org.junit.AfterClass
+import com.android.server.wm.flicker.dsl.flicker
+import com.android.server.wm.flicker.focusDoesNotChange
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
+import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
/**
* Test open app to split screen.
* To run this test: `atest FlickerTests:SplitScreenToLauncherTest`
*/
@LargeTest
-@RunWith(AndroidJUnit4::class)
+@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class SplitScreenToLauncherTest : FlickerTestBase() {
- init {
- testApp = StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
+class SplitScreenToLauncherTest(
+ rotationName: String,
+ rotation: Int
+) : NonRotationTestBase(rotationName, rotation) {
+ @Test
+ fun test() {
+ val testApp = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
- }
- override val transitionToRun: TransitionRunner
- get() = CommonTransitions.splitScreenToLauncher(testApp, instrumentation, uiDevice,
- Surface.ROTATION_0).includeJankyRuns().build()
+ flicker(instrumentation) {
+ withTag { buildTestTag("splitScreenToLauncher", testApp, rotation) }
+ repeat { 1 }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ eachRun {
+ testApp.open()
+ this.setRotation(rotation)
+ device.launchSplitScreen()
+ device.waitForIdle()
+ }
+ }
+ teardown {
+ eachRun {
+ testApp.exit()
+ }
+ test {
+ if (device.isInSplitScreen()) {
+ device.exitSplitScreen()
+ }
+ }
+ }
+ transitions {
+ device.exitSplitScreen()
+ }
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ }
- @Test
- fun checkCoveredRegion_noUncoveredRegions() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .coversRegion(WindowUtils.getDisplayBounds()).forAllEntries()
- }
- }
+ layersTrace {
+ navBarLayerIsAlwaysVisible()
+ statusBarLayerIsAlwaysVisible()
+ noUncoveredRegions(rotation)
+ navBarLayerRotatesAndScales(rotation)
+ statusBarLayerRotatesScales(rotation)
- @Test
- fun checkVisibility_dividerLayerBecomesInVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(DOCKED_STACK_DIVIDER)
- .then()
- .hidesLayer(DOCKED_STACK_DIVIDER)
- .forAllEntries()
- }
- }
+ // b/161435597 causes the test not to work on 90 degrees
+ all("dividerLayerBecomesInvisible") {
+ this.showsLayer(DOCKED_STACK_DIVIDER)
+ .then()
+ .hidesLayer(DOCKED_STACK_DIVIDER)
+ }
- @Test
- fun checkVisibility_appLayerBecomesInVisible() {
- checkResults {
- LayersTraceSubject.assertThat(it)
- .showsLayer(testApp.getPackage())
- .then()
- .hidesLayer(testApp.getPackage())
- .forAllEntries()
- }
- }
-
- @Test
- fun checkVisibility_navBarWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
- }
- }
+ all("appLayerBecomesInvisible") {
+ this.showsLayer(testApp.getPackage())
+ .then()
+ .hidesLayer(testApp.getPackage())
+ }
+ }
- @Test
- fun checkVisibility_statusBarWindowIsAlwaysVisible() {
- checkResults {
- WmTraceSubject.assertThat(it)
- .showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries()
+ eventLog {
+ focusDoesNotChange(bugId = 151179149)
+ }
+ }
}
}
companion object {
- @AfterClass
+ @Parameterized.Parameters(name = "{0}")
@JvmStatic
- fun teardown() {
- val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
- if (AutomationUtils.isInSplitScreen(device)) {
- AutomationUtils.exitSplitScreen(device)
- }
+ fun getParams(): Collection<Array<Any>> {
+ // b/161435597 causes the test not to work on 90 degrees
+ val supportedRotations = intArrayOf(Surface.ROTATION_0)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
}
}
}
diff --git a/tests/LocalizationTest/Android.bp b/tests/LocalizationTest/Android.bp
new file mode 100644
index 000000000000..c4bfcb1d2261
--- /dev/null
+++ b/tests/LocalizationTest/Android.bp
@@ -0,0 +1,41 @@
+// 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_test {
+ name: "LocalizationTest",
+ srcs: ["java/**/*.kt"],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ "android.test.mock",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "mockito-target-extended-minus-junit4",
+ "truth-prebuilt",
+ ],
+ jni_libs: [
+ // For mockito extended
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
+ certificate: "platform",
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/core/res/res/drawable-car-night/car_dialog_button_background.xml b/tests/LocalizationTest/AndroidManifest.xml
index 138cb38b0d87..b135443960f5 100644
--- a/core/res/res/drawable-car-night/car_dialog_button_background.xml
+++ b/tests/LocalizationTest/AndroidManifest.xml
@@ -14,19 +14,16 @@
~ 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:state_focused="true">
- <ripple android:color="#2371cd">
- <item android:id="@android:id/mask">
- <color android:color="@*android:color/car_white_1000"/>
- </item>
- </ripple>
- </item>
- <item>
- <ripple android:color="?android:attr/colorControlHighlight">
- <item android:id="@android:id/mask">
- <color android:color="@*android:color/car_white_1000"/>
- </item>
- </ripple>
- </item>
-</selector>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.android.internal.app">
+
+ <application android:debuggable="true" android:testOnly="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.android.internal.app"
+ android:label="Localization Tests" />
+
+</manifest>
diff --git a/tests/LocalizationTest/AndroidTest.xml b/tests/LocalizationTest/AndroidTest.xml
new file mode 100644
index 000000000000..8309b4f611f8
--- /dev/null
+++ b/tests/LocalizationTest/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?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.
+ -->
+<configuration description="Localization Tests.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="LocalizationTest.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="LocalizationTest" />
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.android.internal.app" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration> \ No newline at end of file
diff --git a/tests/LocalizationTest/java/com/android/internal/app/LocalizationTest.kt b/tests/LocalizationTest/java/com/android/internal/app/LocalizationTest.kt
new file mode 100644
index 000000000000..22ea97167326
--- /dev/null
+++ b/tests/LocalizationTest/java/com/android/internal/app/LocalizationTest.kt
@@ -0,0 +1,118 @@
+/*
+ * 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.android.internal.app
+
+import android.os.SystemProperties
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
+import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
+import com.android.internal.R
+import com.android.internal.app.LocalePicker
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.After
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.MockitoSession
+
+@RunWith(AndroidJUnit4::class)
+class LocalizationTest {
+ private val mContext = InstrumentationRegistry.getInstrumentation().context
+ private val mUnfilteredLocales =
+ mContext.getResources().getStringArray(R.array.supported_locales)
+
+ private lateinit var mMockitoSession: MockitoSession
+
+ @Before
+ fun setUp() {
+ mMockitoSession = mockitoSession()
+ .initMocks(this)
+ .spyStatic(SystemProperties::class.java)
+ .startMocking()
+ }
+
+ @After
+ fun tearDown() {
+ mMockitoSession.finishMocking()
+ }
+
+ @Test
+ fun testGetSupportedLocales_noFilter() {
+ // Filter not set.
+ setTestLocaleFilter(null)
+
+ val locales1 = LocalePicker.getSupportedLocales(mContext)
+
+ assertThat(locales1).isEqualTo(mUnfilteredLocales)
+
+ // Empty filter.
+ setTestLocaleFilter("")
+
+ val locales2 = LocalePicker.getSupportedLocales(mContext)
+
+ assertThat(locales2).isEqualTo(mUnfilteredLocales)
+ }
+
+ @Test
+ fun testGetSupportedLocales_invalidFilter() {
+ setTestLocaleFilter("**")
+
+ val locales = LocalePicker.getSupportedLocales(mContext)
+
+ assertThat(locales).isEqualTo(mUnfilteredLocales)
+ }
+
+ @Test
+ fun testGetSupportedLocales_inclusiveFilter() {
+ setTestLocaleFilter("^(de-AT|de-DE|en|ru).*")
+
+ val locales = LocalePicker.getSupportedLocales(mContext)
+
+ assertThat(locales).isEqualTo(
+ mUnfilteredLocales
+ .filter { it.startsWithAnyOf("de-AT", "de-DE", "en", "ru") }
+ .toTypedArray()
+ )
+ }
+
+ @Test
+ fun testGetSupportedLocales_exclusiveFilter() {
+ setTestLocaleFilter("^(?!de-IT|es|fr).*")
+
+ val locales = LocalePicker.getSupportedLocales(mContext)
+
+ assertThat(locales).isEqualTo(
+ mUnfilteredLocales
+ .filter { !it.startsWithAnyOf("de-IT", "es", "fr") }
+ .toTypedArray()
+ )
+ }
+
+ private fun setTestLocaleFilter(localeFilter: String?) {
+ doReturn(localeFilter).`when` { SystemProperties.get(eq("ro.localization.locale_filter")) }
+ }
+
+ private fun String.startsWithAnyOf(vararg prefixes: String): Boolean {
+ prefixes.forEach {
+ if (startsWith(it)) return true
+ }
+
+ return false
+ }
+}
diff --git a/tests/net/common/java/android/net/NetworkProviderTest.kt b/tests/net/common/java/android/net/NetworkProviderTest.kt
index b7c47c2bc223..dd3f5bebdb8e 100644
--- a/tests/net/common/java/android/net/NetworkProviderTest.kt
+++ b/tests/net/common/java/android/net/NetworkProviderTest.kt
@@ -19,23 +19,23 @@ package android.net
import android.app.Instrumentation
import android.content.Context
import android.net.NetworkCapabilities.TRANSPORT_TEST
+import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable
+import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn
+import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested
import android.os.Build
import android.os.HandlerThread
import android.os.Looper
-import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable
-import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested
-import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn
import androidx.test.InstrumentationRegistry
-import com.android.testutils.ArrayTrackRecord
+import com.android.net.module.util.ArrayTrackRecord
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
-import java.util.UUID
-import kotlin.test.assertEquals
-import kotlin.test.assertNotEquals
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import java.util.UUID
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
private const val DEFAULT_TIMEOUT_MS = 5000L
private val instrumentation: Instrumentation
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 1e7fecf50d85..0f24b0c1c79b 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -4226,7 +4226,7 @@ public class ConnectivityServiceTest {
callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
}
- // Sanity check before testing started keepalive.
+ // Basic check before testing started keepalive.
try (SocketKeepalive ka = mCm.createSocketKeepalive(
myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
ka.start(validKaInterval);
diff --git a/tests/net/java/com/android/server/NetIdManagerTest.kt b/tests/net/java/com/android/server/NetIdManagerTest.kt
index 045f89f85e3b..6f5e740d344c 100644
--- a/tests/net/java/com/android/server/NetIdManagerTest.kt
+++ b/tests/net/java/com/android/server/NetIdManagerTest.kt
@@ -19,8 +19,8 @@ package com.android.server
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.server.NetIdManager.MIN_NET_ID
-import com.android.testutils.ExceptionUtils.ThrowingRunnable
import com.android.testutils.assertThrows
+import com.android.testutils.ExceptionUtils.ThrowingRunnable
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index 5a29c2c96ba7..a384687e06f6 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -26,10 +26,9 @@ import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_OEM;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR;
-import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
-import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
+import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.connectivity.PermissionMonitor.NETWORK;
@@ -97,7 +96,6 @@ public class PermissionMonitorTest {
private static final int SYSTEM_UID1 = 1000;
private static final int SYSTEM_UID2 = 1008;
private static final int VPN_UID = 10002;
- private static final String REAL_SYSTEM_PACKAGE_NAME = "android";
private static final String MOCK_PACKAGE1 = "appName1";
private static final String MOCK_PACKAGE2 = "appName2";
private static final String SYSTEM_PACKAGE1 = "sysName1";
@@ -128,6 +126,7 @@ public class PermissionMonitorTest {
new UserInfo(MOCK_USER1, "", 0),
new UserInfo(MOCK_USER2, "", 0),
}));
+ doReturn(PackageManager.PERMISSION_DENIED).when(mDeps).uidPermission(anyString(), anyInt());
mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps));
@@ -140,35 +139,15 @@ public class PermissionMonitorTest {
verify(mMockPmi).getPackageList(mPermissionMonitor);
}
- private boolean hasRestrictedNetworkPermission(String partition, int targetSdkVersion, int uid,
- String... permissions) {
- final PackageInfo packageInfo =
- packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, permissions, partition);
+ private boolean wouldBeCarryoverPackage(String partition, int targetSdkVersion, int uid) {
+ final PackageInfo packageInfo = buildPackageInfo(partition, uid, MOCK_USER1);
packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion;
- packageInfo.applicationInfo.uid = uid;
- return mPermissionMonitor.hasRestrictedNetworkPermission(packageInfo);
- }
-
- private static PackageInfo systemPackageInfoWithPermissions(String... permissions) {
- return packageInfoWithPermissions(
- REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM);
+ return mPermissionMonitor.isCarryoverPackage(packageInfo.applicationInfo);
}
- private static PackageInfo vendorPackageInfoWithPermissions(String... permissions) {
- return packageInfoWithPermissions(
- REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_VENDOR);
- }
-
- private static PackageInfo packageInfoWithPermissions(int permissionsFlags,
- String[] permissions, String partition) {
- int[] requestedPermissionsFlags = new int[permissions.length];
- for (int i = 0; i < permissions.length; i++) {
- requestedPermissionsFlags[i] = permissionsFlags;
- }
+ private static PackageInfo packageInfoWithPartition(String partition) {
final PackageInfo packageInfo = new PackageInfo();
- packageInfo.requestedPermissions = permissions;
packageInfo.applicationInfo = new ApplicationInfo();
- packageInfo.requestedPermissionsFlags = requestedPermissionsFlags;
int privateFlags = 0;
switch (partition) {
case PARTITION_OEM:
@@ -185,168 +164,145 @@ public class PermissionMonitorTest {
return packageInfo;
}
- private static PackageInfo buildPackageInfo(boolean hasSystemPermission, int uid, int userId) {
- final PackageInfo pkgInfo;
- if (hasSystemPermission) {
- pkgInfo = systemPackageInfoWithPermissions(
- CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
- } else {
- pkgInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, new String[] {}, "");
- }
+ private static PackageInfo buildPackageInfo(String partition, int uid, int userId) {
+ final PackageInfo pkgInfo = packageInfoWithPartition(partition);
pkgInfo.applicationInfo.uid = UserHandle.getUid(userId, UserHandle.getAppId(uid));
return pkgInfo;
}
+ /** This will REMOVE all previously set permissions from given uid. */
+ private void removeAllPermissions(int uid) {
+ doReturn(PackageManager.PERMISSION_DENIED).when(mDeps).uidPermission(anyString(), eq(uid));
+ }
+
+ /** Set up mocks so that given UID has the requested permissions. */
+ private void addPermissions(int uid, String... permissions) {
+ for (String permission : permissions) {
+ doReturn(PackageManager.PERMISSION_GRANTED)
+ .when(mDeps).uidPermission(eq(permission), eq(uid));
+ }
+ }
+
@Test
public void testHasPermission() {
- PackageInfo app = systemPackageInfoWithPermissions();
- assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
- assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
- assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
- assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL));
-
- app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE, NETWORK_STACK);
- assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
- assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
- assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
- assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL));
-
- app = systemPackageInfoWithPermissions(
- CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL);
- assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
- assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
- assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
- assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL));
-
- app = packageInfoWithPermissions(REQUESTED_PERMISSION_REQUIRED, new String[] {
- CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL, NETWORK_STACK },
- PARTITION_SYSTEM);
- assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
- assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
- assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
- assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_INTERNAL));
-
- app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE);
- app.requestedPermissions = null;
- assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
-
- app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE);
- app.requestedPermissionsFlags = null;
- assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
+ addPermissions(MOCK_UID1);
+ assertFalse(mPermissionMonitor.hasPermission(CHANGE_NETWORK_STATE, MOCK_UID1));
+ assertFalse(mPermissionMonitor.hasPermission(NETWORK_STACK, MOCK_UID1));
+ assertFalse(mPermissionMonitor.hasPermission(
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID1));
+ assertFalse(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID1));
+
+ addPermissions(MOCK_UID1, CHANGE_NETWORK_STATE, NETWORK_STACK);
+ assertTrue(mPermissionMonitor.hasPermission(CHANGE_NETWORK_STATE, MOCK_UID1));
+ assertTrue(mPermissionMonitor.hasPermission(NETWORK_STACK, MOCK_UID1));
+ assertFalse(mPermissionMonitor.hasPermission(
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID1));
+ assertFalse(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID1));
+ assertFalse(mPermissionMonitor.hasPermission(CHANGE_NETWORK_STATE, MOCK_UID2));
+ assertFalse(mPermissionMonitor.hasPermission(NETWORK_STACK, MOCK_UID2));
+
+ addPermissions(MOCK_UID2, CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL);
+ assertFalse(mPermissionMonitor.hasPermission(
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID1));
+ assertFalse(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID1));
+ assertTrue(mPermissionMonitor.hasPermission(
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS, MOCK_UID2));
+ assertTrue(mPermissionMonitor.hasPermission(CONNECTIVITY_INTERNAL, MOCK_UID2));
}
@Test
public void testIsVendorApp() {
- PackageInfo app = systemPackageInfoWithPermissions();
+ PackageInfo app = packageInfoWithPartition(PARTITION_SYSTEM);
assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo));
- app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED,
- new String[] {}, PARTITION_OEM);
+ app = packageInfoWithPartition(PARTITION_OEM);
assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
- app = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED,
- new String[] {}, PARTITION_PRODUCT);
+ app = packageInfoWithPartition(PARTITION_PRODUCT);
assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
- app = vendorPackageInfoWithPermissions();
+ app = packageInfoWithPartition(PARTITION_VENDOR);
assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
}
- @Test
- public void testHasNetworkPermission() {
- PackageInfo app = systemPackageInfoWithPermissions();
- assertFalse(mPermissionMonitor.hasNetworkPermission(app));
- app = systemPackageInfoWithPermissions(CHANGE_NETWORK_STATE);
- assertTrue(mPermissionMonitor.hasNetworkPermission(app));
- app = systemPackageInfoWithPermissions(NETWORK_STACK);
- assertFalse(mPermissionMonitor.hasNetworkPermission(app));
- app = systemPackageInfoWithPermissions(CONNECTIVITY_USE_RESTRICTED_NETWORKS);
- assertFalse(mPermissionMonitor.hasNetworkPermission(app));
- app = systemPackageInfoWithPermissions(CONNECTIVITY_INTERNAL);
- assertFalse(mPermissionMonitor.hasNetworkPermission(app));
+ /**
+ * Remove all permissions from the uid then setup permissions to uid for checking restricted
+ * network permission.
+ */
+ private void assertRestrictedNetworkPermission(boolean hasPermission, int uid,
+ String... permissions) {
+ removeAllPermissions(uid);
+ addPermissions(uid, permissions);
+ assertEquals(hasPermission, mPermissionMonitor.hasRestrictedNetworkPermission(uid));
}
@Test
public void testHasRestrictedNetworkPermission() {
- assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, MOCK_UID1));
- assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, NETWORK_STACK));
- assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
- assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE));
-
- assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
- assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL));
+ assertRestrictedNetworkPermission(false, MOCK_UID1);
+ assertRestrictedNetworkPermission(false, MOCK_UID1, CHANGE_NETWORK_STATE);
+ assertRestrictedNetworkPermission(true, MOCK_UID1, NETWORK_STACK);
+ assertRestrictedNetworkPermission(false, MOCK_UID1, CONNECTIVITY_INTERNAL);
+ assertRestrictedNetworkPermission(true, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
+ assertRestrictedNetworkPermission(false, MOCK_UID1, CHANGE_WIFI_STATE);
+ assertRestrictedNetworkPermission(true, MOCK_UID1, PERMISSION_MAINLINE_NETWORK_STACK);
+
+ assertFalse(mPermissionMonitor.hasRestrictedNetworkPermission(MOCK_UID2));
+ assertFalse(mPermissionMonitor.hasRestrictedNetworkPermission(SYSTEM_UID));
}
@Test
- public void testHasRestrictedNetworkPermissionSystemUid() {
+ public void testIsCarryoverPackage() {
doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt();
- assertTrue(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_INTERNAL));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1));
doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt();
- assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
- assertFalse(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_INTERNAL));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
- }
-
- @Test
- public void testHasRestrictedNetworkPermissionVendorApp() {
- assertTrue(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_P, MOCK_UID1));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, NETWORK_STACK));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
- assertTrue(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_P, MOCK_UID1, CHANGE_WIFI_STATE));
-
- assertFalse(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_Q, MOCK_UID1));
- assertFalse(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL));
- assertFalse(hasRestrictedNetworkPermission(
- PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_NETWORK_STATE));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_P, MOCK_UID1));
+ assertTrue(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_P, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_VENDOR, VERSION_Q, MOCK_UID1));
+
+ assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, SYSTEM_UID));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_OEM, VERSION_Q, MOCK_UID1));
+ assertFalse(wouldBeCarryoverPackage(PARTITION_PRODUCT, VERSION_Q, MOCK_UID1));
}
private void assertBackgroundPermission(boolean hasPermission, String name, int uid,
String... permissions) throws Exception {
when(mPackageManager.getPackageInfo(eq(name), anyInt()))
- .thenReturn(packageInfoWithPermissions(
- REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM));
+ .thenReturn(buildPackageInfo(PARTITION_SYSTEM, uid, MOCK_USER1));
+ addPermissions(uid, permissions);
mPermissionMonitor.onPackageAdded(name, uid);
assertEquals(hasPermission, mPermissionMonitor.hasUseBackgroundNetworksPermission(uid));
}
@Test
public void testHasUseBackgroundNetworksPermission() throws Exception {
- assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(SYSTEM_UID));
- assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID);
- assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID, CONNECTIVITY_INTERNAL);
- assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, CHANGE_NETWORK_STATE);
- assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, NETWORK_STACK);
-
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID1));
- assertBackgroundPermission(false, MOCK_PACKAGE1, MOCK_UID1);
- assertBackgroundPermission(true, MOCK_PACKAGE1, MOCK_UID1,
- CONNECTIVITY_USE_RESTRICTED_NETWORKS);
+ assertBackgroundPermission(false, "mock1", MOCK_UID1);
+ assertBackgroundPermission(false, "mock2", MOCK_UID1, CONNECTIVITY_INTERNAL);
+ assertBackgroundPermission(true, "mock3", MOCK_UID1, NETWORK_STACK);
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID2));
- assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2);
- assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2,
- CONNECTIVITY_INTERNAL);
- assertBackgroundPermission(true, MOCK_PACKAGE2, MOCK_UID2, NETWORK_STACK);
+ assertBackgroundPermission(false, "mock4", MOCK_UID2);
+ assertBackgroundPermission(true, "mock5", MOCK_UID2,
+ CONNECTIVITY_USE_RESTRICTED_NETWORKS);
+
+ doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt();
+ assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(SYSTEM_UID));
+ assertBackgroundPermission(false, "system1", SYSTEM_UID);
+ assertBackgroundPermission(true, "system2", SYSTEM_UID, CHANGE_NETWORK_STATE);
+ doReturn(VERSION_P).when(mDeps).getDeviceFirstSdkInt();
+ removeAllPermissions(SYSTEM_UID);
+ assertBackgroundPermission(true, "system3", SYSTEM_UID);
}
private class NetdMonitor {
@@ -416,13 +372,14 @@ public class PermissionMonitorTest {
// MOCK_UID1: MOCK_PACKAGE1 only has network permission.
// SYSTEM_UID: SYSTEM_PACKAGE1 has system permission.
// SYSTEM_UID: SYSTEM_PACKAGE2 only has network permission.
- doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM), anyString());
+ doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(eq(SYSTEM),
+ anyString(), anyInt());
doReturn(SYSTEM).when(mPermissionMonitor).highestPermissionForUid(any(),
- eq(SYSTEM_PACKAGE1));
+ eq(SYSTEM_PACKAGE1), anyInt());
doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(),
- eq(SYSTEM_PACKAGE2));
+ eq(SYSTEM_PACKAGE2), anyInt());
doReturn(NETWORK).when(mPermissionMonitor).highestPermissionForUid(any(),
- eq(MOCK_PACKAGE1));
+ eq(MOCK_PACKAGE1), anyInt());
// Add SYSTEM_PACKAGE2, expect only have network permission.
mPermissionMonitor.onUserAdded(MOCK_USER1);
@@ -473,13 +430,15 @@ public class PermissionMonitorTest {
public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdates() throws Exception {
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
Arrays.asList(new PackageInfo[] {
- buildPackageInfo(/* SYSTEM */ true, SYSTEM_UID1, MOCK_USER1),
- buildPackageInfo(/* SYSTEM */ false, MOCK_UID1, MOCK_USER1),
- buildPackageInfo(/* SYSTEM */ false, MOCK_UID2, MOCK_USER1),
- buildPackageInfo(/* SYSTEM */ false, VPN_UID, MOCK_USER1)
+ buildPackageInfo(PARTITION_SYSTEM, SYSTEM_UID1, MOCK_USER1),
+ buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1),
+ buildPackageInfo(PARTITION_SYSTEM, MOCK_UID2, MOCK_USER1),
+ buildPackageInfo(PARTITION_SYSTEM, VPN_UID, MOCK_USER1)
}));
when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn(
- buildPackageInfo(false, MOCK_UID1, MOCK_USER1));
+ buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1));
+ addPermissions(SYSTEM_UID,
+ CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
mPermissionMonitor.startMonitoring();
// Every app on user 0 except MOCK_UID2 are under VPN.
final Set<UidRange> vpnRange1 = new HashSet<>(Arrays.asList(new UidRange[] {
@@ -524,11 +483,11 @@ public class PermissionMonitorTest {
public void testUidFilteringDuringPackageInstallAndUninstall() throws Exception {
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
Arrays.asList(new PackageInfo[] {
- buildPackageInfo(true, SYSTEM_UID1, MOCK_USER1),
- buildPackageInfo(false, VPN_UID, MOCK_USER1)
+ buildPackageInfo(PARTITION_SYSTEM, SYSTEM_UID1, MOCK_USER1),
+ buildPackageInfo(PARTITION_SYSTEM, VPN_UID, MOCK_USER1)
}));
when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE1), eq(GET_PERMISSIONS))).thenReturn(
- buildPackageInfo(false, MOCK_UID1, MOCK_USER1));
+ buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1));
mPermissionMonitor.startMonitoring();
final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(MOCK_USER1));
@@ -633,10 +592,10 @@ public class PermissionMonitorTest {
private PackageInfo setPackagePermissions(String packageName, int uid, String[] permissions)
throws Exception {
- PackageInfo packageInfo = packageInfoWithPermissions(
- REQUESTED_PERMISSION_GRANTED, permissions, PARTITION_SYSTEM);
+ final PackageInfo packageInfo = buildPackageInfo(PARTITION_SYSTEM, uid, MOCK_USER1);
when(mPackageManager.getPackageInfo(eq(packageName), anyInt())).thenReturn(packageInfo);
when(mPackageManager.getPackagesForUid(eq(uid))).thenReturn(new String[]{packageName});
+ addPermissions(uid, permissions);
return packageInfo;
}
@@ -663,14 +622,13 @@ public class PermissionMonitorTest {
public void testPackageInstallSharedUid() throws Exception {
final NetdServiceMonitor mNetdServiceMonitor = new NetdServiceMonitor(mNetdService);
- PackageInfo packageInfo1 = addPackage(MOCK_PACKAGE1, MOCK_UID1,
- new String[] {INTERNET, UPDATE_DEVICE_STATS});
+ 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});
// Install another package with the same uid and no permissions should not cause the UID to
// lose permissions.
- PackageInfo packageInfo2 = systemPackageInfoWithPermissions();
+ final PackageInfo packageInfo2 = buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1);
when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
when(mPackageManager.getPackagesForUid(MOCK_UID1))
.thenReturn(new String[]{MOCK_PACKAGE1, MOCK_PACKAGE2});
@@ -701,6 +659,7 @@ public class PermissionMonitorTest {
| INetd.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});
@@ -728,10 +687,12 @@ public class PermissionMonitorTest {
| INetd.PERMISSION_UPDATE_DEVICE_STATS, new int[]{MOCK_UID1});
// Mock another package with the same uid but different permissions.
- PackageInfo packageInfo2 = systemPackageInfoWithPermissions(INTERNET);
+ final PackageInfo packageInfo2 = buildPackageInfo(PARTITION_SYSTEM, MOCK_UID1, MOCK_USER1);
when(mPackageManager.getPackageInfo(eq(MOCK_PACKAGE2), anyInt())).thenReturn(packageInfo2);
when(mPackageManager.getPackagesForUid(MOCK_UID1)).thenReturn(new String[]{
MOCK_PACKAGE2});
+ removeAllPermissions(MOCK_UID1);
+ addPermissions(MOCK_UID1, INTERNET);
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID1);
mNetdServiceMonitor.expectPermission(INetd.PERMISSION_INTERNET, new int[]{MOCK_UID1});
@@ -743,9 +704,6 @@ public class PermissionMonitorTest {
// necessary permission.
final Context realContext = InstrumentationRegistry.getContext();
final PermissionMonitor monitor = new PermissionMonitor(realContext, mNetdService);
- final PackageManager manager = realContext.getPackageManager();
- final PackageInfo systemInfo = manager.getPackageInfo(REAL_SYSTEM_PACKAGE_NAME,
- GET_PERMISSIONS | MATCH_ANY_USER);
- assertTrue(monitor.hasPermission(systemInfo, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
+ assertTrue(monitor.hasPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, SYSTEM_UID));
}
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index 551498f2c0cc..e83d2a90bffa 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -23,11 +23,12 @@ import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
+import static android.net.NetworkUtils.multiplySafeByRational;
import static android.os.Process.myUid;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
-import static com.android.server.net.NetworkStatsCollection.multiplySafe;
+import static com.android.testutils.MiscAssertsKt.assertThrows;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -505,23 +506,25 @@ public class NetworkStatsCollectionTest {
}
@Test
- public void testMultiplySafe() {
- assertEquals(25, multiplySafe(50, 1, 2));
- assertEquals(100, multiplySafe(50, 2, 1));
+ public void testMultiplySafeRational() {
+ assertEquals(25, multiplySafeByRational(50, 1, 2));
+ assertEquals(100, multiplySafeByRational(50, 2, 1));
- assertEquals(-10, multiplySafe(30, -1, 3));
- assertEquals(0, multiplySafe(30, 0, 3));
- assertEquals(10, multiplySafe(30, 1, 3));
- assertEquals(20, multiplySafe(30, 2, 3));
- assertEquals(30, multiplySafe(30, 3, 3));
- assertEquals(40, multiplySafe(30, 4, 3));
+ assertEquals(-10, multiplySafeByRational(30, -1, 3));
+ assertEquals(0, multiplySafeByRational(30, 0, 3));
+ assertEquals(10, multiplySafeByRational(30, 1, 3));
+ assertEquals(20, multiplySafeByRational(30, 2, 3));
+ assertEquals(30, multiplySafeByRational(30, 3, 3));
+ assertEquals(40, multiplySafeByRational(30, 4, 3));
assertEquals(100_000_000_000L,
- multiplySafe(300_000_000_000L, 10_000_000_000L, 30_000_000_000L));
+ multiplySafeByRational(300_000_000_000L, 10_000_000_000L, 30_000_000_000L));
assertEquals(100_000_000_010L,
- multiplySafe(300_000_000_000L, 10_000_000_001L, 30_000_000_000L));
+ multiplySafeByRational(300_000_000_000L, 10_000_000_001L, 30_000_000_000L));
assertEquals(823_202_048L,
- multiplySafe(4_939_212_288L, 2_121_815_528L, 12_730_893_165L));
+ multiplySafeByRational(4_939_212_288L, 2_121_815_528L, 12_730_893_165L));
+
+ assertThrows(ArithmeticException.class, () -> multiplySafeByRational(30, 3, 0));
}
/**
diff --git a/tests/utils/DummyIME/Android.bp b/tests/utils/StubIME/Android.bp
index 4a44b3b27992..668c92c86c51 100644
--- a/tests/utils/DummyIME/Android.bp
+++ b/tests/utils/StubIME/Android.bp
@@ -15,7 +15,7 @@
//
android_test {
- name: "DummyIME",
+ name: "StubIME",
srcs: ["src/**/*.java"],
sdk_version: "current",
}
diff --git a/tests/utils/DummyIME/AndroidManifest.xml b/tests/utils/StubIME/AndroidManifest.xml
index 4dc0b57e1075..bc64c671d9be 100644
--- a/tests/utils/DummyIME/AndroidManifest.xml
+++ b/tests/utils/StubIME/AndroidManifest.xml
@@ -18,20 +18,20 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.testing.dummyime">
+ package="com.android.testing.stubime">
<application android:label="Dummy IME">
<service android:name="DummyIme"
- android:permission="android.permission.BIND_INPUT_METHOD"
- android:exported="true">
+ android:permission="android.permission.BIND_INPUT_METHOD"
+ android:exported="true">
<intent-filter>
<action android:name="android.view.InputMethod"/>
</intent-filter>
<meta-data android:name="android.view.im"
- android:resource="@xml/method"/>
+ android:resource="@xml/method"/>
</service>
<activity android:name=".ImePreferences"
- android:label="Dummy IME Settings"
- android:exported="true">
+ android:label="Stub IME Settings"
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
diff --git a/tests/utils/DummyIME/res/xml/method.xml b/tests/utils/StubIME/res/xml/method.xml
index 43a330e2bc93..1bb4bcd3480b 100644
--- a/tests/utils/DummyIME/res/xml/method.xml
+++ b/tests/utils/StubIME/res/xml/method.xml
@@ -21,9 +21,9 @@
<!-- for the Search Manager. -->
<input-method xmlns:android="http://schemas.android.com/apk/res/android"
- android:settingsActivity="com.android.testing.dummyime.ImePreferences">
+ android:settingsActivity="com.android.testing.stubime.ImePreferences">
<subtype
android:label="Generic"
android:imeSubtypeLocale="en_US"
android:imeSubtypeMode="keyboard" />
-</input-method> \ No newline at end of file
+</input-method>
diff --git a/tests/utils/DummyIME/src/com/android/testing/dummyime/ImePreferences.java b/tests/utils/StubIME/src/com/android/testing/stubime/ImePreferences.java
index 41036ab86596..b77525ad0a43 100644
--- a/tests/utils/DummyIME/src/com/android/testing/dummyime/ImePreferences.java
+++ b/tests/utils/StubIME/src/com/android/testing/stubime/ImePreferences.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package com.android.testing.dummyime;
+package com.android.testing.stubime;
import android.preference.PreferenceActivity;
/**
- * Dummy IME preference activity
+ * Stub IME preference activity
*/
public class ImePreferences extends PreferenceActivity {
diff --git a/tests/utils/DummyIME/src/com/android/testing/dummyime/DummyIme.java b/tests/utils/StubIME/src/com/android/testing/stubime/StubIme.java
index 7b7a39a702e5..8795202b3283 100644
--- a/tests/utils/DummyIME/src/com/android/testing/dummyime/DummyIme.java
+++ b/tests/utils/StubIME/src/com/android/testing/stubime/StubIme.java
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-package com.android.testing.dummyime;
+package com.android.testing.stubime;
import android.inputmethodservice.InputMethodService;
/**
- * Dummy IME implementation that basically does nothing
+ * Stub IME implementation that basically does nothing
*/
-public class DummyIme extends InputMethodService {
+public class StubIme extends InputMethodService {
@Override
public boolean onEvaluateFullscreenMode() {
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 931a14b1f650..3d9be59dd960 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -342,7 +342,7 @@ bool ResourceParser::FlattenXmlSubtree(
}
}
- // Sanity check to make sure we processed all the nodes.
+ // Validity check to make sure we processed all the nodes.
CHECK(node_stack.size() == 1u);
CHECK(node_stack.back() == &root);
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 469128b1e50b..7dfc983b54ba 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -740,7 +740,7 @@ std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const Config
if (type == ResourceType::kId) {
if (res_value.dataType != android::Res_value::TYPE_REFERENCE &&
res_value.dataType != android::Res_value::TYPE_DYNAMIC_REFERENCE) {
- // plain "id" resources are actually encoded as dummy values (aapt1 uses an empty string,
+ // plain "id" resources are actually encoded as unused values (aapt1 uses an empty string,
// while aapt2 uses a false boolean).
return util::make_unique<Id>();
}
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index ab9ce66b0ae3..b1e1a77e1224 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -168,6 +168,7 @@ message OverlayableItem {
ODM = 6;
OEM = 7;
ACTOR = 8;
+ CONFIG_SIGNATURE = 9;
}
// The location of the <item> declaration in source.
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index fb7f6d717c72..f9c54f645e2c 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -1401,7 +1401,7 @@ class Linker {
return MergeExportedSymbols(compiled_file.source, compiled_file.exported_symbols);
}
- // Takes a path to load as a ZIP file and merges the files within into the master ResourceTable.
+ // Takes a path to load as a ZIP file and merges the files within into the main ResourceTable.
// If override is true, conflicting resources are allowed to override each other, in order of last
// seen.
// An io::IFileCollection is created from the ZIP file and added to the set of
@@ -1432,7 +1432,7 @@ class Linker {
return !error;
}
- // Takes a path to load and merge into the master ResourceTable. If override is true,
+ // Takes a path to load and merge into the main ResourceTable. If override is true,
// conflicting resources are allowed to override each other, in order of last seen.
// If the file path ends with .flata, .jar, .jack, or .zip the file is treated
// as ZIP archive and the files within are merged individually.
@@ -1449,7 +1449,7 @@ class Linker {
return MergeFile(file, override);
}
- // Takes an AAPT Container file (.apc/.flat) to load and merge into the master ResourceTable.
+ // Takes an AAPT Container file (.apc/.flat) to load and merge into the main ResourceTable.
// If override is true, conflicting resources are allowed to override each other, in order of last
// seen.
// All other file types are ignored. This is because these files could be coming from a zip,
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp
index e36668e5a043..5b18a3789d76 100644
--- a/tools/aapt2/cmd/Optimize.cpp
+++ b/tools/aapt2/cmd/Optimize.cpp
@@ -132,8 +132,8 @@ class Optimizer {
if (context_->IsVerbose()) {
context_->GetDiagnostics()->Note(DiagMessage() << "Optimizing APK...");
}
- if (!options_.resources_blacklist.empty()) {
- ResourceFilter filter(options_.resources_blacklist);
+ if (!options_.resources_exclude_list.empty()) {
+ ResourceFilter filter(options_.resources_exclude_list);
if (!filter.Consume(context_, apk->GetResourceTable())) {
context_->GetDiagnostics()->Error(DiagMessage() << "failed filtering resources");
return 1;
@@ -328,7 +328,7 @@ bool ParseConfig(const std::string& content, IAaptContext* context, OptimizeOpti
}
for (StringPiece directive : util::Tokenize(directives, ',')) {
if (directive == "remove") {
- options->resources_blacklist.insert(resource_name.ToResourceName());
+ options->resources_exclude_list.insert(resource_name.ToResourceName());
} else if (directive == "no_collapse" || directive == "no_obfuscate") {
options->table_flattener_options.name_collapse_exemptions.insert(
resource_name.ToResourceName());
diff --git a/tools/aapt2/cmd/Optimize.h b/tools/aapt2/cmd/Optimize.h
index 5070ccc8afbf..3afc46b04af6 100644
--- a/tools/aapt2/cmd/Optimize.h
+++ b/tools/aapt2/cmd/Optimize.h
@@ -36,8 +36,8 @@ struct OptimizeOptions {
// Details of the app extracted from the AndroidManifest.xml
AppInfo app_info;
- // Blacklist of unused resources that should be removed from the apk.
- std::unordered_set<ResourceName> resources_blacklist;
+ // Exclude list of unused resources that should be removed from the apk.
+ std::unordered_set<ResourceName> resources_exclude_list;
// Split APK options.
TableSplitterOptions table_splitter_options;
diff --git a/tools/aapt2/compile/PngChunkFilter.cpp b/tools/aapt2/compile/PngChunkFilter.cpp
index bc2e6990433c..4db2392b4eab 100644
--- a/tools/aapt2/compile/PngChunkFilter.cpp
+++ b/tools/aapt2/compile/PngChunkFilter.cpp
@@ -35,7 +35,7 @@ constexpr uint32_t u32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
((uint32_t)d);
}
-// Whitelist of PNG chunk types that we want to keep in the resulting PNG.
+// Allow list of PNG chunk types that we want to keep in the resulting PNG.
enum PngChunkTypes {
kPngChunkIHDR = u32(73, 72, 68, 82),
kPngChunkIDAT = u32(73, 68, 65, 84),
@@ -56,7 +56,7 @@ static uint32_t Peek32LE(const char* data) {
return word;
}
-static bool IsPngChunkWhitelisted(uint32_t type) {
+static bool IsPngChunkAllowed(uint32_t type) {
switch (type) {
case kPngChunkIHDR:
case kPngChunkIDAT:
@@ -128,7 +128,7 @@ bool PngChunkFilter::Next(const void** buffer, size_t* len) {
// Do we strip this chunk?
const uint32_t chunk_type = Peek32LE(data_.data() + window_end_ + sizeof(uint32_t));
- if (IsPngChunkWhitelisted(chunk_type)) {
+ if (IsPngChunkAllowed(chunk_type)) {
// Advance the window to include this chunk.
window_end_ += kMinChunkHeaderSize + chunk_len;
diff --git a/tools/aapt2/configuration/ConfigurationParser_test.cpp b/tools/aapt2/configuration/ConfigurationParser_test.cpp
index 2ef8b999a192..e5b3107877cb 100644
--- a/tools/aapt2/configuration/ConfigurationParser_test.cpp
+++ b/tools/aapt2/configuration/ConfigurationParser_test.cpp
@@ -187,7 +187,7 @@ TEST_F(ConfigurationParserTest, ForPath_NoFile) {
TEST_F(ConfigurationParserTest, ExtractConfiguration) {
Maybe<PostProcessingConfiguration> maybe_config =
- ExtractConfiguration(kValidConfig, "dummy.xml", &diag_);
+ ExtractConfiguration(kValidConfig, "fake.xml", &diag_);
PostProcessingConfiguration config = maybe_config.value();
diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp
index 53d9ffe21949..71c70da96109 100644
--- a/tools/aapt2/dump/DumpManifest.cpp
+++ b/tools/aapt2/dump/DumpManifest.cpp
@@ -188,7 +188,7 @@ class ManifestExtractor {
/** Retrieves the resource assigned to the specified resource id if one exists. */
Value* FindValueById(const ResourceTable* table, const ResourceId& res_id,
- const ConfigDescription& config = DummyConfig()) {
+ const ConfigDescription& config = DefaultConfig()) {
if (table) {
for (auto& package : table->packages) {
if (package->id && package->id.value() == res_id.package_id()) {
@@ -210,7 +210,7 @@ class ManifestExtractor {
}
/** Attempts to resolve the reference to a non-reference value. */
- Value* ResolveReference(Reference* ref, const ConfigDescription& config = DummyConfig()) {
+ Value* ResolveReference(Reference* ref, const ConfigDescription& config = DefaultConfig()) {
const int kMaxIterations = 40;
int i = 0;
while (ref && ref->id && i++ < kMaxIterations) {
@@ -231,10 +231,10 @@ class ManifestExtractor {
* this will attempt to resolve the reference to an integer value.
**/
int32_t* GetAttributeInteger(xml::Attribute* attr,
- const ConfigDescription& config = DummyConfig()) {
+ const ConfigDescription& config = DefaultConfig()) {
if (attr != nullptr) {
if (attr->compiled_value) {
- // Resolve references using the dummy configuration
+ // Resolve references using the configuration
Value* value = attr->compiled_value.get();
if (ValueCast<Reference>(value)) {
value = ResolveReference(ValueCast<Reference>(value), config);
@@ -257,7 +257,7 @@ class ManifestExtractor {
* exist or cannot be resolved to an integer value.
**/
int32_t GetAttributeIntegerDefault(xml::Attribute* attr, int32_t def,
- const ConfigDescription& config = DummyConfig()) {
+ const ConfigDescription& config = DefaultConfig()) {
auto value = GetAttributeInteger(attr, config);
if (value) {
return *value;
@@ -270,10 +270,10 @@ class ManifestExtractor {
* this will attempt to resolve the reference to a string value.
**/
const std::string* GetAttributeString(xml::Attribute* attr,
- const ConfigDescription& config = DummyConfig()) {
+ const ConfigDescription& config = DefaultConfig()) {
if (attr != nullptr) {
if (attr->compiled_value) {
- // Resolve references using the dummy configuration
+ // Resolve references using the configuration
Value* value = attr->compiled_value.get();
if (ValueCast<Reference>(value)) {
value = ResolveReference(ValueCast<Reference>(value), config);
@@ -305,7 +305,7 @@ class ManifestExtractor {
* exist or cannot be resolved to an string value.
**/
std::string GetAttributeStringDefault(xml::Attribute* attr, std::string def,
- const ConfigDescription& config = DummyConfig()) {
+ const ConfigDescription& config = DefaultConfig()) {
auto value = GetAttributeString(attr, config);
if (value) {
return *value;
@@ -322,7 +322,7 @@ class ManifestExtractor {
friend Element;
/** Creates a default configuration used to retrieve resources. */
- static ConfigDescription DummyConfig() {
+ static ConfigDescription DefaultConfig() {
ConfigDescription config;
config.orientation = android::ResTable_config::ORIENTATION_PORT;
config.density = android::ResTable_config::DENSITY_MEDIUM;
@@ -1871,7 +1871,7 @@ bool ManifestExtractor::Dump(text::Printer* printer, IDiagnostics* diag) {
// Collect all the unique locales of the apk
if (locales_.find(locale_str) == locales_.end()) {
- ConfigDescription config = ManifestExtractor::DummyConfig();
+ ConfigDescription config = ManifestExtractor::DefaultConfig();
config.setBcp47Locale(locale_str.data());
locales_.insert(std::make_pair(locale_str, config));
}
@@ -1880,7 +1880,7 @@ bool ManifestExtractor::Dump(text::Printer* printer, IDiagnostics* diag) {
uint16_t density = (value->config.density == 0) ? (uint16_t) 160
: value->config.density;
if (densities_.find(density) == densities_.end()) {
- ConfigDescription config = ManifestExtractor::DummyConfig();
+ ConfigDescription config = ManifestExtractor::DefaultConfig();
config.density = density;
densities_.insert(std::make_pair(density, config));
}
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index 59627ce579af..6932baf76c75 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -776,6 +776,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
OverlayableItem overlayable_item_three(group_one);
overlayable_item_three.policies |= PolicyFlags::SIGNATURE;
overlayable_item_three.policies |= PolicyFlags::ACTOR_SIGNATURE;
+ overlayable_item_three.policies |= PolicyFlags::CONFIG_SIGNATURE;
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
@@ -830,7 +831,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
EXPECT_EQ(result_overlayable.policies, PolicyFlags::SIGNATURE
- | PolicyFlags::ACTOR_SIGNATURE);
+ | PolicyFlags::ACTOR_SIGNATURE
+ | PolicyFlags::CONFIG_SIGNATURE);
}
TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) {
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 582bd3983265..06ac9e5dc5c4 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -404,6 +404,9 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable,
case pb::OverlayableItem::ACTOR:
out_overlayable->policies |= PolicyFlags::ACTOR_SIGNATURE;
break;
+ case pb::OverlayableItem::CONFIG_SIGNATURE:
+ out_overlayable->policies |= PolicyFlags::CONFIG_SIGNATURE;
+ break;
default:
*out_error = "unknown overlayable policy";
return false;
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 5ab43b7be378..98c517510028 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -325,6 +325,9 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item
if (overlayable_item.policies & PolicyFlags::ACTOR_SIGNATURE) {
pb_overlayable_item->add_policy(pb::OverlayableItem::ACTOR);
}
+ if (overlayable_item.policies & PolicyFlags::CONFIG_SIGNATURE) {
+ pb_overlayable_item->add_policy(pb::OverlayableItem::CONFIG_SIGNATURE);
+ }
if (source_pool != nullptr) {
SerializeSourceToPb(overlayable_item.source, source_pool,
diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp
index ba9646f9aeb4..ec3c5431c7a3 100644
--- a/tools/aapt2/jni/aapt2_jni.cpp
+++ b/tools/aapt2/jni/aapt2_jni.cpp
@@ -139,5 +139,5 @@ JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(JNIEnv*
JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping(
JNIEnv *env, jclass aapt_obj) {
- // This is just a dummy method to see if the library has been loaded.
+ // This is just a no-op method to see if the library has been loaded.
}
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 49f8e1bcd30b..dac21d7e9200 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -570,8 +570,8 @@ bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
}
xml::XmlActionExecutorPolicy policy = options_.warn_validation
- ? xml::XmlActionExecutorPolicy::kWhitelistWarning
- : xml::XmlActionExecutorPolicy::kWhitelist;
+ ? xml::XmlActionExecutorPolicy::kAllowListWarning
+ : xml::XmlActionExecutorPolicy::kAllowList;
if (!executor.Execute(policy, context->GetDiagnostics(), doc)) {
return false;
}
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index c25e4503a208..ad56092754aa 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -31,11 +31,11 @@ namespace aapt {
TableMerger::TableMerger(IAaptContext* context, ResourceTable* out_table,
const TableMergerOptions& options)
- : context_(context), master_table_(out_table), options_(options) {
+ : context_(context), main_table_(out_table), options_(options) {
// Create the desired package that all tables will be merged into.
- master_package_ =
- master_table_->CreatePackage(context_->GetCompilationPackage(), context_->GetPackageId());
- CHECK(master_package_ != nullptr) << "package name or ID already taken";
+ main_package_ =
+ main_table_->CreatePackage(context_->GetCompilationPackage(), context_->GetPackageId());
+ CHECK(main_package_ != nullptr) << "package name or ID already taken";
}
bool TableMerger::Merge(const Source& src, ResourceTable* table, bool overlay) {
@@ -235,7 +235,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package,
bool error = false;
for (auto& src_type : src_package->types) {
- ResourceTableType* dst_type = master_package_->FindOrCreateType(src_type->type);
+ ResourceTableType* dst_type = main_package_->FindOrCreateType(src_type->type);
if (!MergeType(context_, src, dst_type, src_type.get())) {
error = true;
continue;
@@ -279,7 +279,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package,
if (dst_config_value) {
CollisionResult collision_result = MergeConfigValue(
context_, res_name, overlay, options_.override_styles_instead_of_overlaying,
- dst_config_value, src_config_value.get(), &master_table_->string_pool);
+ dst_config_value, src_config_value.get(), &main_table_->string_pool);
if (collision_result == CollisionResult::kConflict) {
error = true;
continue;
@@ -298,7 +298,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package,
if (mangle_package) {
new_file_ref = CloneAndMangleFile(src_package->name, *f);
} else {
- new_file_ref = std::unique_ptr<FileReference>(f->Clone(&master_table_->string_pool));
+ new_file_ref = std::unique_ptr<FileReference>(f->Clone(&main_table_->string_pool));
}
dst_config_value->value = std::move(new_file_ref);
@@ -307,7 +307,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package,
? dst_config_value->value->GetComment() : Maybe<std::string>();
dst_config_value->value = std::unique_ptr<Value>(
- src_config_value->value->Clone(&master_table_->string_pool));
+ src_config_value->value->Clone(&main_table_->string_pool));
// Keep the comment from the original resource and ignore all comments from overlaying
// resources
@@ -328,14 +328,14 @@ std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile(
std::string mangled_entry = NameMangler::MangleEntry(package, entry.to_string());
std::string newPath = prefix.to_string() + mangled_entry + suffix.to_string();
std::unique_ptr<FileReference> new_file_ref =
- util::make_unique<FileReference>(master_table_->string_pool.MakeRef(newPath));
+ util::make_unique<FileReference>(main_table_->string_pool.MakeRef(newPath));
new_file_ref->SetComment(file_ref.GetComment());
new_file_ref->SetSource(file_ref.GetSource());
new_file_ref->type = file_ref.type;
new_file_ref->file = file_ref.file;
return new_file_ref;
}
- return std::unique_ptr<FileReference>(file_ref.Clone(&master_table_->string_pool));
+ return std::unique_ptr<FileReference>(file_ref.Clone(&main_table_->string_pool));
}
bool TableMerger::MergeFile(const ResourceFile& file_desc, bool overlay, io::IFile* file) {
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index a35a134a887d..e01a0c186392 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -80,9 +80,9 @@ class TableMerger {
DISALLOW_COPY_AND_ASSIGN(TableMerger);
IAaptContext* context_;
- ResourceTable* master_table_;
+ ResourceTable* main_table_;
TableMergerOptions options_;
- ResourceTablePackage* master_package_;
+ ResourceTablePackage* main_package_;
std::set<std::string> merged_packages_;
bool MergeImpl(const Source& src, ResourceTable* src_table, bool overlay, bool allow_new);
diff --git a/tools/aapt2/link/XmlCompatVersioner.cpp b/tools/aapt2/link/XmlCompatVersioner.cpp
index 20ebdc696814..6937ca961f06 100644
--- a/tools/aapt2/link/XmlCompatVersioner.cpp
+++ b/tools/aapt2/link/XmlCompatVersioner.cpp
@@ -143,8 +143,8 @@ std::vector<std::unique_ptr<xml::XmlResource>> XmlCompatVersioner::Process(
// Iterate from smallest to largest API version.
for (ApiVersion api : apis_referenced) {
- std::set<ApiVersion> dummy;
- versioned_docs.push_back(ProcessDoc(api, api_range.end, doc, &dummy));
+ std::set<ApiVersion> tmp;
+ versioned_docs.push_back(ProcessDoc(api, api_range.end, doc, &tmp));
}
return versioned_docs;
}
diff --git a/tools/aapt2/optimize/ResourceFilter.cpp b/tools/aapt2/optimize/ResourceFilter.cpp
index 250b65197a7d..08c045bf68f7 100644
--- a/tools/aapt2/optimize/ResourceFilter.cpp
+++ b/tools/aapt2/optimize/ResourceFilter.cpp
@@ -20,8 +20,8 @@
namespace aapt {
-ResourceFilter::ResourceFilter(const std::unordered_set<ResourceName>& blacklist)
- : blacklist_(blacklist) {
+ResourceFilter::ResourceFilter(const std::unordered_set<ResourceName>& exclude_list)
+ : exclude_list_(exclude_list) {
}
bool ResourceFilter::Consume(IAaptContext* context, ResourceTable* table) {
@@ -29,7 +29,7 @@ bool ResourceFilter::Consume(IAaptContext* context, ResourceTable* table) {
for (auto& type : package->types) {
for (auto it = type->entries.begin(); it != type->entries.end(); ) {
ResourceName resource = ResourceName({}, type->type, (*it)->name);
- if (blacklist_.find(resource) != blacklist_.end()) {
+ if (exclude_list_.find(resource) != exclude_list_.end()) {
it = type->entries.erase(it);
} else {
++it;
diff --git a/tools/aapt2/optimize/ResourceFilter.h b/tools/aapt2/optimize/ResourceFilter.h
index d4baf654b0ff..a2645333e497 100644
--- a/tools/aapt2/optimize/ResourceFilter.h
+++ b/tools/aapt2/optimize/ResourceFilter.h
@@ -25,16 +25,16 @@
namespace aapt {
-// Removes non-whitelisted entries from resource table.
+// Removes exclude-listed entries from resource table.
class ResourceFilter : public IResourceTableConsumer {
public:
- explicit ResourceFilter(const std::unordered_set<ResourceName>& blacklist);
+ explicit ResourceFilter(const std::unordered_set<ResourceName>& exclude_list);
bool Consume(IAaptContext* context, ResourceTable* table) override;
private:
DISALLOW_COPY_AND_ASSIGN(ResourceFilter);
- std::unordered_set<ResourceName> blacklist_;
+ std::unordered_set<ResourceName> exclude_list_;
};
} // namespace aapt
diff --git a/tools/aapt2/optimize/ResourceFilter_test.cpp b/tools/aapt2/optimize/ResourceFilter_test.cpp
index ef57f9c56dab..34d8fd280fa9 100644
--- a/tools/aapt2/optimize/ResourceFilter_test.cpp
+++ b/tools/aapt2/optimize/ResourceFilter_test.cpp
@@ -31,22 +31,22 @@ TEST(ResourceFilterTest, SomeValuesAreFilteredOut) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .AddString("android:string/notblacklisted", ResourceId{}, default_config, "value")
- .AddString("android:string/blacklisted", ResourceId{}, default_config, "value")
- .AddString("android:string/notblacklisted2", ResourceId{}, default_config, "value")
- .AddString("android:string/blacklisted2", ResourceId{}, default_config, "value")
+ .AddString("android:string/notexclude_listed", ResourceId{}, default_config, "value")
+ .AddString("android:string/exclude_listed", ResourceId{}, default_config, "value")
+ .AddString("android:string/notexclude_listed2", ResourceId{}, default_config, "value")
+ .AddString("android:string/exclude_listed2", ResourceId{}, default_config, "value")
.Build();
- std::unordered_set<ResourceName> blacklist = {
- ResourceName({}, ResourceType::kString, "blacklisted"),
- ResourceName({}, ResourceType::kString, "blacklisted2"),
+ std::unordered_set<ResourceName> exclude_list = {
+ ResourceName({}, ResourceType::kString, "exclude_listed"),
+ ResourceName({}, ResourceType::kString, "exclude_listed2"),
};
- ASSERT_TRUE(ResourceFilter(blacklist).Consume(context.get(), table.get()));
- EXPECT_THAT(table, HasValue("android:string/notblacklisted", default_config));
- EXPECT_THAT(table, HasValue("android:string/notblacklisted2", default_config));
- EXPECT_THAT(table, Not(HasValue("android:string/blacklisted", default_config)));
- EXPECT_THAT(table, Not(HasValue("android:string/blacklisted2", default_config)));
+ ASSERT_TRUE(ResourceFilter(exclude_list).Consume(context.get(), table.get()));
+ EXPECT_THAT(table, HasValue("android:string/notexclude_listed", default_config));
+ EXPECT_THAT(table, HasValue("android:string/notexclude_listed2", default_config));
+ EXPECT_THAT(table, Not(HasValue("android:string/exclude_listed", default_config)));
+ EXPECT_THAT(table, Not(HasValue("android:string/exclude_listed2", default_config)));
}
TEST(ResourceFilterTest, TypeIsCheckedBeforeFiltering) {
@@ -55,21 +55,21 @@ TEST(ResourceFilterTest, TypeIsCheckedBeforeFiltering) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .AddString("android:string/notblacklisted", ResourceId{}, default_config, "value")
- .AddString("android:string/blacklisted", ResourceId{}, default_config, "value")
- .AddString("android:drawable/notblacklisted", ResourceId{}, default_config, "value")
- .AddString("android:drawable/blacklisted", ResourceId{}, default_config, "value")
+ .AddString("android:string/notexclude_listed", ResourceId{}, default_config, "value")
+ .AddString("android:string/exclude_listed", ResourceId{}, default_config, "value")
+ .AddString("android:drawable/notexclude_listed", ResourceId{}, default_config, "value")
+ .AddString("android:drawable/exclude_listed", ResourceId{}, default_config, "value")
.Build();
- std::unordered_set<ResourceName> blacklist = {
- ResourceName({}, ResourceType::kString, "blacklisted"),
+ std::unordered_set<ResourceName> exclude_list = {
+ ResourceName({}, ResourceType::kString, "exclude_listed"),
};
- ASSERT_TRUE(ResourceFilter(blacklist).Consume(context.get(), table.get()));
- EXPECT_THAT(table, HasValue("android:string/notblacklisted", default_config));
- EXPECT_THAT(table, HasValue("android:drawable/blacklisted", default_config));
- EXPECT_THAT(table, HasValue("android:drawable/notblacklisted", default_config));
- EXPECT_THAT(table, Not(HasValue("android:string/blacklisted", default_config)));
+ ASSERT_TRUE(ResourceFilter(exclude_list).Consume(context.get(), table.get()));
+ EXPECT_THAT(table, HasValue("android:string/notexclude_listed", default_config));
+ EXPECT_THAT(table, HasValue("android:drawable/exclude_listed", default_config));
+ EXPECT_THAT(table, HasValue("android:drawable/notexclude_listed", default_config));
+ EXPECT_THAT(table, Not(HasValue("android:string/exclude_listed", default_config)));
}
} // namespace aapt
diff --git a/tools/aapt2/test/Common.cpp b/tools/aapt2/test/Common.cpp
index b54c155ddc2f..23c22185a53f 100644
--- a/tools/aapt2/test/Common.cpp
+++ b/tools/aapt2/test/Common.cpp
@@ -21,7 +21,7 @@ using android::ConfigDescription;
namespace aapt {
namespace test {
-struct DummyDiagnosticsImpl : public IDiagnostics {
+struct TestDiagnosticsImpl : public IDiagnostics {
void Log(Level level, DiagMessageActual& actual_msg) override {
switch (level) {
case Level::Note:
@@ -39,7 +39,7 @@ struct DummyDiagnosticsImpl : public IDiagnostics {
};
IDiagnostics* GetDiagnostics() {
- static DummyDiagnosticsImpl diag;
+ static TestDiagnosticsImpl diag;
return &diag;
}
diff --git a/tools/aapt2/trace/TraceBuffer.h b/tools/aapt2/trace/TraceBuffer.h
index 8618e0eeb731..ba751dd72f41 100644
--- a/tools/aapt2/trace/TraceBuffer.h
+++ b/tools/aapt2/trace/TraceBuffer.h
@@ -40,7 +40,7 @@ public:
void BeginTrace(const std::string& tag);
void EndTrace();
-// A master trace is required to flush events to disk. Events are formatted in systrace
+// A main trace is required to flush events to disk. Events are formatted in systrace
// json format.
class FlushTrace {
public:
diff --git a/tools/aapt2/util/Maybe_test.cpp b/tools/aapt2/util/Maybe_test.cpp
index 2057ddcc9e45..4c921f13a3ca 100644
--- a/tools/aapt2/util/Maybe_test.cpp
+++ b/tools/aapt2/util/Maybe_test.cpp
@@ -22,32 +22,32 @@
namespace aapt {
-struct Dummy {
- Dummy() {
+struct Fake {
+ Fake() {
data = new int;
*data = 1;
- std::cerr << "Construct Dummy{0x" << (void*)this << "} with data=0x"
+ std::cerr << "Construct Fake{0x" << (void*)this << "} with data=0x"
<< (void*)data << std::endl;
}
- Dummy(const Dummy& rhs) {
+ Fake(const Fake& rhs) {
data = nullptr;
if (rhs.data) {
data = new int;
*data = *rhs.data;
}
- std::cerr << "CopyConstruct Dummy{0x" << (void*)this << "} from Dummy{0x"
+ std::cerr << "CopyConstruct Fake{0x" << (void*)this << "} from Fake{0x"
<< (const void*)&rhs << "}" << std::endl;
}
- Dummy(Dummy&& rhs) {
+ Fake(Fake&& rhs) {
data = rhs.data;
rhs.data = nullptr;
- std::cerr << "MoveConstruct Dummy{0x" << (void*)this << "} from Dummy{0x"
+ std::cerr << "MoveConstruct Fake{0x" << (void*)this << "} from Fake{0x"
<< (const void*)&rhs << "}" << std::endl;
}
- Dummy& operator=(const Dummy& rhs) {
+ Fake& operator=(const Fake& rhs) {
delete data;
data = nullptr;
@@ -55,22 +55,22 @@ struct Dummy {
data = new int;
*data = *rhs.data;
}
- std::cerr << "CopyAssign Dummy{0x" << (void*)this << "} from Dummy{0x"
+ std::cerr << "CopyAssign Fake{0x" << (void*)this << "} from Fake{0x"
<< (const void*)&rhs << "}" << std::endl;
return *this;
}
- Dummy& operator=(Dummy&& rhs) {
+ Fake& operator=(Fake&& rhs) {
delete data;
data = rhs.data;
rhs.data = nullptr;
- std::cerr << "MoveAssign Dummy{0x" << (void*)this << "} from Dummy{0x"
+ std::cerr << "MoveAssign Fake{0x" << (void*)this << "} from Fake{0x"
<< (const void*)&rhs << "}" << std::endl;
return *this;
}
- ~Dummy() {
- std::cerr << "Destruct Dummy{0x" << (void*)this << "} with data=0x"
+ ~Fake() {
+ std::cerr << "Destruct Fake{0x" << (void*)this << "} with data=0x"
<< (void*)data << std::endl;
delete data;
}
@@ -100,15 +100,15 @@ TEST(MaybeTest, MakeSomething) {
}
TEST(MaybeTest, Lifecycle) {
- Maybe<Dummy> val = make_nothing<Dummy>();
+ Maybe<Fake> val = make_nothing<Fake>();
- Maybe<Dummy> val2 = make_value(Dummy());
+ Maybe<Fake> val2 = make_value(Fake());
}
TEST(MaybeTest, MoveAssign) {
- Maybe<Dummy> val;
+ Maybe<Fake> val;
{
- Maybe<Dummy> val2 = Dummy();
+ Maybe<Fake> val2 = Fake();
val = std::move(val2);
}
}
diff --git a/tools/aapt2/xml/XmlActionExecutor.cpp b/tools/aapt2/xml/XmlActionExecutor.cpp
index cb844f085ecc..fab17c949dd8 100644
--- a/tools/aapt2/xml/XmlActionExecutor.cpp
+++ b/tools/aapt2/xml/XmlActionExecutor.cpp
@@ -74,11 +74,11 @@ bool XmlNodeAction::Execute(XmlActionExecutorPolicy policy, std::vector<StringPi
for (const StringPiece& element : *bread_crumb) {
error_msg << "<" << element << ">";
}
- if (policy == XmlActionExecutorPolicy::kWhitelistWarning) {
+ if (policy == XmlActionExecutorPolicy::kAllowListWarning) {
// Treat the error only as a warning.
diag->Warn(error_msg);
} else {
- // Policy is XmlActionExecutorPolicy::kWhitelist, we should fail.
+ // Policy is XmlActionExecutorPolicy::kAllowList, we should fail.
diag->Error(error_msg);
error = true;
}
@@ -94,7 +94,7 @@ bool XmlActionExecutor::Execute(XmlActionExecutorPolicy policy, IDiagnostics* di
Element* el = doc->root.get();
if (!el) {
- if (policy == XmlActionExecutorPolicy::kWhitelist) {
+ if (policy == XmlActionExecutorPolicy::kAllowList) {
source_diag.Error(DiagMessage() << "no root XML tag found");
return false;
}
@@ -109,7 +109,7 @@ bool XmlActionExecutor::Execute(XmlActionExecutorPolicy policy, IDiagnostics* di
return iter->second.Execute(policy, &bread_crumb, &source_diag, el);
}
- if (policy == XmlActionExecutorPolicy::kWhitelist) {
+ if (policy == XmlActionExecutorPolicy::kAllowList) {
DiagMessage error_msg(el->line_number);
error_msg << "unexpected root element ";
PrintElementToDiagMessage(el, &error_msg);
diff --git a/tools/aapt2/xml/XmlActionExecutor.h b/tools/aapt2/xml/XmlActionExecutor.h
index f689b2a3eaa8..a0ad1dadeddf 100644
--- a/tools/aapt2/xml/XmlActionExecutor.h
+++ b/tools/aapt2/xml/XmlActionExecutor.h
@@ -37,12 +37,12 @@ enum class XmlActionExecutorPolicy {
// The actions defined must match and run. If an element is found that does not match an action,
// an error occurs.
// Note: namespaced elements are always ignored.
- kWhitelist,
+ kAllowList,
// The actions defined should match and run. if an element is found that does not match an
// action, a warning is printed.
// Note: namespaced elements are always ignored.
- kWhitelistWarning,
+ kAllowListWarning,
};
// Contains the actions to perform at this XML node. This is a recursive data structure that
diff --git a/tools/aapt2/xml/XmlActionExecutor_test.cpp b/tools/aapt2/xml/XmlActionExecutor_test.cpp
index d39854e5fe4e..d47b49590f5c 100644
--- a/tools/aapt2/xml/XmlActionExecutor_test.cpp
+++ b/tools/aapt2/xml/XmlActionExecutor_test.cpp
@@ -60,10 +60,10 @@ TEST(XmlActionExecutorTest, FailsWhenUndefinedHierarchyExists) {
StdErrDiagnostics diag;
doc = test::BuildXmlDom("<manifest><application /><activity /></manifest>");
- ASSERT_FALSE(executor.Execute(XmlActionExecutorPolicy::kWhitelist, &diag, doc.get()));
+ ASSERT_FALSE(executor.Execute(XmlActionExecutorPolicy::kAllowList, &diag, doc.get()));
doc = test::BuildXmlDom("<manifest><application><activity /></application></manifest>");
- ASSERT_FALSE(executor.Execute(XmlActionExecutorPolicy::kWhitelist, &diag, doc.get()));
+ ASSERT_FALSE(executor.Execute(XmlActionExecutorPolicy::kAllowList, &diag, doc.get()));
}
} // namespace xml
diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh
index f25fcdcb7479..99aaa3c4d6e5 100755
--- a/tools/aosp/aosp_sha.sh
+++ b/tools/aosp/aosp_sha.sh
@@ -11,7 +11,7 @@ else
if (( count == 0 )); then
echo
fi
- echo -e "\033[0;31mThe source of truth for '$file' is in AOSP.\033[0m"
+ echo -e "\033[0;31;47mThe source of truth for '$file' is in AOSP.\033[0m"
(( count++ ))
done < <(git show --name-only --pretty=format: $1 | grep -- "$2")
if (( count != 0 )); then
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index de6b4785ec37..8a282e5f0821 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -13,9 +13,7 @@
# 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.
-"""
-Generate API lists for non-SDK API enforcement.
-"""
+"""Generate API lists for non-SDK API enforcement."""
import argparse
from collections import defaultdict
import functools
@@ -24,27 +22,47 @@ import re
import sys
# Names of flags recognized by the `hiddenapi` tool.
-FLAG_WHITELIST = "whitelist"
-FLAG_GREYLIST = "greylist"
-FLAG_BLACKLIST = "blacklist"
-FLAG_GREYLIST_MAX_O = "greylist-max-o"
-FLAG_GREYLIST_MAX_P = "greylist-max-p"
-FLAG_GREYLIST_MAX_Q = "greylist-max-q"
-FLAG_GREYLIST_MAX_R = "greylist-max-r"
-FLAG_CORE_PLATFORM_API = "core-platform-api"
-FLAG_PUBLIC_API = "public-api"
-FLAG_SYSTEM_API = "system-api"
-FLAG_TEST_API = "test-api"
+FLAG_SDK = 'sdk'
+FLAG_UNSUPPORTED = 'unsupported'
+FLAG_BLOCKED = 'blocked'
+FLAG_MAX_TARGET_O = 'max-target-o'
+FLAG_MAX_TARGET_P = 'max-target-p'
+FLAG_MAX_TARGET_Q = 'max-target-q'
+FLAG_MAX_TARGET_R = 'max-target-r'
+FLAG_CORE_PLATFORM_API = 'core-platform-api'
+FLAG_PUBLIC_API = 'public-api'
+FLAG_SYSTEM_API = 'system-api'
+FLAG_TEST_API = 'test-api'
+
+OLD_FLAG_SDK = "whitelist"
+OLD_FLAG_UNSUPPORTED = "greylist"
+OLD_FLAG_BLOCKED = "blacklist"
+OLD_FLAG_MAX_TARGET_O = "greylist-max-o"
+OLD_FLAG_MAX_TARGET_P = "greylist-max-p"
+OLD_FLAG_MAX_TARGET_Q = "greylist-max-q"
+OLD_FLAG_MAX_TARGET_R = "greylist-max-r"
+
+OLD_FLAGS_TO_NEW = {
+ OLD_FLAG_SDK: FLAG_SDK,
+ OLD_FLAG_UNSUPPORTED: FLAG_UNSUPPORTED,
+ OLD_FLAG_BLOCKED: FLAG_BLOCKED,
+ OLD_FLAG_MAX_TARGET_O: FLAG_MAX_TARGET_O,
+ OLD_FLAG_MAX_TARGET_P: FLAG_MAX_TARGET_P,
+ OLD_FLAG_MAX_TARGET_Q: FLAG_MAX_TARGET_Q,
+ OLD_FLAG_MAX_TARGET_R: FLAG_MAX_TARGET_R,
+}
+
+NEW_FLAGS_TO_OLD = dict(zip(OLD_FLAGS_TO_NEW.values(), OLD_FLAGS_TO_NEW.keys()))
# List of all known flags.
FLAGS_API_LIST = [
- FLAG_WHITELIST,
- FLAG_GREYLIST,
- FLAG_BLACKLIST,
- FLAG_GREYLIST_MAX_O,
- FLAG_GREYLIST_MAX_P,
- FLAG_GREYLIST_MAX_Q,
- FLAG_GREYLIST_MAX_R,
+ FLAG_SDK,
+ FLAG_UNSUPPORTED,
+ FLAG_BLOCKED,
+ FLAG_MAX_TARGET_O,
+ FLAG_MAX_TARGET_P,
+ FLAG_MAX_TARGET_Q,
+ FLAG_MAX_TARGET_R,
]
ALL_FLAGS = FLAGS_API_LIST + [
FLAG_CORE_PLATFORM_API,
@@ -58,7 +76,7 @@ ALL_FLAGS_SET = set(ALL_FLAGS)
# Suffix used in command line args to express that only known and
# otherwise unassigned entries should be assign the given flag.
-# For example, the P dark greylist is checked in as it was in P,
+# For example, the max-target-P list is checked in as it was in P,
# but signatures have changes since then. The flag instructs this
# script to skip any entries which do not exist any more.
FLAG_IGNORE_CONFLICTS_SUFFIX = "-ignore-conflicts"
@@ -87,6 +105,7 @@ SERIALIZATION_REGEX = re.compile(r'.*->(' + '|'.join(SERIALIZATION_PATTERNS) + r
HAS_NO_API_LIST_ASSIGNED = lambda api, flags: not FLAGS_API_LIST_SET.intersection(flags)
IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api)
+
def get_args():
"""Parses command line arguments.
@@ -113,6 +132,7 @@ def get_args():
return parser.parse_args()
+
def read_lines(filename):
"""Reads entire file and return it as a list of lines.
@@ -130,8 +150,9 @@ def read_lines(filename):
lines = map(lambda line: line.strip(), lines)
return set(lines)
+
def write_lines(filename, lines):
- """Writes list of lines into a file, overwriting the file it it exists.
+ """Writes list of lines into a file, overwriting the file if it exists.
Args:
filename (string): Path to the file to be writting into.
@@ -141,6 +162,7 @@ def write_lines(filename, lines):
with open(filename, 'w') as f:
f.writelines(lines)
+
def extract_package(signature):
"""Extracts the package from a signature.
@@ -159,6 +181,7 @@ def extract_package(signature):
package_name = full_class_name.rpartition("/")[0]
return package_name.replace('/', '.')
+
class FlagsDict:
def __init__(self):
self._dict_keyset = set()
@@ -182,6 +205,36 @@ class FlagsDict:
"Please visit go/hiddenapi for more information.").format(
source, "\n".join(flags_subset - ALL_FLAGS_SET))
+ def convert_to_new_flag(self, flag):
+ """Converts old flag to a new variant.
+
+ Flags that are considered old are replaced with new versions.
+ Otherwise, it is a no-op.
+
+ Args:
+ flag: a string, representing SDK flag.
+
+ Returns:
+ A string. Result of conversion.
+
+ """
+ return OLD_FLAGS_TO_NEW.get(flag, flag)
+
+ def convert_to_old_flag(self, flag):
+ """Converts a new flag to a old variant.
+
+ No-op if there is no suitable old flag.
+ Only used to support backwards compatibility.
+
+ Args:
+ flag: a string, representing SDK flag.
+
+ Returns:
+ A string. Result of conversion.
+
+ """
+ return NEW_FLAGS_TO_OLD.get(flag, flag)
+
def filter_apis(self, filter_fn):
"""Returns APIs which match a given predicate.
@@ -212,10 +265,16 @@ class FlagsDict:
def generate_csv(self):
"""Constructs CSV entries from a dictionary.
+ Old versions of flags are used to generate the file.
+
Returns:
List of lines comprising a CSV file. See "parse_and_merge_csv" for format description.
"""
- return sorted(map(lambda api: ",".join([api] + sorted(self._dict[api])), self._dict))
+ lines = []
+ for api in self._dict:
+ flags = sorted([self.convert_to_old_flag(flag) for flag in self._dict[api]])
+ lines.append(",".join([api] + flags))
+ return sorted(lines)
def parse_and_merge_csv(self, csv_lines, source = "<unknown>"):
"""Parses CSV entries and merges them into a given dictionary.
@@ -237,17 +296,16 @@ class FlagsDict:
self._dict_keyset.update([ csv[0] for csv in csv_values ])
# Check that all flags are known.
- csv_flags = set(functools.reduce(
- lambda x, y: set(x).union(y),
- [ csv[1:] for csv in csv_values ],
- []))
+ csv_flags = set()
+ for csv in csv_values:
+ csv_flags.update([self.convert_to_new_flag(flag) for flag in csv[1:]])
self._check_flags_set(csv_flags, source)
# Iterate over all CSV lines, find entry in dict and append flags to it.
for csv in csv_values:
- flags = csv[1:]
+ flags = [self.convert_to_new_flag(flag) for flag in csv[1:]]
if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags):
- flags.append(FLAG_WHITELIST)
+ flags.append(FLAG_SDK)
self._dict[csv[0]].update(flags)
def assign_flag(self, flag, apis, source="<unknown>"):
@@ -271,6 +329,7 @@ class FlagsDict:
for api in apis:
self._dict[api].add(flag)
+
def main(argv):
# Parse arguments.
args = vars(get_args())
@@ -287,8 +346,8 @@ def main(argv):
flags.parse_and_merge_csv(read_lines(filename), filename)
# Combine inputs which do not require any particular order.
- # (1) Assign serialization API to whitelist.
- flags.assign_flag(FLAG_WHITELIST, flags.filter_apis(IS_SERIALIZATION))
+ # (1) Assign serialization API to SDK.
+ flags.assign_flag(FLAG_SDK, flags.filter_apis(IS_SERIALIZATION))
# (2) Merge text files with a known flag into the dictionary.
for flag in ALL_FLAGS:
@@ -314,8 +373,8 @@ def main(argv):
valid_entries = flags.filter_apis(should_add_signature_to_list)
flags.assign_flag(flag, valid_entries)
- # Assign all remaining entries to the blacklist.
- flags.assign_flag(FLAG_BLACKLIST, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED))
+ # Mark all remaining entries as blocked.
+ flags.assign_flag(FLAG_BLOCKED, flags.filter_apis(HAS_NO_API_LIST_ASSIGNED))
# Write output.
write_lines(args["output"], flags.generate_csv())
diff --git a/tools/hiddenapi/generate_hiddenapi_lists_test.py b/tools/hiddenapi/generate_hiddenapi_lists_test.py
index 55c3a7d718db..321c400ef898 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists_test.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists_test.py
@@ -23,7 +23,7 @@ class TestHiddenapiListGeneration(unittest.TestCase):
# Initialize flags so that A and B are put on the whitelist and
# C, D, E are left unassigned. Try filtering for the unassigned ones.
flags = FlagsDict()
- flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B,' + FLAG_WHITELIST,
+ flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B,' + FLAG_SDK,
'C', 'D', 'E'])
filter_set = flags.filter_apis(lambda api, flags: not flags)
self.assertTrue(isinstance(filter_set, set))
@@ -32,10 +32,10 @@ class TestHiddenapiListGeneration(unittest.TestCase):
def test_get_valid_subset_of_unassigned_keys(self):
# Create flags where only A is unassigned.
flags = FlagsDict()
- flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B', 'C'])
- flags.assign_flag(FLAG_GREYLIST, set(['C']))
+ flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B', 'C'])
+ flags.assign_flag(FLAG_UNSUPPORTED, set(['C']))
self.assertEqual(flags.generate_csv(),
- [ 'A,' + FLAG_WHITELIST, 'B', 'C,' + FLAG_GREYLIST ])
+ [ 'A,' + OLD_FLAG_SDK, 'B', 'C,' + OLD_FLAG_UNSUPPORTED ])
# Check three things:
# (1) B is selected as valid unassigned
@@ -50,20 +50,21 @@ class TestHiddenapiListGeneration(unittest.TestCase):
# Test empty CSV entry.
self.assertEqual(flags.generate_csv(), [])
- # Test new additions.
+ # Test new additions. CSV generator produces values with old flags
+ # to be backwards compatible.
flags.parse_and_merge_csv([
- 'A,' + FLAG_GREYLIST,
- 'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O,
- 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST,
- 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API,
- 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API,
+ 'A,' + FLAG_UNSUPPORTED,
+ 'B,' + FLAG_BLOCKED + ',' + FLAG_MAX_TARGET_O,
+ 'C,' + FLAG_SDK + ',' + FLAG_SYSTEM_API,
+ 'D,' + FLAG_UNSUPPORTED + ',' + FLAG_TEST_API,
+ 'E,' + FLAG_BLOCKED + ',' + FLAG_TEST_API,
])
self.assertEqual(flags.generate_csv(), [
- 'A,' + FLAG_GREYLIST,
- 'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O,
- 'C,' + FLAG_SYSTEM_API + ',' + FLAG_WHITELIST,
- 'D,' + FLAG_GREYLIST+ ',' + FLAG_TEST_API,
- 'E,' + FLAG_BLACKLIST+ ',' + FLAG_TEST_API,
+ 'A,' + OLD_FLAG_UNSUPPORTED,
+ 'B,' + OLD_FLAG_BLOCKED + "," + OLD_FLAG_MAX_TARGET_O,
+ 'C,' + FLAG_SYSTEM_API + ',' + OLD_FLAG_SDK,
+ 'D,' + OLD_FLAG_UNSUPPORTED + ',' + FLAG_TEST_API,
+ 'E,' + OLD_FLAG_BLOCKED + ',' + FLAG_TEST_API,
])
# Test unknown flag.
@@ -72,16 +73,16 @@ class TestHiddenapiListGeneration(unittest.TestCase):
def test_assign_flag(self):
flags = FlagsDict()
- flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST, 'B'])
+ flags.parse_and_merge_csv(['A,' + FLAG_SDK, 'B'])
# Test new additions.
- flags.assign_flag(FLAG_GREYLIST, set([ 'A', 'B' ]))
+ flags.assign_flag(FLAG_UNSUPPORTED, set([ 'A', 'B' ]))
self.assertEqual(flags.generate_csv(),
- [ 'A,' + FLAG_GREYLIST + "," + FLAG_WHITELIST, 'B,' + FLAG_GREYLIST ])
+ [ 'A,' + OLD_FLAG_UNSUPPORTED + "," + OLD_FLAG_SDK, 'B,' + OLD_FLAG_UNSUPPORTED ])
# Test invalid API signature.
with self.assertRaises(AssertionError):
- flags.assign_flag(FLAG_WHITELIST, set([ 'C' ]))
+ flags.assign_flag(FLAG_SDK, set([ 'C' ]))
# Test invalid flag.
with self.assertRaises(AssertionError):
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index e3b6db08c503..43387fc054b5 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -121,10 +121,26 @@ cc_library {
],
target: {
android: {
- shared_libs: ["libstatssocket"],
+ shared_libs: [
+ "libstatssocket",
+ "libstatspull",
+ ],
+ export_shared_lib_headers: [
+ "libstatssocket",
+ "libstatspull",
+ ],
},
host: {
- static_libs: ["libstatssocket"],
+ static_libs: [
+ "libstatssocket",
+ "libstatspull",
+ "statsd-aidl-ndk_platform",
+ ],
+ shared_libs: ["libbinder_ndk"],
+ export_static_lib_headers: [
+ "libstatssocket",
+ "libstatspull",
+ ],
},
},
}
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index 4c741c49cfdb..fe6ca558a0ee 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -72,7 +72,7 @@ static void print_error(const FieldDescriptor* field, const char* format, ...) {
SourceLocation loc;
if (field->GetSourceLocation(&loc)) {
- // TODO: this will work if we can figure out how to pass
+ // TODO(b/162454173): this will work if we can figure out how to pass
// --include_source_info to protoc
fprintf(stderr, "%s:%d: ", file->name().c_str(), loc.start_line);
} else {
@@ -111,7 +111,6 @@ static java_type_t java_type(const FieldDescriptor* field) {
case FieldDescriptor::TYPE_GROUP:
return JAVA_TYPE_UNKNOWN;
case FieldDescriptor::TYPE_MESSAGE:
- // TODO: not the final package name
if (field->message_type()->full_name() == "android.os.statsd.AttributionNode") {
return JAVA_TYPE_ATTRIBUTION_CHAIN;
} else if (field->message_type()->full_name() == "android.os.statsd.KeyValuePair") {
@@ -147,7 +146,7 @@ static java_type_t java_type(const FieldDescriptor* field) {
void collate_enums(const EnumDescriptor& enumDescriptor, AtomField* atomField) {
for (int i = 0; i < enumDescriptor.value_count(); i++) {
atomField->enumValues[enumDescriptor.value(i)->number()] =
- enumDescriptor.value(i)->name().c_str();
+ enumDescriptor.value(i)->name();
}
}
@@ -528,7 +527,7 @@ int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms*
vector<java_type_t> signature;
errorCount += collate_atom(atom, atomDecl.get(), &signature);
- if (atomDecl->primaryFields.size() != 0 && atomDecl->exclusiveField == 0) {
+ if (!atomDecl->primaryFields.empty() && atomDecl->exclusiveField == 0) {
print_error(atomField, "Cannot have a primary field without an exclusive field: %s\n",
atomField->name().c_str());
errorCount++;
@@ -541,8 +540,7 @@ int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms*
atomField->name().c_str());
errorCount++;
continue;
- }
- else if ((oneofAtom->name() != ONEOF_PUSHED_ATOM_NAME) &&
+ } else if ((oneofAtom->name() != ONEOF_PUSHED_ATOM_NAME) &&
(oneofAtom->name() != ONEOF_PULLED_ATOM_NAME)) {
print_error(atomField, "Atom is neither a pushed nor pulled atom: %s\n",
atomField->name().c_str());
@@ -578,7 +576,7 @@ int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms*
printf(" ");
for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end();
jt++) {
- printf(" %d", (int)*jt);
+ printf(" %d", static_cast<int>(*jt));
}
printf("\n");
}
@@ -589,7 +587,7 @@ int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms*
printf(" ");
for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end();
jt++) {
- printf(" %d", (int)*jt);
+ printf(" %d", static_cast<int>(*jt));
}
printf("\n");
}
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index e637ed945a08..5d196c4b8290 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -47,8 +47,8 @@ const int FIRST_UID_IN_CHAIN_ID = 0;
*
* `OneofDescriptor::name()` returns the name of the oneof.
*/
-const string ONEOF_PUSHED_ATOM_NAME = "pushed";
-const string ONEOF_PULLED_ATOM_NAME = "pulled";
+const char ONEOF_PUSHED_ATOM_NAME[] = "pushed";
+const char ONEOF_PULLED_ATOM_NAME[] = "pulled";
enum AnnotationId : uint8_t {
ANNOTATION_ID_IS_UID = 1,
@@ -63,7 +63,7 @@ enum AnnotationId : uint8_t {
const int ATOM_ID_FIELD_NUMBER = -1;
-const string DEFAULT_MODULE_NAME = "DEFAULT";
+const char DEFAULT_MODULE_NAME[] = "DEFAULT";
/**
* The types for atom parameters.
@@ -95,9 +95,9 @@ union AnnotationValue {
int intValue;
bool boolValue;
- AnnotationValue(const int value) : intValue(value) {
+ explicit AnnotationValue(const int value) : intValue(value) {
}
- AnnotationValue(const bool value) : boolValue(value) {
+ explicit AnnotationValue(const bool value) : boolValue(value) {
}
};
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index ffbe9f800736..6fcf267cf39c 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -42,6 +42,7 @@ static int write_java_q_logger_class(FILE* out, const SignatureInfoMap& signatur
static void write_java_annotation_constants(FILE* out) {
fprintf(out, " // Annotation constants.\n");
+ const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) {
fprintf(out, " public static final byte %s = %hhu;\n", name.c_str(), id);
}
@@ -56,6 +57,7 @@ static void write_annotations(FILE* out, int argIndex,
return;
}
const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
+ const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
const string atomConstant = make_constant_name(atomDecl->name);
fprintf(out, " if (%s == code) {\n", atomConstant.c_str());
@@ -102,7 +104,7 @@ static void write_method_signature(FILE* out, const vector<java_type_t>& signatu
for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
arg++) {
if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
+ for (const auto& chainField : attributionDecl.fields) {
fprintf(out, ", %s[] %s", java_type_name(chainField.javaType),
chainField.name.c_str());
}
@@ -243,13 +245,15 @@ static int write_method_body(FILE* out, const vector<java_type_t>& signature,
return 0;
}
-static int write_java_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
+static int write_java_pushed_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
const AtomDecl& attributionDecl, const bool supportQ) {
for (auto signatureInfoMapIt = signatureInfoMap.begin();
signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
// Print method signature.
fprintf(out, " public static void write(int code");
- write_method_signature(out, signatureInfoMapIt->first, attributionDecl);
+ const vector<java_type_t>& signature = signatureInfoMapIt->first;
+ const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
+ write_method_signature(out, signature, attributionDecl);
fprintf(out, ") {\n");
// Print method body.
@@ -259,7 +263,7 @@ static int write_java_methods(FILE* out, const SignatureInfoMap& signatureInfoMa
indent = " ";
}
- int ret = write_method_body(out, signatureInfoMapIt->first, signatureInfoMapIt->second,
+ int ret = write_method_body(out, signature, fieldNumberToAtomDeclSet,
attributionDecl, indent);
if (ret != 0) {
return ret;
@@ -274,8 +278,8 @@ static int write_java_methods(FILE* out, const SignatureInfoMap& signatureInfoMa
fprintf(out, " } else {\n");
fprintf(out, " QLogger.write(code");
int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signatureInfoMapIt->first.begin();
- arg != signatureInfoMapIt->first.end(); arg++) {
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
const char* uidName = attributionDecl.fields.front().name.c_str();
const char* tagName = attributionDecl.fields.back().name.c_str();
@@ -299,18 +303,20 @@ static int write_java_methods(FILE* out, const SignatureInfoMap& signatureInfoMa
return 0;
}
-static int write_java_build_stats_event_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
+static int write_java_pulled_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
const AtomDecl& attributionDecl) {
for (auto signatureInfoMapIt = signatureInfoMap.begin();
signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
// Print method signature.
fprintf(out, " public static StatsEvent buildStatsEvent(int code");
- write_method_signature(out, signatureInfoMapIt->first, attributionDecl);
+ const vector<java_type_t>& signature = signatureInfoMapIt->first;
+ const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
+ write_method_signature(out, signature, attributionDecl);
fprintf(out, ") {\n");
// Print method body.
string indent("");
- int ret = write_method_body(out, signatureInfoMapIt->first, signatureInfoMapIt->second,
+ int ret = write_method_body(out, signature, fieldNumberToAtomDeclSet,
attributionDecl, indent);
if (ret != 0) {
return ret;
@@ -357,9 +363,9 @@ int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl& attribut
// Print write methods.
fprintf(out, " // Write methods\n");
- errors += write_java_methods(out, atoms.signatureInfoMap, attributionDecl, supportQ);
+ errors += write_java_pushed_methods(out, atoms.signatureInfoMap, attributionDecl, supportQ);
errors += write_java_non_chained_methods(out, atoms.nonChainedSignatureInfoMap);
- errors += write_java_build_stats_event_methods(out, atoms.pulledAtomsSignatureInfoMap,
+ errors += write_java_pulled_methods(out, atoms.pulledAtomsSignatureInfoMap,
attributionDecl);
if (supportWorkSource) {
errors += write_java_work_source_methods(out, atoms.signatureInfoMap);
diff --git a/tools/stats_log_api_gen/java_writer.h b/tools/stats_log_api_gen/java_writer.h
index 8b3b50588efc..afd992be6c5e 100644
--- a/tools/stats_log_api_gen/java_writer.h
+++ b/tools/stats_log_api_gen/java_writer.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H
+#define ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H
#include <stdio.h>
#include <string.h>
@@ -28,11 +29,11 @@
namespace android {
namespace stats_log_api_gen {
-using namespace std;
-
int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
const string& javaClass, const string& javaPackage, const bool supportQ,
const bool supportWorkSource);
} // namespace stats_log_api_gen
} // namespace android
+
+#endif // ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H
diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp
index d21e2708b724..be7cb4aeb3f8 100644
--- a/tools/stats_log_api_gen/java_writer_q.cpp
+++ b/tools/stats_log_api_gen/java_writer_q.cpp
@@ -65,7 +65,7 @@ int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfo
for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
arg++) {
if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
+ for (const auto& chainField : attributionDecl.fields) {
fprintf(out, ", %s[] %s", java_type_name(chainField.javaType),
chainField.name.c_str());
}
@@ -407,7 +407,7 @@ void write_java_helpers_for_q_schema_methods(FILE* out, const AtomDecl& attribut
if (requiredHelpers & JAVA_MODULE_REQUIRES_ATTRIBUTION) {
fprintf(out, "%sprivate static void writeAttributionChain(byte[] buff, int pos",
indent.c_str());
- for (auto chainField : attributionDecl.fields) {
+ for (const auto& chainField : attributionDecl.fields) {
fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str());
}
fprintf(out, ") {\n");
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
index c511a8436416..622ef3e37bad 100644
--- a/tools/stats_log_api_gen/java_writer_q.h
+++ b/tools/stats_log_api_gen/java_writer_q.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H
+#define ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H
#include <stdio.h>
#include <string.h>
@@ -28,8 +29,6 @@
namespace android {
namespace stats_log_api_gen {
-using namespace std;
-
void write_java_q_logging_constants(FILE* out, const string& indent);
int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfoMap,
@@ -44,3 +43,5 @@ int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
} // namespace stats_log_api_gen
} // namespace android
+
+#endif // ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index b888ce904b31..28302493a8e1 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -15,9 +15,6 @@
#include "native_writer.h"
#include "utils.h"
-using namespace google::protobuf;
-using namespace std;
-
namespace android {
namespace stats_log_api_gen {
@@ -145,7 +142,7 @@ static int run(int argc, char const* const* argv) {
index++;
}
- if (cppFilename.size() == 0 && headerFilename.size() == 0 && javaFilename.size() == 0) {
+ if (cppFilename.empty() && headerFilename.empty() && javaFilename.empty()) {
print_usage();
return 1;
}
@@ -175,9 +172,9 @@ static int run(int argc, char const* const* argv) {
&attributionSignature);
// Write the .cpp file
- if (cppFilename.size() != 0) {
+ if (!cppFilename.empty()) {
FILE* out = fopen(cppFilename.c_str(), "w");
- if (out == NULL) {
+ if (out == nullptr) {
fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str());
return 1;
}
@@ -198,9 +195,9 @@ static int run(int argc, char const* const* argv) {
}
// Write the .h file
- if (headerFilename.size() != 0) {
+ if (!headerFilename.empty()) {
FILE* out = fopen(headerFilename.c_str(), "w");
- if (out == NULL) {
+ if (out == nullptr) {
fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str());
return 1;
}
@@ -214,24 +211,24 @@ static int run(int argc, char const* const* argv) {
}
// Write the .java file
- if (javaFilename.size() != 0) {
- if (javaClass.size() == 0) {
+ if (!javaFilename.empty()) {
+ if (javaClass.empty()) {
fprintf(stderr, "Must supply --javaClass if supplying a Java filename");
return 1;
}
- if (javaPackage.size() == 0) {
+ if (javaPackage.empty()) {
fprintf(stderr, "Must supply --javaPackage if supplying a Java filename");
return 1;
}
- if (moduleName.size() == 0) {
+ if (moduleName.empty()) {
fprintf(stderr, "Must supply --module if supplying a Java filename");
return 1;
}
FILE* out = fopen(javaFilename.c_str(), "w");
- if (out == NULL) {
+ if (out == nullptr) {
fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str());
return 1;
}
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
index 0c6c0099e459..b4fb8dd8321b 100644
--- a/tools/stats_log_api_gen/native_writer.cpp
+++ b/tools/stats_log_api_gen/native_writer.cpp
@@ -24,6 +24,7 @@ namespace stats_log_api_gen {
static void write_native_annotation_constants(FILE* out) {
fprintf(out, "// Annotation constants.\n");
+ const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) {
fprintf(out, "const uint8_t %s = %hhu;\n", name.c_str(), id);
}
@@ -39,6 +40,7 @@ static void write_annotations(FILE* out, int argIndex,
return;
}
const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
+ const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
const string atomConstant = make_constant_name(atomDecl->name);
fprintf(out, " if (%s == code) {\n", atomConstant.c_str());
@@ -60,8 +62,6 @@ static void write_annotations(FILE* out, int argIndex,
}
break;
case ANNOTATION_TYPE_BOOL:
- // TODO(b/151786433): Write annotation constant name instead of
- // annotation id literal.
fprintf(out, " %saddBoolAnnotation(%s%s, %s);\n", methodPrefix.c_str(),
methodSuffix.c_str(), annotationConstant.c_str(),
annotation->value.boolValue ? "true" : "false");
@@ -82,21 +82,78 @@ static void write_annotations(FILE* out, int argIndex,
}
}
-static int write_native_stats_write_methods(FILE* out, const Atoms& atoms,
+static int write_native_method_body(FILE* out, vector<java_type_t>& signature,
+ const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
+ const AtomDecl& attributionDecl) {
+ int argIndex = 1;
+ fprintf(out, " AStatsEvent_setAtomId(event, code);\n");
+ write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "AStatsEvent_",
+ "event, ");
+ for (vector<java_type_t>::const_iterator arg = signature.begin();
+ arg != signature.end(); arg++) {
+ switch (*arg) {
+ case JAVA_TYPE_ATTRIBUTION_CHAIN: {
+ const char* uidName = attributionDecl.fields.front().name.c_str();
+ const char* tagName = attributionDecl.fields.back().name.c_str();
+ fprintf(out,
+ " AStatsEvent_writeAttributionChain(event, "
+ "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
+ "static_cast<uint8_t>(%s_length));\n",
+ uidName, tagName, uidName);
+ break;
+ }
+ case JAVA_TYPE_BYTE_ARRAY:
+ fprintf(out,
+ " AStatsEvent_writeByteArray(event, "
+ "reinterpret_cast<const uint8_t*>(arg%d.arg), "
+ "arg%d.arg_length);\n",
+ argIndex, argIndex);
+ break;
+ case JAVA_TYPE_BOOLEAN:
+ fprintf(out, " AStatsEvent_writeBool(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_INT: // Fall through.
+ case JAVA_TYPE_ENUM:
+ fprintf(out, " AStatsEvent_writeInt32(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_FLOAT:
+ fprintf(out, " AStatsEvent_writeFloat(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_LONG:
+ fprintf(out, " AStatsEvent_writeInt64(event, arg%d);\n", argIndex);
+ break;
+ case JAVA_TYPE_STRING:
+ fprintf(out, " AStatsEvent_writeString(event, arg%d);\n", argIndex);
+ break;
+ default:
+ // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS
+ fprintf(stderr, "Encountered unsupported type.");
+ return 1;
+ }
+ write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "AStatsEvent_",
+ "event, ");
+ argIndex++;
+ }
+ return 0;
+}
+
+static int write_native_stats_write_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
const AtomDecl& attributionDecl, const bool supportQ) {
fprintf(out, "\n");
- for (auto signatureInfoMapIt = atoms.signatureInfoMap.begin();
- signatureInfoMapIt != atoms.signatureInfoMap.end(); signatureInfoMapIt++) {
+ for (auto signatureInfoMapIt = signatureInfoMap.begin();
+ signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
vector<java_type_t> signature = signatureInfoMapIt->first;
const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
// Key value pairs not supported in native.
- if (find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != signature.end()) {
+ if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
+ signature.end()) {
continue;
}
- write_native_method_signature(out, "int stats_write", signature, attributionDecl, " {");
+ write_native_method_signature(out, "int stats_write(", signature, attributionDecl, " {");
- int argIndex = 1;
+ // Write method body.
if (supportQ) {
+ int argIndex = 1;
fprintf(out, " StatsEventCompat event;\n");
fprintf(out, " event.setAtomId(code);\n");
write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "event.", "");
@@ -138,78 +195,37 @@ static int write_native_stats_write_methods(FILE* out, const Atoms& atoms,
write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "event.", "");
argIndex++;
}
- fprintf(out, " return event.writeToSocket();\n");
+ fprintf(out, " return event.writeToSocket();\n"); // end method body.
} else {
fprintf(out, " AStatsEvent* event = AStatsEvent_obtain();\n");
- fprintf(out, " AStatsEvent_setAtomId(event, code);\n");
- write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "AStatsEvent_",
- "event, ");
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- switch (*arg) {
- case JAVA_TYPE_ATTRIBUTION_CHAIN: {
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
- fprintf(out,
- " AStatsEvent_writeAttributionChain(event, "
- "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
- "static_cast<uint8_t>(%s_length));\n",
- uidName, tagName, uidName);
- break;
- }
- case JAVA_TYPE_BYTE_ARRAY:
- fprintf(out,
- " AStatsEvent_writeByteArray(event, "
- "reinterpret_cast<const uint8_t*>(arg%d.arg), "
- "arg%d.arg_length);\n",
- argIndex, argIndex);
- break;
- case JAVA_TYPE_BOOLEAN:
- fprintf(out, " AStatsEvent_writeBool(event, arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_INT: // Fall through.
- case JAVA_TYPE_ENUM:
- fprintf(out, " AStatsEvent_writeInt32(event, arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_FLOAT:
- fprintf(out, " AStatsEvent_writeFloat(event, arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_LONG:
- fprintf(out, " AStatsEvent_writeInt64(event, arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_STRING:
- fprintf(out, " AStatsEvent_writeString(event, arg%d);\n", argIndex);
- break;
- default:
- // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS
- fprintf(stderr, "Encountered unsupported type.");
- return 1;
- }
- write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "AStatsEvent_",
- "event, ");
- argIndex++;
+ int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet,
+ attributionDecl);
+ if (ret != 0) {
+ return ret;
}
fprintf(out, " const int ret = AStatsEvent_write(event);\n");
fprintf(out, " AStatsEvent_release(event);\n");
- fprintf(out, " return ret;\n");
+ fprintf(out, " return ret;\n"); // end method body.
}
- fprintf(out, "}\n\n");
+ fprintf(out, "}\n\n"); // end method.
}
return 0;
}
-static void write_native_stats_write_non_chained_methods(FILE* out, const Atoms& atoms,
+static void write_native_stats_write_non_chained_methods(FILE* out,
+ const SignatureInfoMap& signatureInfoMap,
const AtomDecl& attributionDecl) {
fprintf(out, "\n");
- for (auto signature_it = atoms.nonChainedSignatureInfoMap.begin();
- signature_it != atoms.nonChainedSignatureInfoMap.end(); signature_it++) {
+ for (auto signature_it = signatureInfoMap.begin();
+ signature_it != signatureInfoMap.end(); signature_it++) {
vector<java_type_t> signature = signature_it->first;
// Key value pairs not supported in native.
- if (find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != signature.end()) {
+ if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
+ signature.end()) {
continue;
}
- write_native_method_signature(out, "int stats_write_non_chained", signature,
+ write_native_method_signature(out, "int stats_write_non_chained(", signature,
attributionDecl, " {");
vector<java_type_t> newSignature;
@@ -235,6 +251,35 @@ static void write_native_stats_write_non_chained_methods(FILE* out, const Atoms&
}
}
+static int write_native_build_stats_event_methods(FILE* out,
+ const SignatureInfoMap& signatureInfoMap,
+ const AtomDecl& attributionDecl) {
+ fprintf(out, "\n");
+ for (auto signatureInfoMapIt = signatureInfoMap.begin();
+ signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
+ vector<java_type_t> signature = signatureInfoMapIt->first;
+ const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
+ // Key value pairs not supported in native.
+ if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
+ signature.end()) {
+ continue;
+ }
+ write_native_method_signature(out, "void addAStatsEvent(AStatsEventList* pulled_data, ",
+ signature, attributionDecl, " {");
+
+ fprintf(out, " AStatsEvent* event = AStatsEventList_addStatsEvent(pulled_data);\n");
+ int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet,
+ attributionDecl);
+ if (ret != 0) {
+ return ret;
+ }
+ fprintf(out, " AStatsEvent_build(event);\n"); // end method body.
+
+ fprintf(out, "}\n\n"); // end method.
+ }
+ return 0;
+}
+
static void write_native_method_header(FILE* out, const string& methodName,
const SignatureInfoMap& signatureInfoMap,
const AtomDecl& attributionDecl) {
@@ -243,7 +288,8 @@ static void write_native_method_header(FILE* out, const string& methodName,
vector<java_type_t> signature = signatureInfoMapIt->first;
// Key value pairs not supported in native.
- if (find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != signature.end()) {
+ if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
+ signature.end()) {
continue;
}
write_native_method_signature(out, methodName, signature, attributionDecl, ";");
@@ -262,13 +308,22 @@ int write_stats_log_cpp(FILE* out, const Atoms& atoms, const AtomDecl& attributi
fprintf(out, "#include <StatsEventCompat.h>\n");
} else {
fprintf(out, "#include <stats_event.h>\n");
+
+ if (!atoms.pulledAtomsSignatureInfoMap.empty()) {
+ fprintf(out, "#include <stats_pull_atom_callback.h>\n");
+ }
}
+
+
fprintf(out, "\n");
write_namespace(out, cppNamespace);
- write_native_stats_write_methods(out, atoms, attributionDecl, supportQ);
- write_native_stats_write_non_chained_methods(out, atoms, attributionDecl);
+ write_native_stats_write_methods(out, atoms.signatureInfoMap, attributionDecl, supportQ);
+ write_native_stats_write_non_chained_methods(out, atoms.nonChainedSignatureInfoMap,
+ attributionDecl);
+ write_native_build_stats_event_methods(out, atoms.pulledAtomsSignatureInfoMap,
+ attributionDecl);
// Print footer
fprintf(out, "\n");
@@ -288,6 +343,9 @@ int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attrib
fprintf(out, "#include <vector>\n");
fprintf(out, "#include <map>\n");
fprintf(out, "#include <set>\n");
+ if (!atoms.pulledAtomsSignatureInfoMap.empty()) {
+ fprintf(out, "#include <stats_pull_atom_callback.h>\n");
+ }
fprintf(out, "\n");
write_namespace(out, cppNamespace);
@@ -337,12 +395,22 @@ int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attrib
fprintf(out, "//\n");
fprintf(out, "// Write methods\n");
fprintf(out, "//\n");
- write_native_method_header(out, "int stats_write", atoms.signatureInfoMap, attributionDecl);
+ write_native_method_header(out, "int stats_write(", atoms.signatureInfoMap, attributionDecl);
+ fprintf(out, "\n");
fprintf(out, "//\n");
fprintf(out, "// Write flattened methods\n");
fprintf(out, "//\n");
- write_native_method_header(out, "int stats_write_non_chained", atoms.nonChainedSignatureInfoMap,
+ write_native_method_header(out, "int stats_write_non_chained(", atoms.nonChainedSignatureInfoMap,
+ attributionDecl);
+ fprintf(out, "\n");
+
+ // Print pulled atoms methods.
+ fprintf(out, "//\n");
+ fprintf(out, "// Add AStatsEvent methods\n");
+ fprintf(out, "//\n");
+ write_native_method_header(out, "void addAStatsEvent(AStatsEventList* pulled_data, ",
+ atoms.pulledAtomsSignatureInfoMap,
attributionDecl);
fprintf(out, "\n");
diff --git a/tools/stats_log_api_gen/native_writer.h b/tools/stats_log_api_gen/native_writer.h
index 264d4db29fc9..4e42d1fa2809 100644
--- a/tools/stats_log_api_gen/native_writer.h
+++ b/tools/stats_log_api_gen/native_writer.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H
+#define ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H
#include <stdio.h>
#include <string.h>
@@ -24,8 +25,6 @@
namespace android {
namespace stats_log_api_gen {
-using namespace std;
-
int write_stats_log_cpp(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
const string& cppNamespace, const string& importHeader,
const bool supportQ);
@@ -35,3 +34,5 @@ int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attrib
} // namespace stats_log_api_gen
} // namespace android
+
+#endif // ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H
diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp
index 5fd728a29c07..6f78921d8f1c 100644
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ b/tools/stats_log_api_gen/test_collation.cpp
@@ -24,7 +24,6 @@ namespace android {
namespace stats_log_api_gen {
using std::map;
-using std::set;
using std::vector;
/**
@@ -32,11 +31,11 @@ using std::vector;
*/
static bool map_contains_vector(const SignatureInfoMap& s, int count, ...) {
va_list args;
- vector<java_type_t> v;
+ vector<java_type_t> v(count);
va_start(args, count);
for (int i = 0; i < count; i++) {
- v.push_back((java_type_t)va_arg(args, int));
+ v[i] = static_cast<java_type_t>(va_arg(args, int));
}
va_end(args);
@@ -222,7 +221,7 @@ TEST(CollationTest, FailOnBadBinaryFieldAtom) {
Atoms atoms;
int errorCount =
collate_atoms(BadEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
- EXPECT_TRUE(errorCount > 0);
+ EXPECT_GT(errorCount, 0);
}
TEST(CollationTest, PassOnLogFromModuleAtom) {
diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp
index abb89133e58e..1eaf42acf153 100644
--- a/tools/stats_log_api_gen/utils.cpp
+++ b/tools/stats_log_api_gen/utils.cpp
@@ -16,11 +16,30 @@
#include "utils.h"
-#include "android-base/strings.h"
-
namespace android {
namespace stats_log_api_gen {
+/**
+ * Inlining this method because "android-base/strings.h" is not available on
+ * google3.
+ */
+static vector<string> Split(const string& s, const string& delimiters) {
+ GOOGLE_CHECK_NE(delimiters.size(), 0U);
+
+ vector<string> result;
+
+ size_t base = 0;
+ size_t found;
+ while (true) {
+ found = s.find_first_of(delimiters, base);
+ result.push_back(s.substr(base, found - base));
+ if (found == s.npos) break;
+ base = found + 1;
+ }
+
+ return result;
+}
+
static void build_non_chained_decl_map(const Atoms& atoms,
std::map<int, AtomDeclSet::const_iterator>* decl_map) {
for (AtomDeclSet::const_iterator atomIt = atoms.non_chained_decls.begin();
@@ -29,6 +48,20 @@ static void build_non_chained_decl_map(const Atoms& atoms,
}
}
+const map<AnnotationId, string>& get_annotation_id_constants() {
+ static const map<AnnotationId, string>* ANNOTATION_ID_CONSTANTS =
+ new map<AnnotationId, string>{
+ {ANNOTATION_ID_IS_UID, "ANNOTATION_ID_IS_UID"},
+ {ANNOTATION_ID_TRUNCATE_TIMESTAMP, "ANNOTATION_ID_TRUNCATE_TIMESTAMP"},
+ {ANNOTATION_ID_PRIMARY_FIELD, "ANNOTATION_ID_PRIMARY_FIELD"},
+ {ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, "ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID"},
+ {ANNOTATION_ID_EXCLUSIVE_STATE, "ANNOTATION_ID_EXCLUSIVE_STATE"},
+ {ANNOTATION_ID_TRIGGER_STATE_RESET, "ANNOTATION_ID_TRIGGER_STATE_RESET"},
+ {ANNOTATION_ID_STATE_NESTED, "ANNOTATION_ID_STATE_NESTED"}};
+
+ return *ANNOTATION_ID_CONSTANTS;
+}
+
/**
* Turn lower and camel case into upper case with underscores.
*/
@@ -102,15 +135,15 @@ const char* java_type_name(java_type_t type) {
// Writes namespaces for the cpp and header files, returning the number of
// namespaces written.
void write_namespace(FILE* out, const string& cppNamespaces) {
- vector<string> cppNamespaceVec = android::base::Split(cppNamespaces, ",");
- for (string cppNamespace : cppNamespaceVec) {
+ vector<string> cppNamespaceVec = Split(cppNamespaces, ",");
+ for (const string& cppNamespace : cppNamespaceVec) {
fprintf(out, "namespace %s {\n", cppNamespace.c_str());
}
}
// Writes namespace closing brackets for cpp and header files.
void write_closing_namespace(FILE* out, const string& cppNamespaces) {
- vector<string> cppNamespaceVec = android::base::Split(cppNamespaces, ",");
+ vector<string> cppNamespaceVec = Split(cppNamespaces, ",");
for (auto it = cppNamespaceVec.rbegin(); it != cppNamespaceVec.rend(); ++it) {
fprintf(out, "} // namespace %s\n", it->c_str());
}
@@ -123,7 +156,7 @@ static void write_cpp_usage(FILE* out, const string& method_name, const string&
for (vector<AtomField>::const_iterator field = atom->fields.begin();
field != atom->fields.end(); field++) {
if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
+ for (const auto& chainField : attributionDecl.fields) {
if (chainField.javaType == JAVA_TYPE_STRING) {
fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType),
chainField.name.c_str());
@@ -182,15 +215,15 @@ void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl&
fprintf(out, "\n");
}
-void write_native_method_signature(FILE* out, const string& methodName,
+void write_native_method_signature(FILE* out, const string& signaturePrefix,
const vector<java_type_t>& signature,
const AtomDecl& attributionDecl, const string& closer) {
- fprintf(out, "%s(int32_t code", methodName.c_str());
+ fprintf(out, "%sint32_t code", signaturePrefix.c_str());
int argIndex = 1;
for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
arg++) {
if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
+ for (const auto& chainField : attributionDecl.fields) {
if (chainField.javaType == JAVA_TYPE_STRING) {
fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType),
chainField.name.c_str());
@@ -222,7 +255,7 @@ void write_native_method_call(FILE* out, const string& methodName,
for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
arg++) {
if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (auto chainField : attributionDecl.fields) {
+ for (const auto& chainField : attributionDecl.fields) {
if (chainField.javaType == JAVA_TYPE_STRING) {
fprintf(out, ", %s", chainField.name.c_str());
} else {
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
index 73e0cb838227..13a7e2d8a54e 100644
--- a/tools/stats_log_api_gen/utils.h
+++ b/tools/stats_log_api_gen/utils.h
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#pragma once
+#ifndef ANDROID_STATS_LOG_API_GEN_UTILS_H
+#define ANDROID_STATS_LOG_API_GEN_UTILS_H
#include <stdio.h>
#include <string.h>
@@ -28,23 +29,14 @@
namespace android {
namespace stats_log_api_gen {
-using namespace std;
-
-const string DEFAULT_CPP_NAMESPACE = "android,util";
-const string DEFAULT_CPP_HEADER_IMPORT = "statslog.h";
+const char DEFAULT_CPP_NAMESPACE[] = "android,util";
+const char DEFAULT_CPP_HEADER_IMPORT[] = "statslog.h";
const int JAVA_MODULE_REQUIRES_FLOAT = 0x01;
const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
const int JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS = 0x04;
-const map<AnnotationId, string> ANNOTATION_ID_CONSTANTS = {
- {ANNOTATION_ID_IS_UID, "ANNOTATION_ID_IS_UID"},
- {ANNOTATION_ID_TRUNCATE_TIMESTAMP, "ANNOTATION_ID_TRUNCATE_TIMESTAMP"},
- {ANNOTATION_ID_PRIMARY_FIELD, "ANNOTATION_ID_PRIMARY_FIELD"},
- {ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, "ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID"},
- {ANNOTATION_ID_EXCLUSIVE_STATE, "ANNOTATION_ID_EXCLUSIVE_STATE"},
- {ANNOTATION_ID_TRIGGER_STATE_RESET, "ANNOTATION_ID_TRIGGER_STATE_RESET"},
- {ANNOTATION_ID_STATE_NESTED, "ANNOTATION_ID_STATE_NESTED"}};
+const map<AnnotationId, string>& get_annotation_id_constants();
string make_constant_name(const string& str);
@@ -59,7 +51,7 @@ void write_closing_namespace(FILE* out, const string& cppNamespaces);
void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl);
-void write_native_method_signature(FILE* out, const string& methodName,
+void write_native_method_signature(FILE* out, const string& signaturePrefix,
const vector<java_type_t>& signature,
const AtomDecl& attributionDecl, const string& closer);
@@ -81,3 +73,5 @@ int write_java_work_source_methods(FILE* out, const SignatureInfoMap& signatureI
} // namespace stats_log_api_gen
} // namespace android
+
+#endif // ANDROID_STATS_LOG_API_GEN_UTILS_H
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 4d3a2c02c686..68eb1bbd8a79 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -943,6 +943,9 @@ public final class WifiNetworkSuggestion implements Parcelable {
*/
@Nullable
public WifiEnterpriseConfig getEnterpriseConfig() {
+ if (!wifiConfiguration.isEnterprise()) {
+ return null;
+ }
return wifiConfiguration.enterpriseConfig;
}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 16b4ad08a830..f0839e9b3122 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -62,6 +62,7 @@ public class WifiNetworkSuggestionTest {
assertEquals(-1, suggestion.wifiConfiguration.priority);
assertFalse(suggestion.isUserAllowedToManuallyConnect);
assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -92,6 +93,7 @@ public class WifiNetworkSuggestionTest {
assertEquals(0, suggestion.wifiConfiguration.priority);
assertFalse(suggestion.isUserAllowedToManuallyConnect);
assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -122,6 +124,7 @@ public class WifiNetworkSuggestionTest {
assertEquals(-1, suggestion.wifiConfiguration.priority);
assertTrue(suggestion.isUserAllowedToManuallyConnect);
assertFalse(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -152,6 +155,7 @@ public class WifiNetworkSuggestionTest {
assertEquals(-1, suggestion.wifiConfiguration.priority);
assertTrue(suggestion.isUserAllowedToManuallyConnect);
assertFalse(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -174,6 +178,7 @@ public class WifiNetworkSuggestionTest {
assertTrue(suggestion.wifiConfiguration.requirePmf);
assertFalse(suggestion.isUserAllowedToManuallyConnect);
assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
@@ -197,6 +202,7 @@ public class WifiNetworkSuggestionTest {
assertTrue(suggestion.wifiConfiguration.requirePmf);
assertTrue(suggestion.isUserAllowedToManuallyConnect);
assertFalse(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
}
@@ -230,6 +236,7 @@ public class WifiNetworkSuggestionTest {
// here.
assertTrue(suggestion.isUserAllowedToManuallyConnect);
assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNotNull(suggestion.getEnterpriseConfig());
}
/**
@@ -286,6 +293,7 @@ public class WifiNetworkSuggestionTest {
.get(WifiConfiguration.GroupCipher.SMS4));
assertEquals("\"" + TEST_PRESHARED_KEY + "\"",
suggestion.wifiConfiguration.preSharedKey);
+ assertNull(suggestion.getEnterpriseConfig());
}
@@ -316,6 +324,7 @@ public class WifiNetworkSuggestionTest {
suggestion.wifiConfiguration.enterpriseConfig.getEapMethod());
assertEquals(TEST_WAPI_CERT_SUITE,
suggestion.wifiConfiguration.enterpriseConfig.getWapiCertSuite());
+ assertNotNull(suggestion.getEnterpriseConfig());
}
/**
@@ -345,6 +354,7 @@ public class WifiNetworkSuggestionTest {
suggestion.wifiConfiguration.enterpriseConfig.getEapMethod());
assertEquals("",
suggestion.wifiConfiguration.enterpriseConfig.getWapiCertSuite());
+ assertNotNull(suggestion.getEnterpriseConfig());
}
/**
@@ -367,6 +377,7 @@ public class WifiNetworkSuggestionTest {
assertEquals(suggestion.getPasspointConfig().getMeteredOverride(),
WifiConfiguration.METERED_OVERRIDE_METERED);
assertTrue(suggestion.isUserAllowedToManuallyConnect);
+ assertNull(suggestion.getEnterpriseConfig());
}
/**
diff --git a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
index 971aa8e05df2..79e95e81396a 100644
--- a/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/TlvBufferUtilsTest.java
@@ -267,42 +267,42 @@ public class TlvBufferUtilsTest {
@Test(expected = IllegalArgumentException.class)
public void testTlvItInvalidSizeT1L0() {
- final byte[] dummy = {
+ final byte[] testTlv = {
0, 1, 2 };
- final int dummyLength = 3;
- TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 0, dummy);
+ final int testLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 0, testTlv);
}
@Test(expected = IllegalArgumentException.class)
public void testTlvItInvalidSizeTm3L2() {
- final byte[] dummy = {
+ final byte[] testTlv = {
0, 1, 2 };
- final int dummyLength = 3;
- TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(-3, 2, dummy);
+ final int testLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(-3, 2, testTlv);
}
@Test(expected = IllegalArgumentException.class)
public void testTlvItInvalidSizeT1Lm2() {
- final byte[] dummy = {
+ final byte[] testTlv = {
0, 1, 2 };
- final int dummyLength = 3;
- TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, -2, dummy);
+ final int testLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, -2, testTlv);
}
@Test(expected = IllegalArgumentException.class)
public void testTlvItInvalidSizeT1L3() {
- final byte[] dummy = {
+ final byte[] testTlv = {
0, 1, 2 };
- final int dummyLength = 3;
- TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 3, dummy);
+ final int testLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(1, 3, testTlv);
}
@Test(expected = IllegalArgumentException.class)
public void testTlvItInvalidSizeT3L1() {
- final byte[] dummy = {
+ final byte[] testTlv = {
0, 1, 2 };
- final int dummyLength = 3;
- TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(3, 1, dummy);
+ final int testLength = 3;
+ TlvBufferUtils.TlvIterable tlvIt10 = new TlvBufferUtils.TlvIterable(3, 1, testTlv);
}
/**
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
index f2961db4eb14..b65de6b9789d 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
@@ -45,7 +45,7 @@ public class WifiAwareAgentNetworkSpecifierTest {
Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>();
for (int i = 0; i < numNs; ++i) {
- nsSet.add(getDummyNetworkSpecifier(10 + i));
+ nsSet.add(getMockNetworkSpecifier(10 + i));
}
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[numNs]));
@@ -78,7 +78,7 @@ public class WifiAwareAgentNetworkSpecifierTest {
@Test
public void testEmptyDoesntMatchAnything() {
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier();
- WifiAwareNetworkSpecifier ns = getDummyNetworkSpecifier(6);
+ WifiAwareNetworkSpecifier ns = getMockNetworkSpecifier(6);
collector.checkThat("No match expected", ns.canBeSatisfiedBy(dut), equalTo(false));
}
@@ -88,9 +88,9 @@ public class WifiAwareAgentNetworkSpecifierTest {
*/
@Test
public void testSingleMatch() {
- WifiAwareNetworkSpecifier nsThis = getDummyNetworkSpecifier(6);
+ WifiAwareNetworkSpecifier nsThis = getMockNetworkSpecifier(6);
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(nsThis);
- WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(8);
+ WifiAwareNetworkSpecifier nsOther = getMockNetworkSpecifier(8);
collector.checkThat("Match expected", nsThis.canBeSatisfiedBy(dut), equalTo(true));
collector.checkThat("No match expected", nsOther.canBeSatisfiedBy(dut), equalTo(false));
}
@@ -105,12 +105,12 @@ public class WifiAwareAgentNetworkSpecifierTest {
Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>();
for (int i = 0; i < numNs; ++i) {
- nsSet.add(getDummyNetworkSpecifier(10 + i));
+ nsSet.add(getMockNetworkSpecifier(10 + i));
}
WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[numNs]));
- WifiAwareNetworkSpecifier nsOther = getDummyNetworkSpecifier(10000);
+ WifiAwareNetworkSpecifier nsOther = getMockNetworkSpecifier(10000);
for (WifiAwareNetworkSpecifier nsThis: nsSet) {
collector.checkThat("Match expected", nsThis.canBeSatisfiedBy(dut), equalTo(true));
@@ -127,13 +127,13 @@ public class WifiAwareAgentNetworkSpecifierTest {
Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>();
for (int i = 0; i < numNs; ++i) {
- nsSet.add(getDummyNetworkSpecifier(10 + i));
+ nsSet.add(getMockNetworkSpecifier(10 + i));
}
WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
- nsSet.add(getDummyNetworkSpecifier(100 + numNs));
+ nsSet.add(getMockNetworkSpecifier(100 + numNs));
WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
@@ -149,13 +149,13 @@ public class WifiAwareAgentNetworkSpecifierTest {
Set<WifiAwareNetworkSpecifier> nsSet = new HashSet<>();
for (int i = 0; i < numNs; ++i) {
- nsSet.add(getDummyNetworkSpecifier(10 + i));
+ nsSet.add(getMockNetworkSpecifier(10 + i));
}
WifiAwareAgentNetworkSpecifier newNs = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
- nsSet.add(getDummyNetworkSpecifier(100 + numNs));
+ nsSet.add(getMockNetworkSpecifier(100 + numNs));
WifiAwareAgentNetworkSpecifier oldNs = new WifiAwareAgentNetworkSpecifier(
nsSet.toArray(new WifiAwareNetworkSpecifier[nsSet.size()]));
@@ -165,10 +165,10 @@ public class WifiAwareAgentNetworkSpecifierTest {
// utilities
/**
- * Returns a WifiAwareNetworkSpecifier with dummy (but valid) entries. Each can be
+ * Returns a WifiAwareNetworkSpecifier with mock (but valid) entries. Each can be
* differentiated (made unique) by specifying a different client ID.
*/
- WifiAwareNetworkSpecifier getDummyNetworkSpecifier(int clientId) {
+ WifiAwareNetworkSpecifier getMockNetworkSpecifier(int clientId) {
return new WifiAwareNetworkSpecifier(WifiAwareNetworkSpecifier.NETWORK_SPECIFIER_TYPE_OOB,
WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR, clientId, 0, 0, new byte[6],
null, null, 10, 5);
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index c5f98045082b..43d728bf593e 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -1585,7 +1585,7 @@ public class WifiAwareManagerTest {
public void testWifiAwareNetworkCapabilitiesParcel() throws UnknownHostException {
final Inet6Address inet6 = MacAddress.fromString(
"11:22:33:44:55:66").getLinkLocalIpv6FromEui48Mac();
- // note: dummy scope = 5
+ // note: placeholder scope = 5
final Inet6Address inet6Scoped = Inet6Address.getByAddress(null, inet6.getAddress(), 5);
final int port = 5;
final int transportProtocol = 6;