summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp2
-rw-r--r--Android.mk46
-rw-r--r--CleanSpec.mk3
-rw-r--r--api/current.txt89
-rw-r--r--api/system-current.txt38
-rw-r--r--api/test-current.txt13
-rw-r--r--cmds/incidentd/src/IncidentService.cpp42
-rw-r--r--cmds/incidentd/src/IncidentService.h1
-rw-r--r--cmds/incidentd/src/main.cpp3
-rw-r--r--cmds/statsd/src/atoms.proto37
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp2
-rw-r--r--cmds/statsd/src/guardrail/StatsdStats.cpp1
-rw-r--r--cmds/statsd/src/logd/LogEvent.cpp2
-rw-r--r--cmds/statsd/src/stats_log_util.cpp8
-rw-r--r--cmds/statsd/tests/LogEvent_test.cpp37
-rw-r--r--cmds/telecom/src/com/android/commands/telecom/Telecom.java33
-rw-r--r--config/hiddenapi-light-greylist.txt6
-rw-r--r--config/preloaded-classes4
-rw-r--r--core/java/android/app/ActivityTaskManager.java14
-rw-r--r--core/java/android/app/ActivityView.java52
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl5
-rw-r--r--core/java/android/app/IWallpaperManager.aidl2
-rw-r--r--core/java/android/app/Notification.java31
-rw-r--r--core/java/android/app/ProcessMemoryState.java7
-rw-r--r--core/java/android/app/WallpaperInfo.java3
-rw-r--r--core/java/android/app/WallpaperManager.java28
-rw-r--r--core/java/android/app/backup/OWNERS3
-rw-r--r--core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java9
-rw-r--r--core/java/android/bluetooth/BluetoothManager.java3
-rw-r--r--core/java/android/content/ContentResolver.java3
-rw-r--r--core/java/android/content/Context.java20
-rw-r--r--core/java/android/content/Intent.java27
-rw-r--r--core/java/android/content/pm/PackageInfo.java21
-rw-r--r--core/java/android/content/pm/PackageManager.java25
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java20
-rw-r--r--core/java/android/content/pm/PackageParser.java92
-rw-r--r--core/java/android/content/pm/PackageUserState.java4
-rw-r--r--core/java/android/content/pm/PermissionInfo.java10
-rw-r--r--core/java/android/content/pm/UsesPermissionInfo.java275
-rw-r--r--core/java/android/hardware/biometrics/BiometricAuthenticator.java16
-rw-r--r--core/java/android/hardware/biometrics/BiometricPrompt.java46
-rw-r--r--core/java/android/hardware/biometrics/IBiometricService.aidl8
-rw-r--r--core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl16
-rw-r--r--core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl41
-rw-r--r--core/java/android/hardware/display/DisplayViewport.java8
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl23
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl23
-rw-r--r--core/java/android/os/Binder.java4
-rw-r--r--core/java/android/os/Process.java3
-rw-r--r--core/java/android/os/UserManager.java21
-rw-r--r--core/java/android/os/storage/StorageManager.java7
-rw-r--r--core/java/android/provider/Settings.java19
-rw-r--r--core/java/android/provider/TEST_MAPPING12
-rw-r--r--core/java/android/service/oemlock/IOemLockService.aidl2
-rw-r--r--core/java/android/service/oemlock/OemLockManager.java17
-rw-r--r--core/java/android/service/wallpaper/IWallpaperEngine.aidl2
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java29
-rw-r--r--core/java/android/view/IWindowManager.aidl14
-rw-r--r--core/java/android/view/KeyEvent.java6
-rw-r--r--core/java/android/view/SurfaceControl.java28
-rw-r--r--core/java/android/view/SurfaceView.java7
-rw-r--r--core/java/android/view/View.java56
-rw-r--r--core/java/android/view/ViewGroup.java5
-rw-r--r--core/java/android/view/ViewRootImpl.java2
-rw-r--r--core/java/android/view/WindowManager.java13
-rw-r--r--core/java/android/view/WindowManagerPolicyConstants.java1
-rw-r--r--core/java/android/widget/GridView.java5
-rw-r--r--core/java/android/widget/NumberPicker.java37
-rw-r--r--core/java/android/widget/TextView.java9
-rw-r--r--core/java/com/android/internal/os/BinderCallsStats.java49
-rw-r--r--core/java/com/android/internal/os/KernelCpuThreadReader.java16
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java5
-rw-r--r--core/java/com/android/internal/policy/ScreenDecorationsUtils.java50
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl6
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl6
-rw-r--r--core/java/com/android/internal/util/BitUtils.java9
-rw-r--r--core/java/com/android/internal/util/CollectionUtils.java8
-rw-r--r--core/java/com/android/internal/util/function/NonaConsumer.java28
-rw-r--r--core/java/com/android/internal/util/function/NonaFunction.java28
-rw-r--r--core/java/com/android/internal/util/function/NonaPredicate.java28
-rw-r--r--core/java/com/android/internal/util/function/OctConsumer.java28
-rw-r--r--core/java/com/android/internal/util/function/OctFunction.java (renamed from core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl)12
-rw-r--r--core/java/com/android/internal/util/function/OctPredicate.java28
-rwxr-xr-xcore/java/com/android/internal/util/function/pooled/OmniFunction.java75
-rwxr-xr-xcore/java/com/android/internal/util/function/pooled/PooledLambda.java320
-rwxr-xr-xcore/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java88
-rw-r--r--core/java/com/android/server/SystemConfig.java2
-rw-r--r--core/jni/android_hardware_display_DisplayViewport.cpp13
-rw-r--r--core/jni/android_os_Debug.cpp6
-rw-r--r--core/jni/android_os_Debug.h7
-rw-r--r--core/jni/android_text_AndroidCharacter.cpp16
-rw-r--r--core/jni/android_util_Process.cpp34
-rw-r--r--core/jni/android_view_RenderNode.cpp5
-rw-r--r--core/jni/android_view_SurfaceControl.cpp10
-rw-r--r--core/proto/android/providers/settings/secure.proto10
-rw-r--r--core/proto/android/telephony/enums.proto1
-rw-r--r--core/res/AndroidManifest.xml120
-rw-r--r--core/res/res/layout/notification_template_header.xml1
-rw-r--r--core/res/res/values/attrs.xml6
-rw-r--r--core/res/res/values/attrs_manifest.xml79
-rw-r--r--core/res/res/values/dimens.xml2
-rw-r--r--core/res/res/values/public.xml7
-rw-r--r--core/res/res/values/strings.xml19
-rw-r--r--core/res/res/values/symbols.xml6
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java4
-rw-r--r--core/tests/coretests/src/android/text/AndroidCharacterTest.java71
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java56
-rw-r--r--core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java46
-rw-r--r--graphics/java/android/graphics/Canvas.java2
-rw-r--r--graphics/java/android/graphics/ColorSpace.java34
-rw-r--r--graphics/java/android/graphics/RenderNode.java19
-rw-r--r--graphics/java/android/graphics/Typeface.java38
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java7
-rw-r--r--libs/hwui/RenderNode.cpp42
-rw-r--r--libs/hwui/RenderNode.h6
-rw-r--r--libs/hwui/pipeline/skia/RenderNodeDrawable.cpp22
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp9
-rw-r--r--location/java/android/location/ILocationManager.aidl14
-rw-r--r--location/java/android/location/LocationManager.java26
-rw-r--r--media/java/android/media/AudioManager.java1
-rw-r--r--media/java/android/media/MediaPlayer2.java1248
-rw-r--r--media/java/android/media/RemoteController.java4
-rw-r--r--media/java/android/media/RingtoneManager.java3
-rw-r--r--media/java/android/media/midi/MidiOutputPort.java11
-rw-r--r--media/java/android/media/session/MediaController.java2
-rw-r--r--media/java/android/media/tv/TvInputService.java4
-rw-r--r--native/webview/plat_support/draw_gl.h12
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java72
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java204
-rw-r--r--packages/PackageInstaller/Android.bp14
-rw-r--r--packages/PackageInstaller/Android.mk32
-rw-r--r--packages/PackageInstaller/AndroidManifest.xml2
-rw-r--r--packages/SettingsLib/ActionButtonsPreference/Android.bp13
-rw-r--r--packages/SettingsLib/ActionButtonsPreference/AndroidManifest.xml23
-rw-r--r--packages/SettingsLib/ActionButtonsPreference/res/layout/settings_action_buttons.xml52
-rw-r--r--packages/SettingsLib/ActionButtonsPreference/res/values/styles.xml26
-rw-r--r--packages/SettingsLib/ActionButtonsPreference/src/com/android/settingslib/widget/ActionButtonsPreference.java393
-rw-r--r--packages/SettingsLib/Android.bp1
-rw-r--r--packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java4
-rw-r--r--packages/SettingsLib/tests/robotests/Android.mk10
-rw-r--r--packages/SettingsLib/tests/robotests/config/robolectric.properties4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/DeviceInfoUtilsTest.java3
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java12
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java19
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java78
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java3
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java3
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/accessibility/AccessibilityUtilsTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java9
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java22
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java15
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java6
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java13
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java13
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java14
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java13
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PbapClientProfileTest.java15
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java15
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java13
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java14
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DeveloperOptionsPreferenceControllerTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java14
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropPokerTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java22
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java6
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java6
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java44
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java9
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java12
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java12
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java21
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java21
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/InjectedSettingTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java9
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java8
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java9
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java14
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java9
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java8
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/IconCacheTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java26
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java24
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/ActionButtonsPreferenceTest.java281
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java6
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/LayoutPreferenceTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java6
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java9
-rw-r--r--packages/SystemUI/res/drawable/ic_notification_block.xml2
-rw-r--r--packages/SystemUI/res/layout/biometric_dialog.xml9
-rw-r--r--packages/SystemUI/res/layout/notification_info.xml46
-rw-r--r--packages/SystemUI/res/values/strings.xml21
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl5
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java5
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java69
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetail.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java110
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java128
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java392
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java5
-rw-r--r--packages/overlays/ExperimentNavigationBarDefaultOverlay/Android.mk30
-rw-r--r--packages/overlays/ExperimentNavigationBarDefaultOverlay/AndroidManifest.xml27
-rw-r--r--packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values/config.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-as/strings.xml)17
-rw-r--r--packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-gu/strings.xml)15
-rw-r--r--packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml2
-rw-r--r--packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml4
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/Android.mk (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/Android.mk)4
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/AndroidManifest.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/AndroidManifest.xml)4
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-af/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-af/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-am/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-am/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ar/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ar/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-az/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-az/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-b+sr+Latn/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-b+sr+Latn/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-be/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-be/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bg/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bg/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bs/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bs/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ca/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ca/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-cs/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-cs/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-da/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-da/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-de/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-de/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-el/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-el/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rAU/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rAU/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rCA/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rCA/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rGB/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rGB/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rIN/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rIN/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rXC/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es-rUS/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-es-rUS/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-es/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-et/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-et/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-eu/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-eu/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fa/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fa/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fi/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fi/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr-rCA/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fr-rCA/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fr/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-gl/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-gl/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hi/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hi/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hr/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hr/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hu/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hu/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hy/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hy/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-in/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-in/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-is/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-is/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-it/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-it/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-iw/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-iw/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ja/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ja/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ka/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ka/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-kk/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kk/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-km/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-km/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ko/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ko/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ky/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ky/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lo/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-lo/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lt/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-lt/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lv/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-lv/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mk/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-mk/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mn/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-mn/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mr/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-mr/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ms/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ms/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-my/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-my/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nb/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-nb/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nl/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-nl/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pl/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pl/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rBR/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pt-rBR/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rPT/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pt-rPT/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pt/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ro/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ro/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ru/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ru/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sk/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sl/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sl/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sq/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sq/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sr/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sr/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sv/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sv/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sw/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sw/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-th/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-th/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tl/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-tl/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tr/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-tr/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uk/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-uk/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ur/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ur/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uz/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-uz/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-vi/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-vi/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rCN/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zh-rCN/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rHK/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zh-rHK/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rTW/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zh-rTW/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zu/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zu/strings.xml)0
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values/config.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/config.xml)8
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/strings.xml)2
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim32Overlay/Android.mk30
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim32Overlay/AndroidManifest.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bn/strings.xml)18
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values/config.xml28
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-si/strings.xml)15
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim40Overlay/Android.mk30
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim40Overlay/AndroidManifest.xml27
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values/config.xml28
-rw-r--r--packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values/strings.xml (renamed from packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ml/strings.xml)15
-rw-r--r--packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kn/strings.xml23
-rw-r--r--packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ne/strings.xml23
-rw-r--r--packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-or/strings.xml23
-rw-r--r--packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pa/strings.xml23
-rw-r--r--packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ta/strings.xml23
-rw-r--r--packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-te/strings.xml23
-rw-r--r--services/backup/OWNERS2
-rw-r--r--services/core/java/com/android/server/AppOpsService.java2
-rw-r--r--services/core/java/com/android/server/BinderCallsStatsService.java4
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java45
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java28
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java8
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java5
-rw-r--r--services/core/java/com/android/server/am/MemoryStatUtil.java36
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java5
-rw-r--r--services/core/java/com/android/server/biometrics/AuthenticationClient.java343
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricService.java628
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricServiceBase.java183
-rw-r--r--services/core/java/com/android/server/biometrics/ClientMonitor.java12
-rw-r--r--services/core/java/com/android/server/biometrics/EnrollClient.java2
-rw-r--r--services/core/java/com/android/server/biometrics/EnumerateClient.java2
-rw-r--r--services/core/java/com/android/server/biometrics/RemovalClient.java2
-rw-r--r--services/core/java/com/android/server/biometrics/face/FaceService.java95
-rw-r--r--services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java96
-rw-r--r--services/core/java/com/android/server/display/DisplayDevice.java2
-rw-r--r--services/core/java/com/android/server/input/ConfigurationProcessor.java121
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java77
-rw-r--r--services/core/java/com/android/server/locksettings/SP800Derive.java82
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java56
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java2
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java26
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java174
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java1
-rw-r--r--services/core/java/com/android/server/oemlock/OemLock.java3
-rw-r--r--services/core/java/com/android/server/oemlock/OemLockService.java13
-rw-r--r--services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java6
-rw-r--r--services/core/java/com/android/server/oemlock/VendorLock.java43
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java83
-rw-r--r--services/core/java/com/android/server/pm/permission/BasePermission.java10
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java13
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java7
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java7
-rw-r--r--services/core/java/com/android/server/role/RoleManagerService.java57
-rw-r--r--services/core/java/com/android/server/role/RoleUserState.java41
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java46
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java17
-rw-r--r--services/core/java/com/android/server/storage/AppFuseBridge.java22
-rw-r--r--services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java2
-rw-r--r--services/core/java/com/android/server/tv/TvInputManagerService.java22
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java34
-rw-r--r--services/core/java/com/android/server/wm/ActivityDisplay.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java16
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLaunchObserverRegistry.java60
-rw-r--r--services/core/java/com/android/server/wm/ActivityMetricsLogger.java92
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java224
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java122
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java82
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartInterceptor.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java183
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java124
-rw-r--r--services/core/java/com/android/server/wm/AppWarnings.java3
-rw-r--r--services/core/java/com/android/server/wm/AppWindowThumbnail.java7
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java86
-rw-r--r--services/core/java/com/android/server/wm/Dimmer.java4
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java275
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java7
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java88
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowController.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowSettings.java20
-rw-r--r--services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java162
-rw-r--r--services/core/java/com/android/server/wm/LaunchParamsPersister.java8
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java4
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java4
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java16
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java149
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java4
-rw-r--r--services/core/java/com/android/server/wm/Task.java8
-rw-r--r--services/core/java/com/android/server/wm/TaskChangeNotificationController.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskRecord.java16
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java56
-rw-r--r--services/core/java/com/android/server/wm/VrController.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java10
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java55
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java30
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java10
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java163
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java10
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp59
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp231
-rw-r--r--services/tests/servicestests/AndroidManifest.xml9
-rw-r--r--services/tests/servicestests/res/raw/input_port_associations.xml4
-rw-r--r--services/tests/servicestests/res/raw/input_port_associations_bad_displayport.xml3
-rw-r--r--services/tests/servicestests/res/raw/input_port_associations_bad_xml.xml3
-rw-r--r--services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java93
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java (renamed from services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java)40
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java322
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java20
-rw-r--r--services/tests/wmtests/AndroidManifest.xml4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java89
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java19
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java107
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java)6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/AppTransitionControllerTest.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java)5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/AppWindowTokenAnimationTests.java)3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java)24
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DimmerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/DimmerTests.java)13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java)8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/DisplayPolicyInsetsTests.java)3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/DisplayPolicyLayoutTests.java)3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/DisplayPolicyTests.java)3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java (renamed from services/tests/servicestests/src/com/android/server/wm/DisplayPolicyTestsBase.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java823
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java)35
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DockedStackDividerControllerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/DockedStackDividerControllerTests.java)3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java)11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java)8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java)8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java45
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java)13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java)8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java)17
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java)13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java)9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java)8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java)7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java)11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskWindowContainerControllerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestIWindow.java (renamed from services/tests/servicestests/src/com/android/server/wm/TestIWindow.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java (renamed from services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java)11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java)2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/WallpaperControllerTests.java)5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java)26
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java)5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java)2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java)12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRuleTest.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java)11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java263
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java)2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java)0
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java (renamed from services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java)0
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomService.aidl6
-rw-r--r--telephony/java/android/telephony/RadioAccessFamily.java3
-rw-r--r--telephony/java/android/telephony/ServiceState.java10
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java8
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java21
-rw-r--r--telephony/java/android/telephony/emergency/EmergencyNumber.java5
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java75
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl7
-rw-r--r--test-mock/api/current.txt1
-rw-r--r--test-mock/api/test-current.txt4
-rw-r--r--tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java6
-rwxr-xr-xtools/hiddenapi/generate_hiddenapi_lists.py403
-rwxr-xr-xtools/hiddenapi/generate_hiddenapi_lists_test.py168
-rw-r--r--tools/incident_section_gen/main.cpp3
-rw-r--r--tools/powermodel/Android.bp26
-rw-r--r--tools/powermodel/TEST_MAPPING8
-rw-r--r--tools/powermodel/src/com/android/powermodel/ActivityReport.java92
-rw-r--r--tools/powermodel/src/com/android/powermodel/AppActivity.java80
-rw-r--r--tools/powermodel/src/com/android/powermodel/AppInfo.java56
-rw-r--r--tools/powermodel/src/com/android/powermodel/AppList.java91
-rw-r--r--tools/powermodel/src/com/android/powermodel/AppPower.java86
-rw-r--r--tools/powermodel/src/com/android/powermodel/AttributionKey.java113
-rw-r--r--tools/powermodel/src/com/android/powermodel/BatteryStatsReader.java74
-rw-r--r--tools/powermodel/src/com/android/powermodel/Component.java34
-rw-r--r--tools/powermodel/src/com/android/powermodel/ComponentActivity.java42
-rw-r--r--tools/powermodel/src/com/android/powermodel/ComponentPower.java41
-rw-r--r--tools/powermodel/src/com/android/powermodel/ComponentProfile.java20
-rw-r--r--tools/powermodel/src/com/android/powermodel/CsvParser.java173
-rw-r--r--tools/powermodel/src/com/android/powermodel/ParseException.java35
-rw-r--r--tools/powermodel/src/com/android/powermodel/PowerProfile.java527
-rw-r--r--tools/powermodel/src/com/android/powermodel/PowerReport.java101
-rw-r--r--tools/powermodel/src/com/android/powermodel/RawBatteryStats.java1175
-rw-r--r--tools/powermodel/src/com/android/powermodel/SpecialApp.java85
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/AudioProfile.java27
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/BluetoothProfile.java29
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/CameraProfile.java27
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/CpuProfile.java145
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/FlashlightProfile.java27
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/GpsProfile.java53
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/ModemAppActivity.java85
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/ModemAppPower.java24
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/ModemBatteryStatsReader.java110
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/ModemGlobalActivity.java51
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/ModemProfile.java92
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/ModemRemainderActivity.java87
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/ModemRemainderPower.java30
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/ScreenProfile.java29
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/VideoProfile.java28
-rw-r--r--tools/powermodel/src/com/android/powermodel/component/WifiProfile.java29
-rw-r--r--tools/powermodel/src/com/android/powermodel/util/Conversion.java47
-rw-r--r--tools/powermodel/test-resource/bs.csv7
-rw-r--r--tools/powermodel/test-resource/power_profile.xml170
-rw-r--r--tools/powermodel/test/com/android/powermodel/BatteryStatsReaderTest.java80
-rw-r--r--tools/powermodel/test/com/android/powermodel/CsvParserTest.java311
-rw-r--r--tools/powermodel/test/com/android/powermodel/PowerProfileTest.java159
-rw-r--r--tools/powermodel/test/com/android/powermodel/PowerReportTest.java128
-rw-r--r--tools/powermodel/test/com/android/powermodel/RawBatteryStatsTest.java96
-rw-r--r--tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java23
-rw-r--r--tools/stats_log_api_gen/main.cpp5
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl12
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java132
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java76
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java5
-rw-r--r--wifi/java/android/net/wifi/WifiScanner.java34
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pConfig.java191
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pManager.java32
-rw-r--r--wifi/java/com/android/server/wifi/AbstractWifiService.java12
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java21
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java76
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java34
592 files changed, 15948 insertions, 5080 deletions
diff --git a/Android.bp b/Android.bp
index 25e738ccb3cf..41d5f28a2680 100644
--- a/Android.bp
+++ b/Android.bp
@@ -158,9 +158,9 @@ java_defaults {
"core/java/android/hardware/IConsumerIrService.aidl",
"core/java/android/hardware/ISerialManager.aidl",
"core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl",
- "core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl",
"core/java/android/hardware/biometrics/IBiometricService.aidl",
"core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl",
+ "core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl",
"core/java/android/hardware/biometrics/IBiometricServiceLockoutResetCallback.aidl",
"core/java/android/hardware/display/IDisplayManager.aidl",
"core/java/android/hardware/display/IDisplayManagerCallback.aidl",
diff --git a/Android.mk b/Android.mk
index 770ec20f151e..b7dda9a45ed8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -73,55 +73,37 @@ $(OUT_DOCS)/offline-sdk-timestamp: $(OUT_DOCS)/offline-sdk-docs-docs.zip
( unzip -qo $< -d $(OUT_DOCS)/offline-sdk && touch -f $@ ) || exit 1
# ==== hiddenapi lists =======================================
-.KATI_RESTAT: \
- $(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST) \
- $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
- $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) \
- $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
-$(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST): \
- .KATI_IMPLICIT_OUTPUTS := \
- $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
- $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) \
- $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
-$(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST): \
+.KATI_RESTAT: $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS)
+$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \
frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py \
frameworks/base/config/hiddenapi-light-greylist.txt \
frameworks/base/config/hiddenapi-vendor-list.txt \
+ frameworks/base/config/hiddenapi-greylist-max-o.txt \
frameworks/base/config/hiddenapi-max-sdk-p-blacklist.txt \
frameworks/base/config/hiddenapi-force-blacklist.txt \
$(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) \
$(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST) \
$(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE)
frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py \
- --input-public $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) \
- --input-private $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST) \
- --input-whitelists $(PRIVATE_WHITELIST_INPUTS) \
- --input-greylists \
+ --public $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) \
+ --private $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST) \
+ --csv $(PRIVATE_FLAGS_INPUTS) \
+ --greylist \
frameworks/base/config/hiddenapi-light-greylist.txt \
frameworks/base/config/hiddenapi-vendor-list.txt \
- frameworks/base/config/hiddenapi-max-sdk-p-blacklist.txt \
- <(comm -12 <(sort $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE)) \
- $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST)) \
- $(PRIVATE_GREYLIST_INPUTS) \
- --input-blacklists frameworks/base/config/hiddenapi-force-blacklist.txt \
- --output-whitelist $(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST).tmp \
- --output-light-greylist $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST).tmp \
- --output-dark-greylist $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST).tmp \
- --output-blacklist $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST).tmp
- $(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST))
- $(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST))
- $(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST))
- $(call commit-change-for-toc,$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST))
+ --greylist-ignore-conflicts $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE) \
+ --greylist-max-o-ignore-conflicts \
+ frameworks/base/config/hiddenapi-greylist-max-o.txt \
+ --blacklist frameworks/base/config/hiddenapi-force-blacklist.txt \
+ --output $@.tmp
+ $(call commit-change-for-toc,$@)
$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA): \
frameworks/base/tools/hiddenapi/merge_csv.py \
$(PRIVATE_METADATA_INPUTS)
frameworks/base/tools/hiddenapi/merge_csv.py $(PRIVATE_METADATA_INPUTS) > $@
-$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_WHITELIST))
-$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST))
-$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST))
-$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST))
+$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS))
$(call dist-for-goals,droidcore,$(INTERNAL_PLATFORM_HIDDENAPI_GREYLIST_METADATA))
# Include subdirectory makefiles
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 6deda0caa9aa..478e4fe86d3b 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -248,6 +248,9 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/com.android.mediad
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/com.android.location.provider.jar)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/com.android.future.usb.accessory.jar)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/framework/com.android.media.remotedisplay.jar)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/overlay/ExperimentNavigationBarSlim)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/vendor/overlay/ExperimentNavigationBarSlim)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/overlay/ExperimentNavigationBarSlim)
# ******************************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST ABOVE THIS BANNER
# ******************************************************************
diff --git a/api/current.txt b/api/current.txt
index 9d46863f0102..079539e3c5f4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -150,6 +150,7 @@ package android {
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
field public static final java.lang.String USE_BIOMETRIC = "android.permission.USE_BIOMETRIC";
field public static final deprecated java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
+ field public static final java.lang.String USE_FULL_SCREEN_INTENT = "android.permission.USE_FULL_SCREEN_INTENT";
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
field public static final java.lang.String WAKE_LOCK = "android.permission.WAKE_LOCK";
@@ -480,6 +481,10 @@ package android {
field public static final int dashGap = 16843175; // 0x10101a7
field public static final int dashWidth = 16843174; // 0x10101a6
field public static final int data = 16842798; // 0x101002e
+ field public static final int dataRetentionTime = 16844189; // 0x101059d
+ field public static final int dataSentOffDevice = 16844186; // 0x101059a
+ field public static final int dataSharedWithThirdParty = 16844187; // 0x101059b
+ field public static final int dataUsedForMonetization = 16844188; // 0x101059c
field public static final int datePickerDialogTheme = 16843948; // 0x10104ac
field public static final int datePickerMode = 16843955; // 0x10104b3
field public static final int datePickerStyle = 16843612; // 0x101035c
@@ -1197,6 +1202,7 @@ package android {
field public static final int selectableItemBackgroundBorderless = 16843868; // 0x101045c
field public static final deprecated int selectedDateVerticalBar = 16843591; // 0x1010347
field public static final deprecated int selectedWeekBackgroundColor = 16843586; // 0x1010342
+ field public static final int selectionDividerHeight = 16844190; // 0x101059e
field public static final int sessionService = 16843837; // 0x101043d
field public static final int settingsActivity = 16843301; // 0x1010225
field public static final int settingsSliceUri = 16844179; // 0x1010593
@@ -1312,7 +1318,6 @@ package android {
field public static final int summaryColumn = 16843426; // 0x10102a2
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
- field public static final int supportsAmbientMode = 16844173; // 0x101058d
field public static final int supportsAssist = 16844016; // 0x10104f0
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
field public static final int supportsLocalInteraction = 16844047; // 0x101050f
@@ -1496,6 +1501,7 @@ package android {
field public static final deprecated int unfocusedMonthDateColor = 16843588; // 0x1010344
field public static final int unselectedAlpha = 16843278; // 0x101020e
field public static final int updatePeriodMillis = 16843344; // 0x1010250
+ field public static final int usageInfoRequired = 16844185; // 0x1010599
field public static final int use32bitAbi = 16844053; // 0x1010515
field public static final int useAppZygote = 16844184; // 0x1010598
field public static final int useDefaultMargins = 16843641; // 0x1010379
@@ -6354,7 +6360,6 @@ package android.app {
method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
method public android.graphics.drawable.Drawable loadThumbnail(android.content.pm.PackageManager);
- method public boolean supportsAmbientMode();
method public boolean supportsMultipleDisplays();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.WallpaperInfo> CREATOR;
@@ -9553,6 +9558,7 @@ package android.content {
method public abstract java.io.File getNoBackupFilesDir();
method public abstract java.io.File getObbDir();
method public abstract java.io.File[] getObbDirs();
+ method public abstract java.lang.String getOpPackageName();
method public abstract java.lang.String getPackageCodePath();
method public abstract android.content.pm.PackageManager getPackageManager();
method public abstract java.lang.String getPackageName();
@@ -9763,6 +9769,7 @@ package android.content {
method public java.io.File getNoBackupFilesDir();
method public java.io.File getObbDir();
method public java.io.File[] getObbDirs();
+ method public java.lang.String getOpPackageName();
method public java.lang.String getPackageCodePath();
method public android.content.pm.PackageManager getPackageManager();
method public java.lang.String getPackageName();
@@ -11173,8 +11180,8 @@ package android.content.pm {
field public android.content.pm.ProviderInfo[] providers;
field public android.content.pm.ActivityInfo[] receivers;
field public android.content.pm.FeatureInfo[] reqFeatures;
- field public java.lang.String[] requestedPermissions;
- field public int[] requestedPermissionsFlags;
+ field public deprecated java.lang.String[] requestedPermissions;
+ field public deprecated int[] requestedPermissionsFlags;
field public android.content.pm.ServiceInfo[] services;
field public java.lang.String sharedUserId;
field public int sharedUserLabel;
@@ -11182,6 +11189,7 @@ package android.content.pm {
field public android.content.pm.SigningInfo signingInfo;
field public java.lang.String[] splitNames;
field public int[] splitRevisionCodes;
+ field public android.content.pm.UsesPermissionInfo[] usesPermissions;
field public deprecated int versionCode;
field public java.lang.String versionName;
}
@@ -11332,7 +11340,7 @@ package android.content.pm {
method public abstract int checkSignatures(java.lang.String, java.lang.String);
method public abstract int checkSignatures(int, int);
method public abstract void clearInstantAppCookie();
- method public abstract void clearPackagePreferredActivities(java.lang.String);
+ method public abstract deprecated void clearPackagePreferredActivities(java.lang.String);
method public abstract java.lang.String[] currentToCanonicalPackageNames(java.lang.String[]);
method public abstract void extendVerificationTimeout(int, int, long);
method public abstract android.graphics.drawable.Drawable getActivityBanner(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -11376,8 +11384,8 @@ package android.content.pm {
method public abstract java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(java.lang.String[], int);
method public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.pm.PermissionInfo getPermissionInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
- method public abstract int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
- method public abstract java.util.List<android.content.pm.PackageInfo> getPreferredPackages(int);
+ method public abstract deprecated int getPreferredActivities(java.util.List<android.content.IntentFilter>, java.util.List<android.content.ComponentName>, java.lang.String);
+ method public abstract deprecated java.util.List<android.content.pm.PackageInfo> getPreferredPackages(int);
method public abstract android.content.pm.ProviderInfo getProviderInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.pm.ActivityInfo getReceiverInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract android.content.res.Resources getResourcesForActivity(android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -11657,6 +11665,7 @@ package android.content.pm {
field public java.lang.String group;
field public java.lang.CharSequence nonLocalizedDescription;
field public deprecated int protectionLevel;
+ field public boolean usageInfoRequired;
}
public final class ProviderInfo extends android.content.pm.ComponentInfo implements android.os.Parcelable {
@@ -11836,6 +11845,28 @@ package android.content.pm {
field public static final android.os.Parcelable.Creator<android.content.pm.SigningInfo> CREATOR;
}
+ public final class UsesPermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getDataRetention();
+ method public int getDataRetentionWeeks();
+ method public int getDataSentOffDevice();
+ method public int getDataSharedWithThirdParty();
+ method public int getDataUsedForMonetization();
+ method public int getFlags();
+ method public java.lang.String getPermission();
+ field public static final android.os.Parcelable.Creator<android.content.pm.UsesPermissionInfo> CREATOR;
+ field public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 2; // 0x2
+ field public static final int RETENTION_NOT_RETAINED = 1; // 0x1
+ field public static final int RETENTION_SPECIFIED = 4; // 0x4
+ field public static final int RETENTION_UNDEFINED = 0; // 0x0
+ field public static final int RETENTION_UNLIMITED = 3; // 0x3
+ field public static final int RETENTION_USER_SELECTED = 2; // 0x2
+ field public static final int USAGE_NO = 3; // 0x3
+ field public static final int USAGE_UNDEFINED = 0; // 0x0
+ field public static final int USAGE_USER_TRIGGERED = 2; // 0x2
+ field public static final int USAGE_YES = 1; // 0x1
+ }
+
public final class VersionedPackage implements android.os.Parcelable {
ctor public VersionedPackage(java.lang.String, int);
ctor public VersionedPackage(java.lang.String, long);
@@ -13697,6 +13728,7 @@ package android.graphics {
public abstract class ColorSpace {
method public static android.graphics.ColorSpace adapt(android.graphics.ColorSpace, float[]);
method public static android.graphics.ColorSpace adapt(android.graphics.ColorSpace, float[], android.graphics.ColorSpace.Adaptation);
+ method public static float[] chromaticAdaptation(android.graphics.ColorSpace.Adaptation, float[], float[]);
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace);
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace, android.graphics.ColorSpace, android.graphics.ColorSpace.RenderIntent);
method public static android.graphics.ColorSpace.Connector connect(android.graphics.ColorSpace);
@@ -14698,6 +14730,7 @@ package android.graphics {
method public float getTranslationX();
method public float getTranslationY();
method public float getTranslationZ();
+ method public long getUniqueId();
method public int getWidth();
method public boolean hasDisplayList();
method public boolean hasIdentityMatrix();
@@ -15051,6 +15084,7 @@ package android.graphics.drawable {
method public void invalidateSelf();
method public boolean isAutoMirrored();
method public boolean isFilterBitmap();
+ method public boolean isProjected();
method public boolean isStateful();
method public final boolean isVisible();
method public void jumpToCurrentState();
@@ -29021,7 +29055,7 @@ package android.net.wifi {
public class WifiManager {
method public deprecated int addNetwork(android.net.wifi.WifiConfiguration);
- method public boolean addNetworkSuggestions(java.util.List<android.net.wifi.WifiNetworkSuggestion>);
+ method public int addNetworkSuggestions(java.util.List<android.net.wifi.WifiNetworkSuggestion>);
method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
method public static int calculateSignalLevel(int, int);
method public deprecated void cancelWps(android.net.wifi.WifiManager.WpsCallback);
@@ -29035,6 +29069,7 @@ package android.net.wifi {
method public deprecated java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
method public android.net.wifi.WifiInfo getConnectionInfo();
method public android.net.DhcpInfo getDhcpInfo();
+ method public int getMaxNumberOfNetworkSuggestionsPerApp();
method public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
@@ -29053,7 +29088,7 @@ package android.net.wifi {
method public deprecated boolean reassociate();
method public deprecated boolean reconnect();
method public deprecated boolean removeNetwork(int);
- method public boolean removeNetworkSuggestions(java.util.List<android.net.wifi.WifiNetworkSuggestion>);
+ method public int removeNetworkSuggestions(java.util.List<android.net.wifi.WifiNetworkSuggestion>);
method public void removePasspointConfiguration(java.lang.String);
method public deprecated boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
@@ -29082,6 +29117,11 @@ package android.net.wifi {
field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
field public static final java.lang.String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
field public static final java.lang.String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 2; // 0x2
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 3; // 0x3
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1; // 0x1
+ field public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 4; // 0x4
+ field public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0; // 0x0
field public static final deprecated java.lang.String SUPPLICANT_CONNECTION_CHANGE_ACTION = "android.net.wifi.supplicant.CONNECTION_CHANGE";
field public static final deprecated java.lang.String SUPPLICANT_STATE_CHANGED_ACTION = "android.net.wifi.supplicant.STATE_CHANGE";
field public static final int WIFI_MODE_FULL = 1; // 0x1
@@ -29123,6 +29163,9 @@ package android.net.wifi {
method public void setReferenceCounted(boolean);
}
+ public static abstract class WifiManager.NetworkSuggestionsStatusCode implements java.lang.annotation.Annotation {
+ }
+
public class WifiManager.WifiLock {
method public void acquire();
method public boolean isHeld();
@@ -29414,11 +29457,24 @@ package android.net.wifi.p2p {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.net.wifi.p2p.WifiP2pConfig> CREATOR;
+ field public static final int GROUP_OWNER_BAND_2GHZ = 1; // 0x1
+ field public static final int GROUP_OWNER_BAND_5GHZ = 2; // 0x2
+ field public static final int GROUP_OWNER_BAND_AUTO = 0; // 0x0
field public java.lang.String deviceAddress;
field public int groupOwnerIntent;
field public android.net.wifi.WpsInfo wps;
}
+ public static final class WifiP2pConfig.Builder {
+ ctor public WifiP2pConfig.Builder();
+ method public android.net.wifi.p2p.WifiP2pConfig build();
+ method public android.net.wifi.p2p.WifiP2pConfig.Builder enablePersistentMode(boolean);
+ method public android.net.wifi.p2p.WifiP2pConfig.Builder setDeviceAddress(android.net.MacAddress);
+ method public android.net.wifi.p2p.WifiP2pConfig.Builder setGroupOwnerBand(int);
+ method public android.net.wifi.p2p.WifiP2pConfig.Builder setNetworkName(java.lang.String);
+ method public android.net.wifi.p2p.WifiP2pConfig.Builder setPassphrase(java.lang.String);
+ }
+
public class WifiP2pDevice implements android.os.Parcelable {
ctor public WifiP2pDevice();
ctor public WifiP2pDevice(android.net.wifi.p2p.WifiP2pDevice);
@@ -29485,6 +29541,7 @@ package android.net.wifi.p2p {
method public void clearServiceRequests(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void connect(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void createGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
+ method public void createGroup(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pConfig, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void discoverPeers(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public void discoverServices(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener);
method public android.net.wifi.p2p.WifiP2pManager.Channel initialize(android.content.Context, android.os.Looper, android.net.wifi.p2p.WifiP2pManager.ChannelListener);
@@ -40899,11 +40956,9 @@ package android.service.wallpaper {
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
method public android.view.SurfaceHolder getSurfaceHolder();
- method public boolean isInAmbientMode();
method public boolean isPreview();
method public boolean isVisible();
method public void notifyColorsChanged();
- method public void onAmbientModeChanged(boolean, boolean);
method public void onApplyWindowInsets(android.view.WindowInsets);
method public android.os.Bundle onCommand(java.lang.String, int, int, int, android.os.Bundle, boolean);
method public android.app.WallpaperColors onComputeColors();
@@ -43883,6 +43938,7 @@ package android.telephony {
field public static final int NETWORK_TYPE_IDEN = 11; // 0xb
field public static final int NETWORK_TYPE_IWLAN = 18; // 0x12
field public static final int NETWORK_TYPE_LTE = 13; // 0xd
+ field public static final int NETWORK_TYPE_NR = 20; // 0x14
field public static final int NETWORK_TYPE_TD_SCDMA = 17; // 0x11
field public static final int NETWORK_TYPE_UMTS = 3; // 0x3
field public static final int NETWORK_TYPE_UNKNOWN = 0; // 0x0
@@ -49024,10 +49080,12 @@ package android.view {
method protected int getTopPaddingOffset();
method public android.view.TouchDelegate getTouchDelegate();
method public java.util.ArrayList<android.view.View> getTouchables();
+ method public float getTransitionAlpha();
method public java.lang.String getTransitionName();
method public float getTranslationX();
method public float getTranslationY();
method public float getTranslationZ();
+ method public long getUniqueDrawingId();
method public int getVerticalFadingEdgeLength();
method public int getVerticalScrollbarPosition();
method public int getVerticalScrollbarWidth();
@@ -49232,6 +49290,7 @@ package android.view {
method public void setActivated(boolean);
method public void setAlpha(float);
method public void setAnimation(android.view.animation.Animation);
+ method public void setAnimationMatrix(android.graphics.Matrix);
method public void setAutofillHints(java.lang.String...);
method public void setAutofillId(android.view.autofill.AutofillId);
method public void setBackground(android.graphics.drawable.Drawable);
@@ -49283,7 +49342,7 @@ package android.view {
method public void setLayoutDirection(int);
method public void setLayoutParams(android.view.ViewGroup.LayoutParams);
method public final void setLeft(int);
- method public void setLeftTopRightBottom(int, int, int, int);
+ method public final void setLeftTopRightBottom(int, int, int, int);
method public void setLongClickable(boolean);
method protected final void setMeasuredDimension(int, int);
method public void setMinimumHeight(int);
@@ -49350,6 +49409,7 @@ package android.view {
method public void setTooltipText(java.lang.CharSequence);
method public final void setTop(int);
method public void setTouchDelegate(android.view.TouchDelegate);
+ method public void setTransitionAlpha(float);
method public final void setTransitionName(java.lang.String);
method public void setTranslationX(float);
method public void setTranslationY(float);
@@ -49823,6 +49883,7 @@ package android.view {
method public deprecated boolean isAnimationCacheEnabled();
method protected boolean isChildrenDrawingOrderEnabled();
method protected deprecated boolean isChildrenDrawnWithCacheEnabled();
+ method public boolean isLayoutSuppressed();
method public boolean isMotionEventSplittingEnabled();
method public boolean isTransitionGroup();
method public final void layout(int, int, int, int);
@@ -49888,6 +49949,7 @@ package android.view {
method public android.view.ActionMode startActionModeForChild(android.view.View, android.view.ActionMode.Callback, int);
method public void startLayoutAnimation();
method public void startViewTransition(android.view.View);
+ method public void suppressLayout(boolean);
method public void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
field protected static final int CLIP_TO_PADDING_MASK = 34; // 0x22
field public static final int FOCUS_AFTER_DESCENDANTS = 262144; // 0x40000
@@ -54535,6 +54597,7 @@ package android.widget {
method public java.lang.String[] getDisplayedValues();
method public int getMaxValue();
method public int getMinValue();
+ method public int getSelectionDividerHeight();
method public int getValue();
method public boolean getWrapSelectorWheel();
method public void setDisplayedValues(java.lang.String[]);
@@ -54544,6 +54607,7 @@ package android.widget {
method public void setOnLongPressUpdateInterval(long);
method public void setOnScrollListener(android.widget.NumberPicker.OnScrollListener);
method public void setOnValueChangedListener(android.widget.NumberPicker.OnValueChangeListener);
+ method public void setSelectionDividerHeight(int);
method public void setValue(int);
method public void setWrapSelectorWheel(boolean);
}
@@ -55551,6 +55615,7 @@ package android.widget {
method public boolean isElegantTextHeight();
method public boolean isFallbackLineSpacing();
method public boolean isInputMethodTarget();
+ method public boolean isSingleLine();
method public boolean isSuggestionsEnabled();
method public boolean isTextSelectable();
method public int length();
diff --git a/api/system-current.txt b/api/system-current.txt
index 257b4f636963..62d446f7254e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -17,6 +17,7 @@ package android {
field public static final java.lang.String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
field public static final java.lang.String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
field public static final java.lang.String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
+ field public static final java.lang.String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER";
field public static final java.lang.String BACKUP = "android.permission.BACKUP";
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
@@ -216,6 +217,10 @@ package android {
field public static final java.lang.String WRITE_SECURE_SETTINGS = "android.permission.WRITE_SECURE_SETTINGS";
}
+ public static final class Manifest.permission_group {
+ field public static final java.lang.String UNDEFINED = "android.permission-group.UNDEFINED";
+ }
+
public static final class R.array {
field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005
}
@@ -224,6 +229,7 @@ package android {
field public static final int isVrOnly = 16844152; // 0x1010578
field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
+ field public static final int supportsAmbientMode = 16844173; // 0x101058d
field public static final int userRestriction = 16844164; // 0x1010584
}
@@ -555,6 +561,10 @@ package android.app {
method public void onVrStateChanged(boolean);
}
+ public final class WallpaperInfo implements android.os.Parcelable {
+ method public boolean supportsAmbientMode();
+ }
+
public class WallpaperManager {
method public void clearWallpaper(int, int);
method public void setDisplayOffset(android.os.IBinder, int, int);
@@ -1063,7 +1073,6 @@ package android.content {
field public static final java.lang.String ACTION_INSTALL_INSTANT_APP_PACKAGE = "android.intent.action.INSTALL_INSTANT_APP_PACKAGE";
field public static final java.lang.String ACTION_INSTANT_APP_RESOLVER_SETTINGS = "android.intent.action.INSTANT_APP_RESOLVER_SETTINGS";
field public static final java.lang.String ACTION_INTENT_FILTER_NEEDS_VERIFICATION = "android.intent.action.INTENT_FILTER_NEEDS_VERIFICATION";
- field public static final java.lang.String ACTION_MANAGE_APP_PERMISSION = "android.intent.action.MANAGE_APP_PERMISSION";
field public static final java.lang.String ACTION_MANAGE_APP_PERMISSIONS = "android.intent.action.MANAGE_APP_PERMISSIONS";
field public static final java.lang.String ACTION_MANAGE_PERMISSIONS = "android.intent.action.MANAGE_PERMISSIONS";
field public static final java.lang.String ACTION_MANAGE_PERMISSION_APPS = "android.intent.action.MANAGE_PERMISSION_APPS";
@@ -1235,7 +1244,7 @@ package android.content.pm {
method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(android.content.Intent, int, android.os.UserHandle);
method public abstract void registerDexModule(java.lang.String, android.content.pm.PackageManager.DexModuleRegisterCallback);
method public abstract void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
- method public void replacePreferredActivity(android.content.IntentFilter, int, java.util.List<android.content.ComponentName>, android.content.ComponentName);
+ method public deprecated void replacePreferredActivity(android.content.IntentFilter, int, java.util.List<android.content.ComponentName>, android.content.ComponentName);
method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
method public void sendDeviceCustomizationReadyBroadcast();
method public abstract boolean setDefaultBrowserPackageNameAsUser(java.lang.String, int);
@@ -2756,7 +2765,6 @@ package android.location {
public class LocationManager {
method public deprecated boolean addGpsMeasurementListener(android.location.GpsMeasurementsEvent.Listener);
method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
- method public android.app.PendingIntent createManageLocationPermissionIntent(java.lang.String, java.lang.String);
method public void flushGnssBatch();
method public int getGnssBatchSize();
method public java.lang.String getNetworkProviderPackage();
@@ -2865,6 +2873,7 @@ package android.media {
field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
+ field public static final int FLAG_FROM_KEY = 4096; // 0x1000
}
public static abstract class AudioManager.AudioServerStateCallback {
@@ -3679,8 +3688,11 @@ package android.net.wifi {
public class WifiManager {
method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
+ method public void connect(int, android.net.wifi.WifiManager.ActionListener);
+ method public void disable(int, android.net.wifi.WifiManager.ActionListener);
+ method public void disableEphemeralNetwork(java.lang.String);
+ method public void forget(int, android.net.wifi.WifiManager.ActionListener);
method public java.util.List<android.net.wifi.WifiConfiguration> getAllMatchingWifiConfigs(java.util.List<android.net.wifi.ScanResult>);
- method public java.util.List<android.net.wifi.hotspot2.OsuProvider> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>);
method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
method public android.net.wifi.WifiConfiguration getWifiApConfiguration();
method public int getWifiApState();
@@ -3690,6 +3702,7 @@ package android.net.wifi {
method public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
method public void registerNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback, android.os.Handler);
+ method public void save(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener);
method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
method public boolean startScan(android.os.WorkSource);
method public void unregisterNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback);
@@ -3838,6 +3851,7 @@ package android.net.wifi {
ctor public WifiScanner.ScanSettings();
field public int band;
field public android.net.wifi.WifiScanner.ChannelSpec[] channels;
+ field public boolean ignoreLocationSettings;
field public int maxPeriodInMs;
field public int maxScansToCache;
field public int numBssidsPerScan;
@@ -4295,6 +4309,7 @@ package android.os {
public class UserManager {
method public void clearSeedAccountData();
+ method public android.os.UserHandle getProfileParent(android.os.UserHandle);
method public java.lang.String getSeedAccountName();
method public android.os.PersistableBundle getSeedAccountOptions();
method public java.lang.String getSeedAccountType();
@@ -4626,6 +4641,8 @@ package android.provider {
field public static final java.lang.String HUSH_GESTURE_USED = "hush_gesture_used";
field public static final java.lang.String INSTANT_APPS_ENABLED = "instant_apps_enabled";
field public static final java.lang.String LAST_SETUP_SHOWN = "last_setup_shown";
+ field public static final java.lang.String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
+ field public static final java.lang.String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
field public static final java.lang.String LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS = "lock_screen_allow_private_notifications";
field public static final java.lang.String LOCK_SCREEN_SHOW_NOTIFICATIONS = "lock_screen_show_notifications";
field public static final java.lang.String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
@@ -5164,6 +5181,7 @@ package android.service.notification {
package android.service.oemlock {
public class OemLockManager {
+ method public java.lang.String getLockName();
method public boolean isOemUnlockAllowedByCarrier();
method public boolean isOemUnlockAllowedByUser();
method public void setOemUnlockAllowedByCarrier(boolean, byte[]);
@@ -5334,6 +5352,15 @@ package android.service.trust {
}
+package android.service.wallpaper {
+
+ public class WallpaperService.Engine {
+ method public boolean isInAmbientMode();
+ method public void onAmbientModeChanged(boolean, long);
+ }
+
+}
+
package android.telecom {
public deprecated class AudioState implements android.os.Parcelable {
@@ -5903,6 +5930,7 @@ package android.telephony {
field public static final int NETWORK_TYPE_BITMASK_HSUPA = 512; // 0x200
field public static final int NETWORK_TYPE_BITMASK_LTE = 8192; // 0x2000
field public static final int NETWORK_TYPE_BITMASK_LTE_CA = 524288; // 0x80000
+ field public static final int NETWORK_TYPE_BITMASK_NR = 1048576; // 0x100000
field public static final int NETWORK_TYPE_BITMASK_TD_SCDMA = 131072; // 0x20000
field public static final int NETWORK_TYPE_BITMASK_UMTS = 8; // 0x8
field public static final int NETWORK_TYPE_BITMASK_UNKNOWN = 1; // 0x1
@@ -6215,6 +6243,7 @@ package android.telephony.ims {
method public android.os.Bundle getCallExtras();
method public int getCallType();
method public static int getCallTypeFromVideoState(int);
+ method public int getEmergencyServiceCategories();
method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
method public int getRestrictCause();
method public int getServiceType();
@@ -6227,6 +6256,7 @@ package android.telephony.ims {
method public void setCallExtraBoolean(java.lang.String, boolean);
method public void setCallExtraInt(java.lang.String, int);
method public void setCallRestrictCause(int);
+ method public void setEmergencyServiceCategories(int);
method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
method public void updateCallType(android.telephony.ims.ImsCallProfile);
method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
diff --git a/api/test-current.txt b/api/test-current.txt
index 8c710c1237c6..46cbb52f6efa 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -61,6 +61,7 @@ package android.app {
}
public class ActivityTaskManager {
+ method public void clearLaunchParamsForPackages(java.util.List<java.lang.String>);
method public java.lang.String listAllStacks();
method public void moveTaskToStack(int, int, boolean);
method public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect);
@@ -304,16 +305,11 @@ package android.content {
public abstract class Context {
method public android.content.Context createPackageContextAsUser(java.lang.String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
- method public abstract java.lang.String getOpPackageName();
method public android.os.UserHandle getUser();
method public int getUserId();
method public void setAutofillCompatibilityEnabled(boolean);
}
- public class ContextWrapper extends android.content.Context {
- method public java.lang.String getOpPackageName();
- }
-
}
package android.content.pm {
@@ -947,6 +943,10 @@ package android.os.health {
package android.os.storage {
+ public class StorageManager {
+ method public static boolean hasIsolatedStorage();
+ }
+
public final class StorageVolume implements android.os.Parcelable {
method public java.lang.String getPath();
}
@@ -1002,6 +1002,7 @@ package android.provider {
}
public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
+ method public static void resetToDefaults(android.content.ContentResolver, java.lang.String);
field public static final java.lang.String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED = "accessibility_display_magnification_enabled";
field public static final java.lang.String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE = "accessibility_shortcut_target_service";
field public static final java.lang.String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
@@ -1013,6 +1014,8 @@ package android.provider {
field public static final java.lang.String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
field public static final java.lang.String DISABLED_PRINT_SERVICES = "disabled_print_services";
field public static final deprecated java.lang.String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
+ field public static final java.lang.String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
+ field public static final java.lang.String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
field public static final java.lang.String SYNC_PARENT_SOUNDS = "sync_parent_sounds";
field public static final java.lang.String USER_SETUP_COMPLETE = "user_setup_complete";
field public static final java.lang.String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index 1c3ebd877695..b23c1eda87b3 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -24,6 +24,7 @@
#include "incidentd_util.h"
#include "section_list.h"
+#include <android/os/IncidentReportArgs.h>
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <binder/IServiceManager.h>
@@ -41,6 +42,15 @@ enum { WHAT_RUN_REPORT = 1, WHAT_SEND_BACKLOG_TO_DROPBOX = 2 };
#define DEFAULT_BYTES_SIZE_LIMIT (20 * 1024 * 1024) // 20MB
#define DEFAULT_REFACTORY_PERIOD_MS (24 * 60 * 60 * 1000) // 1 Day
+// Skip logs (1100 - 1108) because they are already in the bug report
+// Skip 1200, 1201, 1202, 3018 because they take too long
+// TODO(120079956): Skip 3008, 3015 because of error
+#define SKIPPED_SECTIONS { 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, /* Logs */ \
+ 1200, 1201, 1202, /* Native, hal, java traces */ \
+ 3008, /* "package --proto" */ \
+ 3015, /* "activity --proto processes" */ \
+ 3018 /* "meminfo -a --proto" */ }
+
namespace android {
namespace os {
namespace incidentd {
@@ -391,6 +401,38 @@ status_t IncidentService::cmd_privacy(FILE* in, FILE* out, FILE* err, Vector<Str
return NO_ERROR;
}
+status_t IncidentService::dump(int fd, const Vector<String16>& args) {
+ if (std::find(args.begin(), args.end(), String16("--proto")) == args.end()) {
+ ALOGD("Skip dumping incident. Only proto format is supported.");
+ dprintf(fd, "Incident dump only supports proto version.\n");
+ return NO_ERROR;
+ }
+
+ ALOGD("Dump incident proto");
+ IncidentReportArgs incidentArgs;
+ incidentArgs.setDest(DEST_EXPLICIT);
+ int skipped[] = SKIPPED_SECTIONS;
+ for (const Section** section = SECTION_LIST; *section; section++) {
+ const int id = (*section)->id;
+ if (std::find(std::begin(skipped), std::end(skipped), id) == std::end(skipped)) {
+ incidentArgs.addSection(id);
+ }
+ }
+
+ if (!checkIncidentPermissions(incidentArgs).isOk()) {
+ return PERMISSION_DENIED;
+ }
+
+ int fd1 = dup(fd);
+ if (fd1 < 0) {
+ return -errno;
+ }
+
+ mHandler->scheduleRunReport(new ReportRequest(incidentArgs, NULL, fd1));
+
+ return NO_ERROR;
+}
+
} // namespace incidentd
} // namespace os
} // namespace android
diff --git a/cmds/incidentd/src/IncidentService.h b/cmds/incidentd/src/IncidentService.h
index e176bfd95c5f..6252ad295224 100644
--- a/cmds/incidentd/src/IncidentService.h
+++ b/cmds/incidentd/src/IncidentService.h
@@ -112,6 +112,7 @@ public:
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) override;
virtual status_t command(FILE* in, FILE* out, FILE* err, Vector<String8>& args);
+ virtual status_t dump(int fd, const Vector<String16>& args);
private:
sp<ReportRequestQueue> mQueue;
diff --git a/cmds/incidentd/src/main.cpp b/cmds/incidentd/src/main.cpp
index 494882336611..098d74ecd786 100644
--- a/cmds/incidentd/src/main.cpp
+++ b/cmds/incidentd/src/main.cpp
@@ -45,7 +45,8 @@ int main(int /*argc*/, char** /*argv*/) {
// Create the service
sp<IncidentService> service = new IncidentService(looper);
- if (defaultServiceManager()->addService(String16("incident"), service) != 0) {
+ if (defaultServiceManager()->addService(String16("incident"), service, false,
+ IServiceManager::DUMP_FLAG_PRIORITY_NORMAL | IServiceManager::DUMP_FLAG_PROTO) != 0) {
ALOGE("Failed to add service");
return -1;
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index c8405a279f7d..41a202109713 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -2018,6 +2018,9 @@ message LmkKillOccurred {
// SWAP
optional int64 swap_in_bytes = 8;
+
+ // The elapsed real time of start of the process.
+ optional int64 process_start_time_nanos = 9;
}
/*
@@ -2543,10 +2546,7 @@ message ProcessMemoryState {
// SWAP
optional int64 swap_in_bytes = 8;
- // RSS high watermark.
- // Peak RSS usage of the process. Value is read from the VmHWM field in /proc/PID/status or
- // from memory.max_usage_in_bytes under /dev/memcg if the device uses per-app memory cgroups.
- // Deprecated: use ProcessMemoryHighWaterMark atom instead.
+ // Deprecated: use ProcessMemoryHighWaterMark atom instead. Always 0.
optional int64 rss_high_watermark_in_bytes = 9 [deprecated = true];
// Elapsed real time when the process started.
@@ -2573,9 +2573,7 @@ message NativeProcessMemoryState {
// RSS
optional int64 rss_in_bytes = 5;
- // RSS high watermark.
- // Peak RSS usage of the process. Value is read from the VmHWM field in /proc/PID/status.
- // Deprecated: use ProcessMemoryHighWaterMark atom instead.
+ // Deprecated: use ProcessMemoryHighWaterMark atom instead. Always 0.
optional int64 rss_high_watermark_in_bytes = 6 [deprecated = true];
// Elapsed real time when the process started.
@@ -3331,10 +3329,27 @@ message CpuTimePerThreadFreq {
optional string process_name = 4;
// Name of the thread taken from `/proc/$PID/task/$TID/comm`
optional string thread_name = 5;
- // What frequency the CPU was running at, in KHz
- optional int32 frequency_khz = 6;
- // Time spent in frequency in milliseconds, since thread start.
- optional int32 time_millis = 7;
+
+ // Report eight different frequencies, and how much time is spent in each frequency. Frequencies
+ // are given in KHz, and time is given in milliseconds since the thread started. All eight
+ // frequencies are given here as the alternative is sending eight separate atoms. This method
+ // significantly reduces the amount of data created
+ optional int32 frequency1_khz = 6;
+ optional int32 time1_millis = 7;
+ optional int32 frequency2_khz = 8;
+ optional int32 time2_millis = 9;
+ optional int32 frequency3_khz = 10;
+ optional int32 time3_millis = 11;
+ optional int32 frequency4_khz = 12;
+ optional int32 time4_millis = 13;
+ optional int32 frequency5_khz = 14;
+ optional int32 time5_millis = 15;
+ optional int32 frequency6_khz = 16;
+ optional int32 time6_millis = 17;
+ optional int32 frequency7_khz = 18;
+ optional int32 time7_millis = 19;
+ optional int32 frequency8_khz = 20;
+ optional int32 time8_millis = 21;
}
/**
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index f9b79823741b..c070ca375d74 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -210,7 +210,7 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
5 * NS_PER_SEC /* min cool-down in seconds*/,
new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
{android::util::CPU_TIME_PER_THREAD_FREQ,
- {{7},
+ {{7, 9, 11, 13, 15, 17, 19, 21},
1 * NS_PER_SEC,
new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}},
// DeviceCalculatedPowerUse.
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 661768914c69..3e5e82f7f4df 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -101,6 +101,7 @@ const int FIELD_ID_UID_MAP_DELETED_APPS = 4;
const std::map<int, std::pair<size_t, size_t>> StatsdStats::kAtomDimensionKeySizeLimitMap = {
{android::util::BINDER_CALLS, {6000, 10000}},
+ {android::util::LOOPER_STATS, {1500, 2500}},
{android::util::CPU_TIME_PER_UID_FREQ, {6000, 10000}},
};
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index b9732a596b2d..8d61aba432d4 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -679,7 +679,7 @@ float LogEvent::GetFloat(size_t key, status_t* err) const {
string LogEvent::ToString() const {
string result;
- result += StringPrintf("{ %lld %lld (%d)", (long long)mLogdTimestampNs,
+ result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
(long long)mElapsedTimestampNs, mTagId);
for (const auto& value : mValues) {
result +=
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 504c5864f2ec..f1310db03d45 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -343,9 +343,11 @@ void writeFieldValueTreeToStreamHelper(int tagId, const std::vector<FieldValue>&
}
}
if (isBytesField) {
- protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
- (const char*)dim.mValue.str_value.c_str(),
- dim.mValue.str_value.length());
+ if (dim.mValue.str_value.length() > 0) {
+ protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
+ (const char*)dim.mValue.str_value.c_str(),
+ dim.mValue.str_value.length());
+ }
} else {
protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
}
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index 90dfa87abeaa..3a5be43ed695 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -605,7 +605,44 @@ TEST(LogEventTest, TestBinaryFieldAtom) {
EXPECT_EQ(orig_str, result_str);
}
+TEST(LogEventTest, TestBinaryFieldAtom_empty) {
+ Atom launcherAtom;
+ auto launcher_event = launcherAtom.mutable_launcher_event();
+ launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
+ launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
+ launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
+
+ // empty string.
+ string extension_str;
+
+ LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
+
+ event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
+ event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
+ event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
+ event1.write(extension_str);
+ event1.init();
+
+ ProtoOutputStream proto;
+ event1.ToProto(proto);
+ std::vector<uint8_t> outData;
+ outData.resize(proto.size());
+ size_t pos = 0;
+ auto iter = proto.data();
+ while (iter.readBuffer() != NULL) {
+ size_t toRead = iter.currentToRead();
+ std::memcpy(&(outData[pos]), iter.readBuffer(), toRead);
+ pos += toRead;
+ iter.rp()->move(toRead);
+ }
+
+ std::string result_str(outData.begin(), outData.end());
+ std::string orig_str;
+ launcherAtom.SerializeToString(&orig_str);
+
+ EXPECT_EQ(orig_str, result_str);
+}
} // namespace statsd
} // namespace os
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index 8e9b91dab95d..f3bf6e7b7231 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -46,6 +46,10 @@ public final class Telecom extends BaseCommand {
private static final String COMMAND_SET_PHONE_ACCOUNT_DISABLED = "set-phone-account-disabled";
private static final String COMMAND_REGISTER_PHONE_ACCOUNT = "register-phone-account";
private static final String COMMAND_REGISTER_SIM_PHONE_ACCOUNT = "register-sim-phone-account";
+ private static final String COMMAND_SET_TEST_CALL_SCREENING_APP = "set-test-call-screening-app";
+ private static final String COMMAND_ADD_OR_REMOVE_CALL_COMPANION_APP =
+ "add-or-remove-call-companion-app";
+ private static final String COMMAND_SET_TEST_AUTO_MODE_APP = "set-test-auto-mode-app";
private static final String COMMAND_UNREGISTER_PHONE_ACCOUNT = "unregister-phone-account";
private static final String COMMAND_SET_DEFAULT_DIALER = "set-default-dialer";
private static final String COMMAND_GET_DEFAULT_DIALER = "get-default-dialer";
@@ -64,6 +68,9 @@ public final class Telecom extends BaseCommand {
"usage: telecom set-phone-account-enabled <COMPONENT> <ID> <USER_SN>\n" +
"usage: telecom set-phone-account-disabled <COMPONENT> <ID> <USER_SN>\n" +
"usage: telecom register-phone-account <COMPONENT> <ID> <USER_SN> <LABEL>\n" +
+ "usage: telecom set-test-call-screening-app <PACKAGE>\n" +
+ "usage: telecom set-test-auto-mode-app <PACKAGE>\n" +
+ "usage: telecom add-or-remove-call-companion-app <PACKAGE> <1/0>\n" +
"usage: telecom register-sim-phone-account <COMPONENT> <ID> <USER_SN> <LABEL> <ADDRESS>\n" +
"usage: telecom unregister-phone-account <COMPONENT> <ID> <USER_SN>\n" +
"usage: telecom set-default-dialer <PACKAGE>\n" +
@@ -113,6 +120,15 @@ public final class Telecom extends BaseCommand {
case COMMAND_REGISTER_PHONE_ACCOUNT:
runRegisterPhoneAccount();
break;
+ case COMMAND_SET_TEST_CALL_SCREENING_APP:
+ runSetTestCallScreeningApp();
+ break;
+ case COMMAND_ADD_OR_REMOVE_CALL_COMPANION_APP:
+ runAddOrRemoveCallCompanionApp();
+ break;
+ case COMMAND_SET_TEST_AUTO_MODE_APP:
+ runSetTestAutoModeApp();
+ break;
case COMMAND_REGISTER_SIM_PHONE_ACCOUNT:
runRegisterSimPhoneAccount();
break;
@@ -173,6 +189,23 @@ public final class Telecom extends BaseCommand {
System.out.println("Success - " + handle + " registered.");
}
+ private void runSetTestCallScreeningApp() throws RemoteException {
+ final String packageName = nextArg();
+ mTelecomService.setTestDefaultCallScreeningApp(packageName);
+ }
+
+ private void runAddOrRemoveCallCompanionApp() throws RemoteException {
+ final String packageName = nextArgRequired();
+ String isAdded = nextArgRequired();
+ boolean isAddedBool = "1".equals(isAdded);
+ mTelecomService.addOrRemoveTestCallCompanionApp(packageName, isAddedBool);
+ }
+
+ private void runSetTestAutoModeApp() throws RemoteException {
+ final String packageName = nextArg();
+ mTelecomService.setTestAutoModeApp(packageName);
+ }
+
private void runUnregisterPhoneAccount() throws RemoteException {
final PhoneAccountHandle handle = getPhoneAccountHandleFromArgs();
mTelecomService.unregisterPhoneAccount(handle);
diff --git a/config/hiddenapi-light-greylist.txt b/config/hiddenapi-light-greylist.txt
index 25bd0330ad5c..e10f72913d22 100644
--- a/config/hiddenapi-light-greylist.txt
+++ b/config/hiddenapi-light-greylist.txt
@@ -2695,7 +2695,6 @@ Lcom/android/internal/telephony/dataconnection/DcTracker;->onRecordsLoadedOrSubI
Lcom/android/internal/telephony/dataconnection/DcTracker;->onSetUserDataEnabled(Z)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Lcom/android/internal/telephony/dataconnection/ApnContext;)Z
Lcom/android/internal/telephony/dataconnection/DcTracker;->onTrySetupData(Ljava/lang/String;)Z
-Lcom/android/internal/telephony/dataconnection/DcTracker;->registerForAllDataDisconnected(Landroid/os/Handler;ILjava/lang/Object;)V
Lcom/android/internal/telephony/dataconnection/DcTracker;->registerSettingsObserver()V
Lcom/android/internal/telephony/dataconnection/DcTracker;->resetPollStats()V
Lcom/android/internal/telephony/dataconnection/DcTracker;->restartDataStallAlarm()V
@@ -2709,7 +2708,6 @@ Lcom/android/internal/telephony/dataconnection/DcTracker;->startNetStatPoll()V
Lcom/android/internal/telephony/dataconnection/DcTracker;->stopDataStallAlarm()V
Lcom/android/internal/telephony/dataconnection/DcTracker;->stopNetStatPoll()V
Lcom/android/internal/telephony/dataconnection/DcTracker;->unregisterForAllDataDisconnected(Landroid/os/Handler;)V
-Lcom/android/internal/telephony/dataconnection/DcTracker;->updateRecords()V
Lcom/android/internal/telephony/DctConstants$Activity;->DATAIN:Lcom/android/internal/telephony/DctConstants$Activity;
Lcom/android/internal/telephony/DctConstants$Activity;->DATAINANDOUT:Lcom/android/internal/telephony/DctConstants$Activity;
Lcom/android/internal/telephony/DctConstants$Activity;->DATAOUT:Lcom/android/internal/telephony/DctConstants$Activity;
@@ -3130,7 +3128,6 @@ Lcom/android/internal/telephony/ITelephony;->getCallState()I
Lcom/android/internal/telephony/ITelephony;->getDataActivity()I
Lcom/android/internal/telephony/ITelephony;->getDataState()I
Lcom/android/internal/telephony/ITelephony;->getNetworkType()I
-Lcom/android/internal/telephony/ITelephony;->getVoiceMessageCount()I
Lcom/android/internal/telephony/ITelephony;->handlePinMmi(Ljava/lang/String;)Z
Lcom/android/internal/telephony/ITelephony;->handlePinMmiForSubscriber(ILjava/lang/String;)Z
Lcom/android/internal/telephony/ITelephony;->hasIccCard()Z
@@ -3201,7 +3198,6 @@ Lcom/android/internal/telephony/Phone;->isVolteEnabled()Z
Lcom/android/internal/telephony/Phone;->isWifiCallingEnabled()Z
Lcom/android/internal/telephony/Phone;->mCi:Lcom/android/internal/telephony/CommandsInterface;
Lcom/android/internal/telephony/Phone;->mContext:Landroid/content/Context;
-Lcom/android/internal/telephony/Phone;->mDcTracker:Lcom/android/internal/telephony/dataconnection/DcTracker;
Lcom/android/internal/telephony/Phone;->mIccRecords:Ljava/util/concurrent/atomic/AtomicReference;
Lcom/android/internal/telephony/Phone;->mImsPhone:Lcom/android/internal/telephony/Phone;
Lcom/android/internal/telephony/Phone;->mMmiRegistrants:Landroid/os/RegistrantList;
@@ -3294,7 +3290,6 @@ Lcom/android/internal/telephony/ProxyController;->mOldRadioAccessFamily:[I
Lcom/android/internal/telephony/ProxyController;->mRadioCapabilitySessionId:I
Lcom/android/internal/telephony/ProxyController;->mSetRadioAccessFamilyStatus:[I
Lcom/android/internal/telephony/ProxyController;->mUniqueIdGenerator:Ljava/util/concurrent/atomic/AtomicInteger;
-Lcom/android/internal/telephony/ProxyController;->registerForAllDataDisconnected(ILandroid/os/Handler;ILjava/lang/Object;)V
Lcom/android/internal/telephony/ProxyController;->sendRadioCapabilityRequest(IIIILjava/lang/String;II)V
Lcom/android/internal/telephony/ProxyController;->sProxyController:Lcom/android/internal/telephony/ProxyController;
Lcom/android/internal/telephony/RadioCapability;->getRadioAccessFamily()I
@@ -3394,7 +3389,6 @@ Lcom/android/internal/telephony/ServiceStateTracker;->mVoiceRoamingOnRegistrants
Lcom/android/internal/telephony/ServiceStateTracker;->notifyDataRegStateRilRadioTechnologyChanged()V
Lcom/android/internal/telephony/ServiceStateTracker;->notifySignalStrength()Z
Lcom/android/internal/telephony/ServiceStateTracker;->pollState()V
-Lcom/android/internal/telephony/ServiceStateTracker;->powerOffRadioSafely(Lcom/android/internal/telephony/dataconnection/DcTracker;)V
Lcom/android/internal/telephony/ServiceStateTracker;->reRegisterNetwork(Landroid/os/Message;)V
Lcom/android/internal/telephony/ServiceStateTracker;->resetServiceStateInIwlanMode()V
Lcom/android/internal/telephony/ServiceStateTracker;->setOperatorIdd(Ljava/lang/String;)V
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 5940c45466fb..30959256c922 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -4117,6 +4117,10 @@ com.android.internal.util.StateMachine$SmHandler$StateInfo
com.android.internal.util.VirtualRefBasePtr
com.android.internal.util.XmlUtils
com.android.internal.util.XmlUtils$WriteMapCallback
+com.android.internal.util.function.NonaConsumer
+com.android.internal.util.function.NonaFunction
+com.android.internal.util.function.OctConsumer
+com.android.internal.util.function.OctFunction
com.android.internal.util.function.HeptConsumer
com.android.internal.util.function.HeptFunction
com.android.internal.util.function.HexConsumer
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 56ccf6f4a76f..6fdf7c8b4fac 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -433,4 +433,18 @@ public class ActivityTaskManager {
}
return sb.toString();
}
+
+ /**
+ * Clears launch params for the given package.
+ * @param packageNames the names of the packages of which the launch params are to be cleared
+ */
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+ public void clearLaunchParamsForPackages(List<String> packageNames) {
+ try {
+ getService().clearLaunchParamsForPackages(packageNames);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index c879db8967d3..446d98e97936 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -34,7 +34,9 @@ import android.view.InputDevice;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.Surface;
+import android.view.SurfaceControl;
import android.view.SurfaceHolder;
+import android.view.SurfaceSession;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -59,12 +61,16 @@ public class ActivityView extends ViewGroup {
private VirtualDisplay mVirtualDisplay;
private final SurfaceView mSurfaceView;
- private Surface mSurface;
+
+ /**
+ * This is the root surface for the VirtualDisplay. The VirtualDisplay child surfaces will be
+ * re-parented to this surface. This will also be a child of the SurfaceView's SurfaceControl.
+ */
+ private SurfaceControl mRootSurfaceControl;
private final SurfaceCallback mSurfaceCallback;
private StateCallback mActivityViewCallback;
- private IActivityManager mActivityManager;
private IActivityTaskManager mActivityTaskManager;
private IInputForwarder mInputForwarder;
// Temp container to store view coordinates on screen.
@@ -75,6 +81,9 @@ public class ActivityView extends ViewGroup {
private final CloseGuard mGuard = CloseGuard.get();
private boolean mOpened; // Protected by mGuard.
+ private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+ private Surface mTmpSurface = new Surface();
+
@UnsupportedAppUsage
public ActivityView(Context context) {
this(context, null /* attrs */);
@@ -87,7 +96,6 @@ public class ActivityView extends ViewGroup {
public ActivityView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- mActivityManager = ActivityManager.getService();
mActivityTaskManager = ActivityTaskManager.getService();
mSurfaceView = new SurfaceView(context);
mSurfaceCallback = new SurfaceCallback();
@@ -297,14 +305,19 @@ public class ActivityView extends ViewGroup {
private class SurfaceCallback implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
- mSurface = mSurfaceView.getHolder().getSurface();
+ mTmpSurface = new Surface();
if (mVirtualDisplay == null) {
- initVirtualDisplay();
+ initVirtualDisplay(new SurfaceSession(surfaceHolder.getSurface()));
if (mVirtualDisplay != null && mActivityViewCallback != null) {
mActivityViewCallback.onActivityViewReady(ActivityView.this);
}
} else {
- mVirtualDisplay.setSurface(surfaceHolder.getSurface());
+ // TODO (b/119209373): DisplayManager determines if a VirtualDisplay is on by
+ // whether it has a surface. Setting a fake surface here so DisplayManager will
+ // consider this display on.
+ mVirtualDisplay.setSurface(mTmpSurface);
+ mTmpTransaction.reparent(mRootSurfaceControl,
+ mSurfaceView.getSurfaceControl().getHandle()).apply();
}
updateLocation();
}
@@ -319,8 +332,8 @@ public class ActivityView extends ViewGroup {
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
- mSurface.release();
- mSurface = null;
+ mTmpSurface.release();
+ mTmpSurface = null;
if (mVirtualDisplay != null) {
mVirtualDisplay.setSurface(null);
}
@@ -328,7 +341,7 @@ public class ActivityView extends ViewGroup {
}
}
- private void initVirtualDisplay() {
+ private void initVirtualDisplay(SurfaceSession surfaceSession) {
if (mVirtualDisplay != null) {
throw new IllegalStateException("Trying to initialize for the second time.");
}
@@ -336,9 +349,13 @@ public class ActivityView extends ViewGroup {
final int width = mSurfaceView.getWidth();
final int height = mSurfaceView.getHeight();
final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+
+ // TODO (b/119209373): DisplayManager determines if a VirtualDisplay is on by
+ // whether it has a surface. Setting a fake surface here so DisplayManager will consider
+ // this display on.
mVirtualDisplay = displayManager.createVirtualDisplay(
DISPLAY_NAME + "@" + System.identityHashCode(this),
- width, height, getBaseDisplayDensity(), mSurface,
+ width, height, getBaseDisplayDensity(), mTmpSurface,
DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
| DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
if (mVirtualDisplay == null) {
@@ -348,11 +365,20 @@ public class ActivityView extends ViewGroup {
final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+
+ mRootSurfaceControl = new SurfaceControl.Builder(surfaceSession)
+ .setContainerLayer(true)
+ .setName(DISPLAY_NAME)
+ .build();
+
try {
+ wm.reparentDisplayContent(displayId, mRootSurfaceControl.getHandle());
wm.dontOverrideDisplayInfo(displayId);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
+
+ mTmpTransaction.show(mRootSurfaceControl).apply();
mInputForwarder = InputManager.getInstance().createInputForwarder(displayId);
mTaskStackListener = new TaskStackListenerImpl();
try {
@@ -392,9 +418,9 @@ public class ActivityView extends ViewGroup {
displayReleased = false;
}
- if (mSurface != null) {
- mSurface.release();
- mSurface = null;
+ if (mTmpSurface != null) {
+ mTmpSurface.release();
+ mTmpSurface = null;
}
if (displayReleased && mActivityViewCallback != null) {
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 09b77d5b8d0a..777a4949a132 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -445,4 +445,9 @@ interface IActivityTaskManager {
void setPackageScreenCompatMode(in String packageName, int mode);
boolean getPackageAskScreenCompat(in String packageName);
void setPackageAskScreenCompat(in String packageName, boolean ask);
+
+ /**
+ * Clears launch params for given packages.
+ */
+ void clearLaunchParamsForPackages(in List<String> packageNames);
}
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 00547b4a5ce4..3a2038d40952 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -159,5 +159,5 @@ interface IWallpaperManager {
/**
* Called from SystemUI when it shows the AoD UI.
*/
- oneway void setInAmbientMode(boolean inAmbientMode, boolean animated);
+ oneway void setInAmbientMode(boolean inAmbientMode, long animationDuration);
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5002a8125d44..0281e6a0631e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1693,11 +1693,30 @@ public class Notification implements Parcelable
}
/**
+ * Throws an NPE if we are building a contextual action missing one of the fields
+ * necessary to display the action.
+ */
+ private void checkContextualActionNullFields() {
+ if (mSemanticAction != SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION) return;
+
+ if (mIcon == null) {
+ throw new NullPointerException("Contextual Actions must contain a valid icon");
+ }
+
+ if (mIntent == null) {
+ throw new NullPointerException(
+ "Contextual Actions must contain a valid PendingIntent");
+ }
+ }
+
+ /**
* Combine all of the options that have been set and return a new {@link Action}
* object.
* @return the built action
*/
public Action build() {
+ checkContextualActionNullFields();
+
ArrayList<RemoteInput> dataOnlyInputs = new ArrayList<>();
RemoteInput[] previousDataInputs =
(RemoteInput[]) mExtras.getParcelableArray(EXTRA_DATA_ONLY_INPUTS);
@@ -3848,6 +3867,9 @@ public class Notification implements Parcelable
* The system UI may choose to display a heads-up notification, instead of
* launching this intent, while the user is using the device.
* </p>
+ * <p>Apps targeting {@link Build.VERSION_CODES#Q} and above will have to request
+ * a permission ({@link android.Manifest.permission#USE_FULL_SCREEN_INTENT}) in order to
+ * use full screen intents.</p>
*
* @param intent The pending intent to launch.
* @param highPriority Passing true will cause this notification to be sent
@@ -4449,6 +4471,14 @@ public class Notification implements Parcelable
}
}
+ private void bindAlertedIcon(RemoteViews contentView, StandardTemplateParams p) {
+ contentView.setDrawableTint(
+ R.id.alerted_icon,
+ false /* targetBackground */,
+ getNeutralColor(p),
+ PorterDuff.Mode.SRC_ATOP);
+ }
+
/**
* @hide
*/
@@ -4851,6 +4881,7 @@ public class Notification implements Parcelable
bindHeaderTextSecondary(contentView, p);
bindHeaderChronometerAndTime(contentView, p);
bindProfileBadge(contentView, p);
+ bindAlertedIcon(contentView, p);
}
bindActivePermissions(contentView, p);
bindExpandButton(contentView, p);
diff --git a/core/java/android/app/ProcessMemoryState.java b/core/java/android/app/ProcessMemoryState.java
index 9df4fff1e776..95d5d193c29a 100644
--- a/core/java/android/app/ProcessMemoryState.java
+++ b/core/java/android/app/ProcessMemoryState.java
@@ -32,13 +32,11 @@ public final class ProcessMemoryState implements Parcelable {
public final long rssInBytes;
public final long cacheInBytes;
public final long swapInBytes;
- // TODO(rslawik): Delete this field once ProcessMemoryHighWaterMark is ready.
- public final long rssHighWatermarkInBytes;
public final long startTimeNanos;
public ProcessMemoryState(int uid, String processName, int oomScore, long pgfault,
long pgmajfault, long rssInBytes, long cacheInBytes,
- long swapInBytes, long rssHighWatermarkInBytes, long startTimeNanos) {
+ long swapInBytes, long startTimeNanos) {
this.uid = uid;
this.processName = processName;
this.oomScore = oomScore;
@@ -47,7 +45,6 @@ public final class ProcessMemoryState implements Parcelable {
this.rssInBytes = rssInBytes;
this.cacheInBytes = cacheInBytes;
this.swapInBytes = swapInBytes;
- this.rssHighWatermarkInBytes = rssHighWatermarkInBytes;
this.startTimeNanos = startTimeNanos;
}
@@ -60,7 +57,6 @@ public final class ProcessMemoryState implements Parcelable {
rssInBytes = in.readLong();
cacheInBytes = in.readLong();
swapInBytes = in.readLong();
- rssHighWatermarkInBytes = in.readLong();
startTimeNanos = in.readLong();
}
@@ -91,7 +87,6 @@ public final class ProcessMemoryState implements Parcelable {
parcel.writeLong(rssInBytes);
parcel.writeLong(cacheInBytes);
parcel.writeLong(swapInBytes);
- parcel.writeLong(rssHighWatermarkInBytes);
parcel.writeLong(startTimeNanos);
}
}
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index 3ea3da25e2fc..f0f7d899ff07 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -16,6 +16,7 @@
package android.app;
+import android.annotation.SystemApi;
import android.app.slice.Slice;
import android.content.ComponentName;
import android.content.Context;
@@ -330,7 +331,9 @@ public final class WallpaperInfo implements Parcelable {
* @see WallpaperService.Engine#onAmbientModeChanged(boolean, boolean)
* @see WallpaperService.Engine#isInAmbientMode()
* @return {@code true} if wallpaper can draw when in ambient mode.
+ * @hide
*/
+ @SystemApi
public boolean supportsAmbientMode() {
return mSupportsAmbientMode;
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 27471cac10e9..27ae0b0314d0 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1898,23 +1898,33 @@ public class WallpaperManager {
* @hide
*/
public static ComponentName getDefaultWallpaperComponent(Context context) {
+ ComponentName cn = null;
+
String flat = SystemProperties.get(PROP_WALLPAPER_COMPONENT);
if (!TextUtils.isEmpty(flat)) {
- final ComponentName cn = ComponentName.unflattenFromString(flat);
- if (cn != null) {
- return cn;
+ cn = ComponentName.unflattenFromString(flat);
+ }
+
+ if (cn == null) {
+ flat = context.getString(com.android.internal.R.string.default_wallpaper_component);
+ if (!TextUtils.isEmpty(flat)) {
+ cn = ComponentName.unflattenFromString(flat);
}
}
- flat = context.getString(com.android.internal.R.string.default_wallpaper_component);
- if (!TextUtils.isEmpty(flat)) {
- final ComponentName cn = ComponentName.unflattenFromString(flat);
- if (cn != null) {
- return cn;
+ // Check if the package exists
+ if (cn != null) {
+ try {
+ final PackageManager packageManager = context.getPackageManager();
+ packageManager.getPackageInfo(cn.getPackageName(),
+ PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
+ } catch (PackageManager.NameNotFoundException e) {
+ cn = null;
}
}
- return null;
+ return cn;
}
/**
diff --git a/core/java/android/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
index 1c9a43acfa65..673d85fe79c5 100644
--- a/core/java/android/app/backup/OWNERS
+++ b/core/java/android/app/backup/OWNERS
@@ -1,7 +1,6 @@
-artikz@google.com
+anniemeng@google.com
brufino@google.com
bryanmawhinney@google.com
ctate@google.com
jorlow@google.com
-mkarpinski@google.com
diff --git a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
index 237082e4cb66..2f0b44f76ffb 100644
--- a/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
+++ b/core/java/android/bluetooth/BluetoothHidDeviceAppSdpSettings.java
@@ -18,6 +18,7 @@ package android.bluetooth;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.EventLog;
/**
@@ -30,6 +31,8 @@ import android.os.Parcelable;
*/
public final class BluetoothHidDeviceAppSdpSettings implements Parcelable {
+ private static final int MAX_DESCRIPTOR_SIZE = 2048;
+
private final String mName;
private final String mDescription;
private final String mProvider;
@@ -55,6 +58,12 @@ public final class BluetoothHidDeviceAppSdpSettings implements Parcelable {
mDescription = description;
mProvider = provider;
mSubclass = subclass;
+
+ if (descriptors == null || descriptors.length > MAX_DESCRIPTOR_SIZE) {
+ EventLog.writeEvent(0x534e4554, "119819889", -1, "");
+ throw new IllegalArgumentException("descriptors must be not null and shorter than "
+ + MAX_DESCRIPTOR_SIZE);
+ }
mDescriptors = descriptors.clone();
}
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 11f8ab7551c2..e3672a7e064f 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -52,8 +52,7 @@ import java.util.List;
@RequiresFeature(PackageManager.FEATURE_BLUETOOTH)
public final class BluetoothManager {
private static final String TAG = "BluetoothManager";
- private static final boolean DBG = true;
- private static final boolean VDBG = true;
+ private static final boolean DBG = false;
private final BluetoothAdapter mAdapter;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 437039dcbccf..7d5202d0dbce 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -97,8 +97,7 @@ public abstract class ContentResolver {
*
* @hide
*/
- public static final boolean DEPRECATE_DATA_COLUMNS = SystemProperties
- .getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false);
+ public static final boolean DEPRECATE_DATA_COLUMNS = StorageManager.hasIsolatedStorage();
/**
* Special filesystem path prefix which indicates that a path should be
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index cec8ef59b961..ff57b0311d60 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -741,16 +741,22 @@ public abstract class Context {
/** Return the name of this application's package. */
public abstract String getPackageName();
- /** @hide Return the name of the base context this context is derived from. */
+ /**
+ * @hide Return the name of the base context this context is derived from.
+ * This is the same as {@link #getOpPackageName()} except in
+ * cases where system components are loaded into other app processes, in which
+ * case {@link #getOpPackageName()} will be the name of the primary package in
+ * that process (so that app ops uid verification will work with the name).
+ */
@UnsupportedAppUsage
public abstract String getBasePackageName();
- /** @hide Return the package name that should be used for app ops calls from
- * this context. This is the same as {@link #getBasePackageName()} except in
- * cases where system components are loaded into other app processes, in which
- * case this will be the name of the primary package in that process (so that app
- * ops uid verification will work with the name). */
- @TestApi
+ /**
+ * Return the package name that should be used for {@link android.app.AppOpsManager} calls from
+ * this context, so that app ops manager's uid verification will work with the name.
+ * <p>
+ * This is not generally intended for third party application developers.
+ */
public abstract String getOpPackageName();
/** Return the full application info for this context's package. */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6fd5061eee63..edfb3a72e933 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1757,33 +1757,6 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.MANAGE_APP_PERMISSIONS";
/**
- * Activity action: Launch UI to manage a specific permissions of an app.
- * <p>
- * Input: {@link #EXTRA_PACKAGE_NAME} specifies the package whose permission
- * will be managed by the launched UI.
- * </p>
- * <p>
- * Input: {@link #EXTRA_PERMISSION_NAME} specifies the (individual) permission
- * that should be managed by the launched UI.
- * </p>
- * <p>
- * <li> {@link #EXTRA_USER} specifies the UserHandle of the user that owns the app.
- * </p>
- * <p>
- * Output: Nothing.
- * </p>
- *
- * @see #EXTRA_PACKAGE_NAME
- * @see #EXTRA_PERMISSION_NAME
- *
- * @hide
- */
- @SystemApi
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_MANAGE_APP_PERMISSION =
- "android.intent.action.MANAGE_APP_PERMISSION";
-
- /**
* Activity action: Launch UI to manage permissions.
* <p>
* Input: Nothing.
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index ecdd810653ec..099d15ad61c2 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -22,6 +22,9 @@ import android.apex.ApexInfo;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Overall information about the contents of a package. This corresponds
* to all of the information collected from AndroidManifest.xml.
@@ -204,7 +207,10 @@ public class PackageInfo implements Parcelable {
* {@link PackageManager#GET_PERMISSIONS} was set. This list includes
* all permissions requested, even those that were not granted or known
* by the system at install time.
+ *
+ * @deprecated Use {@link #usesPermissions}
*/
+ @Deprecated
public String[] requestedPermissions;
/**
@@ -214,10 +220,23 @@ public class PackageInfo implements Parcelable {
* {@link PackageManager#GET_PERMISSIONS} was set. Each value matches
* the corresponding entry in {@link #requestedPermissions}, and will have
* the flag {@link #REQUESTED_PERMISSION_GRANTED} set as appropriate.
+ *
+ * @deprecated Use {@link #usesPermissions}
*/
+ @Deprecated
public int[] requestedPermissionsFlags;
/**
+ * Array of all {@link android.R.styleable#AndroidManifestUsesPermission
+ * &lt;uses-permission&gt;} tags included under &lt;manifest&gt;,
+ * or null if there were none. This is only filled in if the flag
+ * {@link PackageManager#GET_PERMISSIONS} was set. This list includes
+ * all permissions requested, even those that were not granted or known
+ * by the system at install time.
+ */
+ public UsesPermissionInfo[] usesPermissions;
+
+ /**
* Flag for {@link #requestedPermissionsFlags}: the requested permission
* is required for the application to run; the user can not optionally
* disable it. Currently all permissions are required.
@@ -456,6 +475,7 @@ public class PackageInfo implements Parcelable {
dest.writeTypedArray(permissions, parcelableFlags);
dest.writeStringArray(requestedPermissions);
dest.writeIntArray(requestedPermissionsFlags);
+ dest.writeTypedArray(usesPermissions, parcelableFlags);
dest.writeTypedArray(signatures, parcelableFlags);
dest.writeTypedArray(configPreferences, parcelableFlags);
dest.writeTypedArray(reqFeatures, parcelableFlags);
@@ -520,6 +540,7 @@ public class PackageInfo implements Parcelable {
permissions = source.createTypedArray(PermissionInfo.CREATOR);
requestedPermissions = source.createStringArray();
requestedPermissionsFlags = source.createIntArray();
+ usesPermissions = source.createTypedArray(UsesPermissionInfo.CREATOR);
signatures = source.createTypedArray(Signature.CREATOR);
configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 6421dc5a3f68..b7df2bf5a5f7 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5372,6 +5372,10 @@ public abstract class PackageManager {
public abstract void removePackageFromPreferred(String packageName);
/**
+ * @deprecated This function no longer does anything; it was an old
+ * approach to managing preferred activities, which has been superseded
+ * by (and conflicts with) the modern activity-based preferences.
+ *
* Retrieve the list of all currently configured preferred packages. The
* first package on the list is the most preferred, the last is the least
* preferred.
@@ -5380,6 +5384,7 @@ public abstract class PackageManager {
* @return A List of PackageInfo objects, one for each preferred
* application, in order of preference.
*/
+ @Deprecated
public abstract List<PackageInfo> getPreferredPackages(@PackageInfoFlags int flags);
/**
@@ -5406,11 +5411,16 @@ public abstract class PackageManager {
ComponentName[] set, ComponentName activity);
/**
+ * @deprecated This is a protected API that should not have been available
+ * to third party applications. It is the platform's responsibility for
+ * assigning preferred activities and this cannot be directly modified.
+ *
* Same as {@link #addPreferredActivity(IntentFilter, int,
ComponentName[], ComponentName)}, but with a specific userId to apply the preference
to.
* @hide
*/
+ @Deprecated
@UnsupportedAppUsage
public void addPreferredActivityAsUser(IntentFilter filter, int match,
ComponentName[] set, ComponentName activity, @UserIdInt int userId) {
@@ -5444,6 +5454,10 @@ public abstract class PackageManager {
ComponentName[] set, ComponentName activity);
/**
+ * @deprecated This is a protected API that should not have been available
+ * to third party applications. It is the platform's responsibility for
+ * assigning preferred activities and this cannot be directly modified.
+ *
* Replaces an existing preferred activity mapping to the system, and if that were not present
* adds a new preferred activity. This will be used to automatically select the given activity
* component when {@link Context#startActivity(Intent) Context.startActivity()} finds multiple
@@ -5459,6 +5473,7 @@ public abstract class PackageManager {
*
* @hide
*/
+ @Deprecated
@SystemApi
public void replacePreferredActivity(@NonNull IntentFilter filter, int match,
@NonNull List<ComponentName> set, @NonNull ComponentName activity) {
@@ -5476,6 +5491,10 @@ public abstract class PackageManager {
}
/**
+ * @deprecated This function no longer does anything; it was an old
+ * approach to managing preferred activities, which has been superseded
+ * by (and conflicts with) the modern activity-based preferences.
+ *
* Remove all preferred activity mappings, previously added with
* {@link #addPreferredActivity}, from the
* system whose activities are implemented in the given package name.
@@ -5484,9 +5503,14 @@ public abstract class PackageManager {
* @param packageName The name of the package whose preferred activity
* mappings are to be removed.
*/
+ @Deprecated
public abstract void clearPackagePreferredActivities(String packageName);
/**
+ * @deprecated This function no longer does anything; it was an old
+ * approach to managing preferred activities, which has been superseded
+ * by (and conflicts with) the modern activity-based preferences.
+ *
* Retrieve all preferred activities, previously added with
* {@link #addPreferredActivity}, that are
* currently registered with the system.
@@ -5503,6 +5527,7 @@ public abstract class PackageManager {
* (the number of distinct IntentFilter records, not the number of unique
* activity components) that were found.
*/
+ @Deprecated
public abstract int getPreferredActivities(@NonNull List<IntentFilter> outFilters,
@NonNull List<ComponentName> outActivities, String packageName);
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 6f49cc42f6f6..b49c4476e82d 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -28,6 +28,7 @@ import android.content.pm.PackageManager.PackageInfoFlags;
import android.content.pm.PackageManager.ResolveInfoFlags;
import android.os.Bundle;
import android.os.PersistableBundle;
+import android.util.ArraySet;
import android.util.SparseArray;
import com.android.internal.util.function.TriFunction;
@@ -37,6 +38,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.function.BiFunction;
+import java.util.function.Consumer;
/**
* Package manager local system service interface.
@@ -735,4 +737,22 @@ public abstract class PackageManagerInternal {
/** Returns {@code true} if the given user requires extra badging for icons. */
public abstract boolean userNeedsBadging(int userId);
+
+ /**
+ * Perform the given action for each package.
+ * Note that packages lock will be held while performin the actions.
+ *
+ * @param actionLocked action to be performed
+ */
+ public abstract void forEachPackage(Consumer<PackageParser.Package> actionLocked);
+
+ /** Returns the list of enabled components */
+ public abstract ArraySet<String> getEnabledComponents(String packageName, int userId);
+
+ /** Returns the list of disabled components */
+ public abstract ArraySet<String> getDisabledComponents(String packageName, int userId);
+
+ /** Returns whether the given package is enabled for the given user */
+ public abstract @PackageManager.EnabledState int getApplicationEnabledState(
+ String packageName, int userId);
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index d00c9a036a53..ac18dca74950 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -785,18 +785,23 @@ public class PackageParser {
pi.permissions[i] = generatePermissionInfo(p.permissions.get(i), flags);
}
}
- N = p.requestedPermissions.size();
+ N = p.usesPermissionInfos.size();
if (N > 0) {
pi.requestedPermissions = new String[N];
pi.requestedPermissionsFlags = new int[N];
+ pi.usesPermissions = new UsesPermissionInfo[N];
for (int i=0; i<N; i++) {
- final String perm = p.requestedPermissions.get(i);
+ UsesPermissionInfo info = p.usesPermissionInfos.get(i);
+ final String perm = info.getPermission();
pi.requestedPermissions[i] = perm;
+ int permissionFlags = 0;
// The notion of required permissions is deprecated but for compatibility.
- pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
+ permissionFlags |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
if (grantedPermissions != null && grantedPermissions.contains(perm)) {
- pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
+ permissionFlags |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
}
+ pi.requestedPermissionsFlags[i] = permissionFlags;
+ pi.usesPermissions[i] = new UsesPermissionInfo(info, permissionFlags);
}
}
}
@@ -2114,12 +2119,12 @@ public class PackageParser {
return null;
}
} else if (tagName.equals(TAG_USES_PERMISSION)) {
- if (!parseUsesPermission(pkg, res, parser)) {
+ if (!parseUsesPermission(pkg, res, parser, outError)) {
return null;
}
} else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
|| tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
- if (!parseUsesPermission(pkg, res, parser)) {
+ if (!parseUsesPermission(pkg, res, parser, outError)) {
return null;
}
} else if (tagName.equals(TAG_USES_CONFIGURATION)) {
@@ -2442,7 +2447,7 @@ public class PackageParser {
newPermsMsg.append(' ');
}
newPermsMsg.append(npi.name);
- pkg.requestedPermissions.add(npi.name);
+ addRequestedPermission(pkg, npi.name);
pkg.implicitPermissions.add(npi.name);
}
}
@@ -2463,7 +2468,7 @@ public class PackageParser {
for (int in = 0; in < newPerms.size(); in++) {
final String perm = newPerms.get(in);
if (!pkg.requestedPermissions.contains(perm)) {
- pkg.requestedPermissions.add(perm);
+ addRequestedPermission(pkg, perm);
pkg.implicitPermissions.add(perm);
}
}
@@ -2508,7 +2513,7 @@ public class PackageParser {
// If the storage model feature flag is disabled, we need to fiddle
// around with permission definitions to return us to pre-Q behavior.
// STOPSHIP(b/112545973): remove once feature enabled by default
- if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+ if (!StorageManager.hasIsolatedStorage()) {
if ("android".equals(pkg.packageName)) {
final ArraySet<String> newGroups = new ArraySet<>();
newGroups.add(android.Manifest.permission_group.MEDIA_AURAL);
@@ -2543,13 +2548,13 @@ public class PackageParser {
}
} else {
if (FORCE_AUDIO_PACKAGES.contains(pkg.packageName)) {
- pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO);
+ addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_AUDIO);
}
if (FORCE_VIDEO_PACKAGES.contains(pkg.packageName)) {
- pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO);
+ addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_VIDEO);
}
if (FORCE_IMAGES_PACKAGES.contains(pkg.packageName)) {
- pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES);
+ addRequestedPermission(pkg, android.Manifest.permission.READ_MEDIA_IMAGES);
}
}
@@ -2589,6 +2594,14 @@ public class PackageParser {
}
/**
+ * Helper method for adding a requested permission to a package outside of a uses-permission.
+ */
+ private void addRequestedPermission(Package pkg, String permission) {
+ pkg.requestedPermissions.add(permission);
+ pkg.usesPermissionInfos.add(new UsesPermissionInfo(permission));
+ }
+
+ /**
* Computes the targetSdkVersion to use at runtime. If the package is not
* compatible with this platform, populates {@code outError[0]} with an
* error message.
@@ -2845,8 +2858,8 @@ public class PackageParser {
return certSha256Digests;
}
- private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser)
- throws XmlPullParserException, IOException {
+ private boolean parseUsesPermission(Package pkg, Resources res, XmlResourceParser parser,
+ String[] outError) throws XmlPullParserException, IOException {
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestUsesPermission);
@@ -2870,6 +2883,44 @@ public class PackageParser {
final String requiredNotfeature = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestUsesPermission_requiredNotFeature, 0);
+ int dataSentOffDevice = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSentOffDevice, 0);
+
+ int dataSharedWithThirdParty = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataSharedWithThirdParty, 0);
+
+ int dataUsedForMonetization = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataUsedForMonetization, 0);
+
+ int retentionWeeks = -1;
+ int retention;
+
+ String rawRetention = sa.getString(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime);
+
+ if (rawRetention == null) {
+ retention = UsesPermissionInfo.RETENTION_UNDEFINED;
+ } else if ("notRetained".equals(rawRetention)) {
+ retention = UsesPermissionInfo.RETENTION_NOT_RETAINED;
+ } else if ("userSelected".equals(rawRetention)) {
+ retention = UsesPermissionInfo.RETENTION_USER_SELECTED;
+ } else if ("unlimited".equals(rawRetention)) {
+ retention = UsesPermissionInfo.RETENTION_UNLIMITED;
+ } else {
+ // A number of weeks was specified
+ retention = UsesPermissionInfo.RETENTION_SPECIFIED;
+ retentionWeeks = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestUsesPermission_dataRetentionTime,
+ -1);
+
+ if (retentionWeeks < 0) {
+ outError[0] = "Bad value provided for dataRetentionTime.";
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ XmlUtils.skipCurrentTag(parser);
+ sa.recycle();
+ return false;
+ }
+ }
sa.recycle();
XmlUtils.skipCurrentTag(parser);
@@ -2902,6 +2953,10 @@ public class PackageParser {
+ parser.getPositionDescription());
}
+ UsesPermissionInfo info = new UsesPermissionInfo(name, dataSentOffDevice,
+ dataSharedWithThirdParty, dataUsedForMonetization, retention, retentionWeeks);
+ pkg.usesPermissionInfos.add(info);
+
return true;
}
@@ -3236,6 +3291,10 @@ public class PackageParser {
perm.info.flags = sa.getInt(
com.android.internal.R.styleable.AndroidManifestPermission_permissionFlags, 0);
+ perm.info.usageInfoRequired = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestPermission_usageInfoRequired, 0)
+ != 0;
+
sa.recycle();
if (perm.info.protectionLevel == -1) {
@@ -6370,6 +6429,9 @@ public class PackageParser {
@UnsupportedAppUsage
public final ArrayList<String> requestedPermissions = new ArrayList<String>();
+ public final ArrayList<UsesPermissionInfo> usesPermissionInfos =
+ new ArrayList<>();
+
/** Permissions requested but not in the manifest. */
public final ArrayList<String> implicitPermissions = new ArrayList<>();
@@ -6900,6 +6962,7 @@ public class PackageParser {
dest.readStringList(requestedPermissions);
internStringArrayList(requestedPermissions);
+ dest.readParcelableList(usesPermissionInfos, boot);
dest.readStringList(implicitPermissions);
internStringArrayList(implicitPermissions);
protectedBroadcasts = dest.createStringArrayList();
@@ -7066,6 +7129,7 @@ public class PackageParser {
dest.writeParcelableList(instrumentation, flags);
dest.writeStringList(requestedPermissions);
+ dest.writeParcelableList(usesPermissionInfos, flags);
dest.writeStringList(implicitPermissions);
dest.writeStringList(protectedBroadcasts);
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index e21c33ad3bc1..be6ed51e3c89 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -21,7 +21,6 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
@@ -130,9 +129,6 @@ public class PackageUserState {
* </p>
*/
public boolean isMatch(ComponentInfo componentInfo, int flags) {
- if ((flags & MATCH_ALL) != 0) {
- return true;
- }
final boolean isSystemApp = componentInfo.applicationInfo.isSystemApp();
final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0;
if (!isAvailable(flags)
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 60c06a1e4d87..d9d6b5f87eac 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -308,6 +309,12 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
*/
public CharSequence nonLocalizedDescription;
+ /**
+ * If {@code true} an application targeting {@link Build.VERSION_CODES#Q} <em>must</em>
+ * include permission data usage information in order to be able to be granted this permission.
+ */
+ public boolean usageInfoRequired;
+
/** @hide */
public static int fixProtectionLevel(int level) {
if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
@@ -394,6 +401,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
descriptionRes = orig.descriptionRes;
requestRes = orig.requestRes;
nonLocalizedDescription = orig.nonLocalizedDescription;
+ usageInfoRequired = orig.usageInfoRequired;
}
/**
@@ -458,6 +466,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
dest.writeInt(descriptionRes);
dest.writeInt(requestRes);
TextUtils.writeToParcel(nonLocalizedDescription, dest, parcelableFlags);
+ dest.writeInt(usageInfoRequired ? 1 : 0);
}
/** @hide */
@@ -498,5 +507,6 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {
descriptionRes = source.readInt();
requestRes = source.readInt();
nonLocalizedDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+ usageInfoRequired = source.readInt() != 0;
}
}
diff --git a/core/java/android/content/pm/UsesPermissionInfo.java b/core/java/android/content/pm/UsesPermissionInfo.java
new file mode 100644
index 000000000000..d08548fa31a5
--- /dev/null
+++ b/core/java/android/content/pm/UsesPermissionInfo.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.annotation.IntDef;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.RetentionPolicy;
+/**
+ * Information you can retrive about a particular application requested permission. This
+ * corresponds to information collected from the AndroidManifest.xml's &lt;uses-permission&gt;
+ * tags.
+ */
+public final class UsesPermissionInfo extends PackageItemInfo implements Parcelable {
+
+ /**
+ * Flag for {@link #getFlags()}: the requested permission is currently granted to the
+ * application.
+ */
+ public static final int FLAG_REQUESTED_PERMISSION_GRANTED = 1 << 1;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = {"FLAG_"}, value = {FLAG_REQUESTED_PERMISSION_GRANTED})
+ @java.lang.annotation.Retention(RetentionPolicy.SOURCE)
+ public @interface Flags {}
+
+ /** An unset value for {@link #getDataSentOffDevice()},
+ * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()}
+ */
+ public static final int USAGE_UNDEFINED = 0;
+
+ /**
+ * A yes value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()},
+ * and {@link #getDataUsedForMonetization()} corresponding to the <code>yes</code> value of
+ * {@link android.R.attr#dataSentOffDevice}, {@link android.R.attr#dataSharedWithThirdParty},
+ * and {@link android.R.attr#dataUsedForMonetization} attributes.
+ */
+ public static final int USAGE_YES = 1;
+
+ /**
+ * A user triggered only value for {@link #getDataSentOffDevice()},
+ * {@link #getDataSharedWithThirdParty()}, and {@link #getDataUsedForMonetization()}
+ * corresponding to the <code>userTriggered</code> value of
+ * {@link android.R.attr#dataSentOffDevice}, {@link android.R.attr#dataSharedWithThirdParty},
+ * and {@link android.R.attr#dataUsedForMonetization} attributes.
+ */
+ public static final int USAGE_USER_TRIGGERED = 2;
+
+ /**
+ * A no value for {@link #getDataSentOffDevice()}, {@link #getDataSharedWithThirdParty()},
+ * and {@link #getDataUsedForMonetization()} corresponding to the <code>no</code> value of
+ * {@link android.R.attr#dataSentOffDevice}, {@link android.R.attr#dataSharedWithThirdParty},
+ * and {@link android.R.attr#dataUsedForMonetization} attributes.
+ */
+ public static final int USAGE_NO = 3;
+
+ /** @hide */
+ @IntDef(prefix = {"USAGE_"}, value = {
+ USAGE_UNDEFINED,
+ USAGE_YES,
+ USAGE_USER_TRIGGERED,
+ USAGE_NO})
+ @java.lang.annotation.Retention(RetentionPolicy.SOURCE)
+ public @interface Usage {}
+
+ /**
+ * An unset value for {@link #getDataRetention}.
+ */
+ public static final int RETENTION_UNDEFINED = 0;
+
+ /**
+ * A data not retained value for {@link #getDataRetention()} corresponding to the
+ * <code>notRetained</code> value of {@link android.R.attr#dataRetentionTime}.
+ */
+ public static final int RETENTION_NOT_RETAINED = 1;
+
+ /**
+ * A user selected value for {@link #getDataRetention()} corresponding to the
+ * <code>userSelected</code> value of {@link android.R.attr#dataRetentionTime}.
+ */
+ public static final int RETENTION_USER_SELECTED = 2;
+
+ /**
+ * An unlimited value for {@link #getDataRetention()} corresponding to the
+ * <code>unlimited</code> value of {@link android.R.attr#dataRetentionTime}.
+ */
+ public static final int RETENTION_UNLIMITED = 3;
+
+ /**
+ * A specified value for {@link #getDataRetention()} corresponding to providing the number of
+ * weeks data is retained in {@link android.R.attr#dataRetentionTime}. The number of weeks
+ * is available in {@link #getDataRetentionWeeks()}.
+ */
+ public static final int RETENTION_SPECIFIED = 4;
+
+ /** @hide */
+ @IntDef(prefix = {"RETENTION_"}, value = {
+ RETENTION_UNDEFINED,
+ RETENTION_NOT_RETAINED,
+ RETENTION_USER_SELECTED,
+ RETENTION_UNLIMITED,
+ RETENTION_SPECIFIED})
+ @java.lang.annotation.Retention(RetentionPolicy.SOURCE)
+ public @interface Retention {}
+
+ private final String mPermission;
+ private final @Flags int mFlags;
+ private final @Usage int mDataSentOffDevice;
+ private final @Usage int mDataSharedWithThirdParty;
+ private final @Usage int mDataUsedForMonetization;
+ private final @Retention int mDataRetention;
+ private final int mDataRetentionWeeks;
+
+ /** @hide */
+ public UsesPermissionInfo(String permission) {
+ mPermission = permission;
+ mDataSentOffDevice = USAGE_UNDEFINED;
+ mDataSharedWithThirdParty = USAGE_UNDEFINED;
+ mDataUsedForMonetization = USAGE_UNDEFINED;
+ mDataRetention = RETENTION_UNDEFINED;
+ mDataRetentionWeeks = -1;
+ mFlags = 0;
+ }
+
+ /** @hide */
+ public UsesPermissionInfo(String permission,
+ @Usage int dataSentOffDevice, @Usage int dataSharedWithThirdParty,
+ @Usage int dataUsedForMonetization, @Retention int dataRetention,
+ int dataRetentionWeeks) {
+ mPermission = permission;
+ mDataSentOffDevice = dataSentOffDevice;
+ mDataSharedWithThirdParty = dataSharedWithThirdParty;
+ mDataUsedForMonetization = dataUsedForMonetization;
+ mDataRetention = dataRetention;
+ mDataRetentionWeeks = dataRetentionWeeks;
+ mFlags = 0;
+ }
+
+ /** @hide */
+ public UsesPermissionInfo(UsesPermissionInfo orig) {
+ this(orig, orig.mFlags);
+ }
+
+ /** @hide */
+ public UsesPermissionInfo(UsesPermissionInfo orig, int flags) {
+ super(orig);
+ mPermission = orig.mPermission;
+ mFlags = flags;
+ mDataSentOffDevice = orig.mDataSentOffDevice;
+ mDataSharedWithThirdParty = orig.mDataSharedWithThirdParty;
+ mDataUsedForMonetization = orig.mDataUsedForMonetization;
+ mDataRetention = orig.mDataRetention;
+ mDataRetentionWeeks = orig.mDataRetentionWeeks;
+ }
+
+ /**
+ * The name of the requested permission.
+ */
+ public String getPermission() {
+ return mPermission;
+ }
+
+ public @Flags int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * If the application sends the data guarded by this permission off the device.
+ *
+ * See {@link android.R.attr#dataSentOffDevice}
+ */
+ public @Usage int getDataSentOffDevice() {
+ return mDataSentOffDevice;
+ }
+
+ /**
+ * If the application or its services shares the data guarded by this permission with third
+ * parties.
+ *
+ * See {@link android.R.attr#dataSharedWithThirdParty}
+ */
+ public @Usage int getDataSharedWithThirdParty() {
+ return mDataSharedWithThirdParty;
+ }
+
+ /**
+ * If the application or its services use the data guarded by this permission for monetization
+ * purposes.
+ *
+ * See {@link android.R.attr#dataUsedForMonetization}
+ */
+ public @Usage int getDataUsedForMonetization() {
+ return mDataUsedForMonetization;
+ }
+
+ /**
+ * How long the application or its services store the data guarded by this permission.
+ * If set to {@link #RETENTION_SPECIFIED} {@link #getDataRetentionWeeks()} will contain the
+ * number of weeks the data is stored.
+ *
+ * See {@link android.R.attr#dataRetentionTime}
+ */
+ public @Retention int getDataRetention() {
+ return mDataRetention;
+ }
+
+ /**
+ * If {@link #getDataRetention()} is {@link #RETENTION_SPECIFIED} the number of weeks the
+ * application or its services store data guarded by this permission.
+ *
+ * @throws IllegalStateException if {@link #getDataRetention} is not
+ * {@link #RETENTION_SPECIFIED}.
+ */
+ public int getDataRetentionWeeks() {
+ if (mDataRetention != RETENTION_SPECIFIED) {
+ throw new IllegalStateException("Data retention weeks not specified");
+ }
+ return mDataRetentionWeeks;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(mPermission);
+ dest.writeInt(mFlags);
+ dest.writeInt(mDataSentOffDevice);
+ dest.writeInt(mDataSharedWithThirdParty);
+ dest.writeInt(mDataUsedForMonetization);
+ dest.writeInt(mDataRetention);
+ dest.writeInt(mDataRetentionWeeks);
+ }
+
+ private UsesPermissionInfo(Parcel source) {
+ super(source);
+ mPermission = source.readString();
+ mFlags = source.readInt();
+ mDataSentOffDevice = source.readInt();
+ mDataSharedWithThirdParty = source.readInt();
+ mDataUsedForMonetization = source.readInt();
+ mDataRetention = source.readInt();
+ mDataRetentionWeeks = source.readInt();
+ }
+
+ public static final Creator<UsesPermissionInfo> CREATOR =
+ new Creator<UsesPermissionInfo>() {
+ @Override
+ public UsesPermissionInfo createFromParcel(Parcel source) {
+ return new UsesPermissionInfo(source);
+ }
+ @Override
+ public UsesPermissionInfo[] newArray(int size) {
+ return new UsesPermissionInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/hardware/biometrics/BiometricAuthenticator.java b/core/java/android/hardware/biometrics/BiometricAuthenticator.java
index 79e15a7a9a2d..0ec812fe0350 100644
--- a/core/java/android/hardware/biometrics/BiometricAuthenticator.java
+++ b/core/java/android/hardware/biometrics/BiometricAuthenticator.java
@@ -30,19 +30,29 @@ import java.util.concurrent.Executor;
public interface BiometricAuthenticator {
/**
+ * No biometric methods or nothing has been enrolled.
+ * Move/expose these in BiometricPrompt if we ever want to allow applications to "blacklist"
+ * modalities when calling authenticate().
* @hide
*/
- int TYPE_FINGERPRINT = 1;
+ int TYPE_NONE = 0;
+ /**
+ * Constant representing fingerprint.
+ * @hide
+ */
+ int TYPE_FINGERPRINT = 1 << 0;
/**
+ * Constant representing iris.
* @hide
*/
- int TYPE_IRIS = 2;
+ int TYPE_IRIS = 1 << 1;
/**
+ * Constant representing face.
* @hide
*/
- int TYPE_FACE = 3;
+ int TYPE_FACE = 1 << 2;
/**
* Container for biometric data
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index bd149fd05f59..b238d778f55a 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -251,27 +251,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
private Executor mExecutor;
private AuthenticationCallback mAuthenticationCallback;
- IBiometricPromptReceiver mDialogReceiver = new IBiometricPromptReceiver.Stub() {
- @Override
- public void onDialogDismissed(int reason) {
- // Check the reason and invoke OnClickListener(s) if necessary
- if (reason == DISMISSED_REASON_POSITIVE) {
- mPositiveButtonInfo.executor.execute(() -> {
- mPositiveButtonInfo.listener.onClick(null, DialogInterface.BUTTON_POSITIVE);
- });
- } else if (reason == DISMISSED_REASON_NEGATIVE) {
- mNegativeButtonInfo.executor.execute(() -> {
- mNegativeButtonInfo.listener.onClick(null, DialogInterface.BUTTON_NEGATIVE);
- });
- }
- }
- };
-
- IBiometricServiceReceiver mBiometricServiceReceiver =
+ private final IBiometricServiceReceiver mBiometricServiceReceiver =
new IBiometricServiceReceiver.Stub() {
@Override
- public void onAuthenticationSucceeded(long deviceId) throws RemoteException {
+ public void onAuthenticationSucceeded() throws RemoteException {
mExecutor.execute(() -> {
final AuthenticationResult result = new AuthenticationResult(mCryptoObject);
mAuthenticationCallback.onAuthenticationSucceeded(result);
@@ -279,26 +263,39 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
@Override
- public void onAuthenticationFailed(long deviceId) throws RemoteException {
+ public void onAuthenticationFailed() throws RemoteException {
mExecutor.execute(() -> {
mAuthenticationCallback.onAuthenticationFailed();
});
}
@Override
- public void onError(long deviceId, int error, String message)
- throws RemoteException {
+ public void onError(int error, String message) throws RemoteException {
mExecutor.execute(() -> {
mAuthenticationCallback.onAuthenticationError(error, message);
});
}
@Override
- public void onAcquired(long deviceId, int acquireInfo, String message) {
+ public void onAcquired(int acquireInfo, String message) throws RemoteException {
mExecutor.execute(() -> {
mAuthenticationCallback.onAuthenticationHelp(acquireInfo, message);
});
}
+
+ @Override
+ public void onDialogDismissed(int reason) throws RemoteException {
+ // Check the reason and invoke OnClickListener(s) if necessary
+ if (reason == DISMISSED_REASON_POSITIVE) {
+ mPositiveButtonInfo.executor.execute(() -> {
+ mPositiveButtonInfo.listener.onClick(null, DialogInterface.BUTTON_POSITIVE);
+ });
+ } else if (reason == DISMISSED_REASON_NEGATIVE) {
+ mNegativeButtonInfo.executor.execute(() -> {
+ mNegativeButtonInfo.listener.onClick(null, DialogInterface.BUTTON_NEGATIVE);
+ });
+ }
+ }
};
private BiometricPrompt(Context context, Bundle bundle,
@@ -557,9 +554,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
mExecutor = executor;
mAuthenticationCallback = callback;
final long sessionId = crypto != null ? crypto.getOpId() : 0;
- mService.authenticate(mToken, sessionId, userId,
- mBiometricServiceReceiver, 0 /* flags */, mContext.getOpPackageName(),
- mBundle, mDialogReceiver);
+ mService.authenticate(mToken, sessionId, userId, mBiometricServiceReceiver,
+ mContext.getOpPackageName(), mBundle);
} catch (RemoteException e) {
Log.e(TAG, "Remote exception while authenticating", e);
mExecutor.execute(() -> {
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index e17feff0160a..53a076135aaa 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -18,7 +18,6 @@ package android.hardware.biometrics;
import android.os.Bundle;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
-import android.hardware.biometrics.IBiometricPromptReceiver;
import android.hardware.biometrics.IBiometricServiceReceiver;
/**
@@ -32,8 +31,7 @@ interface IBiometricService {
// Requests authentication. The service choose the appropriate biometric to use, and show
// the corresponding BiometricDialog.
void authenticate(IBinder token, long sessionId, int userId,
- IBiometricServiceReceiver receiver, int flags, String opPackageName,
- in Bundle bundle, IBiometricPromptReceiver dialogReceiver);
+ IBiometricServiceReceiver receiver, String opPackageName, in Bundle bundle);
// Cancel authentication for the given sessionId
void cancelAuthentication(IBinder token, String opPackageName);
@@ -46,4 +44,8 @@ interface IBiometricService {
// Explicitly set the active user.
void setActiveUser(int userId);
+
+ // Notify BiometricService when <Biometric>Service is ready to start the prepared client.
+ // Client lifecycle is still managed in <Biometric>Service.
+ void onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId);
}
diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
index a6e3696eeb10..22ef33e86e17 100644
--- a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl
@@ -16,12 +16,18 @@
package android.hardware.biometrics;
/**
- * Communication channel from the BiometricService back to BiometricPrompt.
+ * Communication channel from BiometricService back to BiometricPrompt
* @hide
*/
oneway interface IBiometricServiceReceiver {
- void onAuthenticationSucceeded(long deviceId);
- void onAuthenticationFailed(long deviceId);
- void onError(long deviceId, int error, String message);
- void onAcquired(long deviceId, int acquiredInfo, String message);
+ // Notify BiometricPrompt that authentication was successful
+ void onAuthenticationSucceeded();
+ // Noties that authentication failed.
+ void onAuthenticationFailed();
+ // Notify BiometricPrompt that an error has occurred.
+ void onError(int error, String message);
+ // Notifies that a biometric has been acquired.
+ void onAcquired(int acquiredInfo, String message);
+ // Notifies that the SystemUI dialog has been dismissed.
+ void onDialogDismissed(int reason);
}
diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
new file mode 100644
index 000000000000..180daaf97ada
--- /dev/null
+++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.biometrics;
+
+/**
+ * Communication channel from
+ * 1) BiometricDialogImpl (SysUI) back to BiometricService
+ * 2) <Biometric>Service back to BiometricService
+ * Receives messages from the above and does some handling before forwarding to BiometricPrompt
+ * via IBiometricServiceReceiver.
+ * @hide
+ */
+oneway interface IBiometricServiceReceiverInternal {
+ // Notify BiometricService that authentication was successful. If user confirmation is required,
+ // the auth token must be submitted into KeyStore.
+ void onAuthenticationSucceeded(boolean requireConfirmation, in byte[] token);
+ // Notify BiometricService that an error has occurred.
+ void onAuthenticationFailed(int cookie, boolean requireConfirmation);
+ // Notify BiometricService than an error has occured. Forward to the correct receiver depending
+ // on the cookie.
+ void onError(int cookie, int error, String message);
+ // Notifies that a biometric has been acquired.
+ void onAcquired(int acquiredInfo, String message);
+ // Notifies that the SystemUI dialog has been dismissed.
+ void onDialogDismissed(int reason);
+ // Notifies that the user has pressed the "try again" button on SystemUI
+ void onTryAgainPressed();
+}
diff --git a/core/java/android/hardware/display/DisplayViewport.java b/core/java/android/hardware/display/DisplayViewport.java
index df0d46be1354..f2c50b5cc464 100644
--- a/core/java/android/hardware/display/DisplayViewport.java
+++ b/core/java/android/hardware/display/DisplayViewport.java
@@ -19,6 +19,7 @@ package android.hardware.display;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.graphics.Rect;
import android.text.TextUtils;
@@ -71,6 +72,9 @@ public final class DisplayViewport {
// The ID used to uniquely identify this display.
public String uniqueId;
+ // The physical port that the associated display device is connected to.
+ public @Nullable Byte physicalPort;
+
public @ViewportType int type;
public void copyFrom(DisplayViewport viewport) {
@@ -82,6 +86,7 @@ public final class DisplayViewport {
deviceWidth = viewport.deviceWidth;
deviceHeight = viewport.deviceHeight;
uniqueId = viewport.uniqueId;
+ physicalPort = viewport.physicalPort;
type = viewport.type;
}
@@ -113,6 +118,7 @@ public final class DisplayViewport {
&& deviceWidth == other.deviceWidth
&& deviceHeight == other.deviceHeight
&& TextUtils.equals(uniqueId, other.uniqueId)
+ && physicalPort == other.physicalPort
&& type == other.type;
}
@@ -128,6 +134,7 @@ public final class DisplayViewport {
result += prime * result + deviceWidth;
result += prime * result + deviceHeight;
result += prime * result + uniqueId.hashCode();
+ result += prime * result + physicalPort;
result += prime * result + type;
return result;
}
@@ -139,6 +146,7 @@ public final class DisplayViewport {
+ ", valid=" + valid
+ ", displayId=" + displayId
+ ", uniqueId='" + uniqueId + "'"
+ + ", physicalPort=" + physicalPort
+ ", orientation=" + orientation
+ ", logicalFrame=" + logicalFrame
+ ", physicalFrame=" + physicalFrame
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 47df8e8f9729..a15dcec3b276 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -15,9 +15,7 @@
*/
package android.hardware.face;
-import android.os.Bundle;
-import android.hardware.biometrics.IBiometricPromptReceiver;
-import android.hardware.biometrics.IBiometricServiceReceiver;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.face.IFaceServiceReceiver;
import android.hardware.face.Face;
@@ -32,19 +30,24 @@ interface IFaceService {
void authenticate(IBinder token, long sessionId,
IFaceServiceReceiver receiver, int flags, String opPackageName);
- // This method invokes the BiometricDialog. The arguments are almost the same as above,
- // but should only be called from (BiometricPromptService).
- void authenticateFromService(boolean requireConfirmation, IBinder token, long sessionId,
- int userId, IBiometricServiceReceiver receiver, int flags, String opPackageName,
- in Bundle bundle, IBiometricPromptReceiver dialogReceiver,
- int callingUid, int callingPid, int callingUserId);
+ // This method prepares the service to start authenticating, but doesn't start authentication.
+ // This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
+ // called from BiometricService. The additional uid, pid, userId arguments should be determined
+ // by BiometricService. To start authentication after the clients are ready, use
+ // startPreparedClient().
+ void prepareForAuthentication(boolean requireConfirmation, IBinder token, long sessionId,
+ int userId, IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName,
+ int cookie, int callingUid, int callingPid, int callingUserId);
+
+ // Starts authentication with the previously prepared client.
+ void startPreparedClient(int cookie);
// Cancel authentication for the given sessionId
void cancelAuthentication(IBinder token, String opPackageName);
// Same as above, with extra arguments.
void cancelAuthenticationFromService(IBinder token, String opPackageName,
- int callingUid, int callingPid, int callingUserId);
+ int callingUid, int callingPid, int callingUserId, boolean fromClient);
// Start face enrollment
void enroll(IBinder token, in byte [] cryptoToken, int userId, IFaceServiceReceiver receiver,
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 2662a11c2dd4..dd6b29d87d67 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -15,9 +15,7 @@
*/
package android.hardware.fingerprint;
-import android.os.Bundle;
-import android.hardware.biometrics.IBiometricPromptReceiver;
-import android.hardware.biometrics.IBiometricServiceReceiver;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
@@ -35,22 +33,25 @@ interface IFingerprintService {
void authenticate(IBinder token, long sessionId, int userId,
IFingerprintServiceReceiver receiver, int flags, String opPackageName);
- // This method invokes the BiometricDialog. The arguments are almost the same as above, except
- // this is protected by the MANAGE_BIOMETRIC signature permission. This method should only be
- // called from BiometricPromptService. The additional uid, pid, userId arguments should be
- // determined by BiometricPromptService.
- void authenticateFromService(IBinder token, long sessionId, int userId,
- IBiometricServiceReceiver receiver, int flags, String opPackageName,
- in Bundle bundle, IBiometricPromptReceiver dialogReceiver,
+ // This method prepares the service to start authenticating, but doesn't start authentication.
+ // This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
+ // called from BiometricService. The additional uid, pid, userId arguments should be determined
+ // by BiometricService. To start authentication after the clients are ready, use
+ // startPreparedClient().
+ void prepareForAuthentication(IBinder token, long sessionId, int userId,
+ IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName, int cookie,
int callingUid, int callingPid, int callingUserId);
+ // Starts authentication with the previously prepared client.
+ void startPreparedClient(int cookie);
+
// Cancel authentication for the given sessionId
void cancelAuthentication(IBinder token, String opPackageName);
// Same as above, except this is protected by the MANAGE_BIOMETRIC signature permission. Takes
// an additional uid, pid, userid.
void cancelAuthenticationFromService(IBinder token, String opPackageName,
- int callingUid, int callingPid, int callingUserId);
+ int callingUid, int callingPid, int callingUserId, boolean fromClient);
// Start fingerprint enrollment
void enroll(IBinder token, in byte [] cryptoToken, int groupId, IFingerprintServiceReceiver receiver,
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 1468fe5bfca8..64314a7d8060 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -928,7 +928,9 @@ public class Binder implements IBinder {
final long origWorkSource = ThreadLocalWorkSource.setUid(Binder.getCallingUid());
try {
if (tracingEnabled) {
- Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":" + code);
+ final String transactionName = getTransactionName(code);
+ Trace.traceBegin(Trace.TRACE_TAG_ALWAYS, getClass().getName() + ":"
+ + (transactionName != null ? transactionName : code));
}
res = onTransact(code, data, reply, flags);
} catch (RemoteException|RuntimeException e) {
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 651caece01f9..2abcb4cd9379 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -1055,6 +1055,9 @@ public class Process {
*/
public static final native long getPss(int pid);
+ /** @hide */
+ public static final native long[] getRss(int pid);
+
/**
* Specifies the outcome of having started a process.
* @hide
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 92b316914d82..abfcfaacde21 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2463,6 +2463,27 @@ public class UserManager {
}
/**
+ * Get the parent of a user profile.
+ *
+ * @param user the handle of the user profile
+ *
+ * @return the parent of the user or {@code null} if the user is not profile
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public @Nullable UserHandle getProfileParent(@NonNull UserHandle user) {
+ UserInfo info = getProfileParent(user.getIdentifier());
+
+ if (info == null) {
+ return null;
+ }
+
+ return UserHandle.of(info.id);
+ }
+
+ /**
* Enables or disables quiet mode for a managed profile. If quiet mode is enabled, apps in a
* managed profile don't run, generate notifications, or consume data or battery.
* <p>
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index b42f1c4df4e3..8e11d858128a 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -25,6 +25,7 @@ import android.annotation.SdkConstant;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.annotation.WorkerThread;
import android.app.Activity;
@@ -1533,6 +1534,12 @@ public class StorageManager {
return SystemProperties.getBoolean(PROP_HAS_ADOPTABLE, false);
}
+ /** {@hide} */
+ @TestApi
+ public static boolean hasIsolatedStorage() {
+ return SystemProperties.getBoolean(PROP_ISOLATED_STORAGE, false);
+ }
+
/**
* @deprecated disabled now that FUSE has been replaced by sdcardfs
* @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d7729037bfad..c297ef4f2a85 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5075,6 +5075,7 @@ public final class Settings {
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
public static void resetToDefaults(@NonNull ContentResolver resolver,
@Nullable String tag) {
@@ -8232,6 +8233,24 @@ public final class Settings {
public static final String NOTIFICATION_NEW_INTERRUPTION_MODEL = "new_interruption_model";
/**
+ * How often to check for location access.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS =
+ "location_access_check_interval_millis";
+
+ /**
+ * Delay between granting location access and checking it.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS =
+ "location_access_check_delay_millis";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
diff --git a/core/java/android/provider/TEST_MAPPING b/core/java/android/provider/TEST_MAPPING
new file mode 100644
index 000000000000..8e67ce7b2aa9
--- /dev/null
+++ b/core/java/android/provider/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.provider.SettingsBackupTest"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/java/android/service/oemlock/IOemLockService.aidl b/core/java/android/service/oemlock/IOemLockService.aidl
index d5e10d6629ca..99cffc5c5b8b 100644
--- a/core/java/android/service/oemlock/IOemLockService.aidl
+++ b/core/java/android/service/oemlock/IOemLockService.aidl
@@ -22,6 +22,8 @@ package android.service.oemlock;
* @hide
*/
interface IOemLockService {
+ String getLockName();
+
void setOemUnlockAllowedByCarrier(boolean allowed, in byte[] signature);
boolean isOemUnlockAllowedByCarrier();
diff --git a/core/java/android/service/oemlock/OemLockManager.java b/core/java/android/service/oemlock/OemLockManager.java
index f0d660354167..029d645dda19 100644
--- a/core/java/android/service/oemlock/OemLockManager.java
+++ b/core/java/android/service/oemlock/OemLockManager.java
@@ -44,6 +44,23 @@ public class OemLockManager {
}
/**
+ * Returns a vendor specific name for the OEM lock.
+ *
+ * This value is used to identify the security protocol used by locks.
+ *
+ * @return The name of the OEM lock or {@code null} if failed to get the name.
+ */
+ @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE)
+ @Nullable
+ public String getLockName() {
+ try {
+ return mService.getLockName();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Sets whether the carrier has allowed this device to be OEM unlocked.
*
* Depending on the implementation, the validity of the request might need to be proved. This
diff --git a/core/java/android/service/wallpaper/IWallpaperEngine.aidl b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
index dccce406e32c..ebce4846c16b 100644
--- a/core/java/android/service/wallpaper/IWallpaperEngine.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperEngine.aidl
@@ -27,7 +27,7 @@ oneway interface IWallpaperEngine {
void setDesiredSize(int width, int height);
void setDisplayPadding(in Rect padding);
void setVisibility(boolean visible);
- void setInAmbientMode(boolean inAmbientDisplay, boolean animated);
+ void setInAmbientMode(boolean inAmbientDisplay, long animationDuration);
void dispatchPointer(in MotionEvent event);
void dispatchWallpaperCommand(String action, int x, int y,
int z, in Bundle extras);
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 45d53f340f35..a095b0d8b239 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -19,6 +19,7 @@ package android.service.wallpaper;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.app.Service;
import android.app.WallpaperColors;
@@ -442,7 +443,9 @@ public abstract class WallpaperService extends Service {
/**
* Returns true if this engine is running in ambient mode -- that is,
* it is being shown in low power mode, on always on display.
+ * @hide
*/
+ @SystemApi
public boolean isInAmbientMode() {
return mIsInAmbientMode;
}
@@ -568,14 +571,16 @@ public abstract class WallpaperService extends Service {
* Called when the device enters or exits ambient mode.
*
* @param inAmbientMode {@code true} if in ambient mode.
- * @param animated {@code true} if you'll have the opportunity of animating your transition
- * {@code false} when the wallpaper should present its ambient version
- * immediately.
+ * @param animationDuration How long the transition animation to change the ambient state
+ * should run, in milliseconds. If 0 is passed as the argument
+ * here, the state should be switched immediately.
*
* @see #isInAmbientMode()
* @see WallpaperInfo#supportsAmbientMode()
+ * @hide
*/
- public void onAmbientModeChanged(boolean inAmbientMode, boolean animated) {
+ @SystemApi
+ public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
}
/**
@@ -1049,19 +1054,19 @@ public abstract class WallpaperService extends Service {
* message sent from handler.
*
* @param inAmbientMode {@code true} if in ambient mode.
- * @param animated {@code true} if the transition will be animated.
+ * @param animationDuration For how long the transition will last, in ms.
* @hide
*/
@VisibleForTesting
- public void doAmbientModeChanged(boolean inAmbientMode, boolean animated) {
+ public void doAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
if (!mDestroyed) {
if (DEBUG) {
Log.v(TAG, "onAmbientModeChanged(" + inAmbientMode + ", "
- + animated + "): " + this);
+ + animationDuration + "): " + this);
}
mIsInAmbientMode = inAmbientMode;
if (mCreated) {
- onAmbientModeChanged(inAmbientMode, animated);
+ onAmbientModeChanged(inAmbientMode, animationDuration);
}
}
}
@@ -1320,10 +1325,10 @@ public abstract class WallpaperService extends Service {
}
@Override
- public void setInAmbientMode(boolean inAmbientDisplay, boolean animated)
+ public void setInAmbientMode(boolean inAmbientDisplay, long animationDuration)
throws RemoteException {
- Message msg = mCaller.obtainMessageII(DO_IN_AMBIENT_MODE, inAmbientDisplay ? 1 : 0,
- animated ? 1 : 0);
+ Message msg = mCaller.obtainMessageIO(DO_IN_AMBIENT_MODE, inAmbientDisplay ? 1 : 0,
+ animationDuration);
mCaller.sendMessage(msg);
}
@@ -1394,7 +1399,7 @@ public abstract class WallpaperService extends Service {
return;
}
case DO_IN_AMBIENT_MODE: {
- mEngine.doAmbientModeChanged(message.arg1 != 0, message.arg2 != 0);
+ mEngine.doAmbientModeChanged(message.arg1 != 0, (Long) message.obj);
return;
}
case MSG_UPDATE_SURFACE:
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index dace388b66f6..c4be0e504c5b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -304,7 +304,7 @@ interface IWindowManager
/**
* Get the position of the nav bar
*/
- int getNavBarPosition();
+ int getNavBarPosition(int displayId);
/**
* Lock the device immediately with the specified options (can be null).
@@ -551,4 +551,16 @@ interface IWindowManager
* @see KeyguardManager#isDeviceLocked()
*/
void setShouldShowIme(int displayId, boolean shouldShow);
+
+ /**
+ * Reparent the top layers for a display to the requested surfaceControl. The display that
+ * is going to be re-parented (the displayId passed in) needs to have been created by the same
+ * process that is requesting the re-parent. This is to ensure clients can't just re-parent
+ * display content info to any SurfaceControl, as this would be a security issue.
+ *
+ * @param displayId The id of the display.
+ * @param surfaceControlHandle The SurfaceControl handle that the top level layers for the
+ * display should be re-parented to.
+ */
+ void reparentDisplayContent(int displayId, in IBinder surfaceControlHandle);
}
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 0739516e4e96..8b39cc72af8f 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1862,12 +1862,12 @@ public class KeyEvent extends InputEvent implements Parcelable {
}
/**
- * Whether this key is a media key, which can be send to apps that are
- * interested in media key events.
+ * Returns whether this key can be handled by
+ * {@link android.media.session.MediaSession.Callback}.
*
* @hide
*/
- public static final boolean isMediaKey(int keyCode) {
+ public static final boolean isMediaSessionKey(int keyCode) {
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_PLAY:
case KeyEvent.KEYCODE_MEDIA_PAUSE:
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 46f396a0b66b..ab010855b896 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -104,6 +104,8 @@ public class SurfaceControl implements Parcelable {
int flags, int mask);
private static native void nativeSetWindowCrop(long transactionObj, long nativeObject,
int l, int t, int r, int b);
+ private static native void nativeSetCornerRadius(long transactionObj, long nativeObject,
+ float cornerRadius);
private static native void nativeSetLayerStack(long transactionObj, long nativeObject,
int layerStack);
@@ -1006,6 +1008,18 @@ public class SurfaceControl implements Parcelable {
}
}
+ /**
+ * Sets the corner radius of a {@link SurfaceControl}.
+ *
+ * @param cornerRadius Corner radius in pixels.
+ */
+ public void setCornerRadius(float cornerRadius) {
+ checkNotReleased();
+ synchronized (SurfaceControl.class) {
+ sGlobalTransaction.setCornerRadius(this, cornerRadius);
+ }
+ }
+
public void setLayerStack(int layerStack) {
checkNotReleased();
synchronized(SurfaceControl.class) {
@@ -1529,6 +1543,20 @@ public class SurfaceControl implements Parcelable {
return this;
}
+ /**
+ * Sets the corner radius of a {@link SurfaceControl}.
+ * @param sc SurfaceControl
+ * @param cornerRadius Corner radius in pixels.
+ * @return Itself.
+ */
+ @UnsupportedAppUsage
+ public Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) {
+ sc.checkNotReleased();
+ nativeSetCornerRadius(mNativeObject, sc.mNativeObject, cornerRadius);
+
+ return this;
+ }
+
@UnsupportedAppUsage
public Transaction setLayerStack(SurfaceControl sc, int layerStack) {
sc.checkNotReleased();
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 3c4ce8f7cfad..797d1c5f47aa 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1126,6 +1126,13 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
}
};
+ /**
+ * @hide
+ */
+ public SurfaceControl getSurfaceControl() {
+ return mSurfaceControl;
+ }
+
class SurfaceControlWithBackground extends SurfaceControl {
SurfaceControl mBackgroundControl;
private boolean mOpaque = true;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2767505aece3..c5d03741dbba 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4159,7 +4159,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
float mAlpha = 1f;
/**
- * The opacity of the view as manipulated by the Fade transition. This is a hidden
+ * The opacity of the view as manipulated by the Fade transition. This is a
* property only used by transitions, which is composited with the other alpha
* values to calculate the final visual alpha value.
*/
@@ -15729,15 +15729,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * This property is hidden and intended only for use by the Fade transition, which
- * animates it to produce a visual translucency that does not side-effect (or get
- * affected by) the real alpha property. This value is composited with the other
- * alpha value (and the AlphaAnimation value, when that is present) to produce
- * a final visual translucency result, which is what is passed into the DisplayList.
- *
- * @hide
+ * This property is intended only for use by the Fade transition, which animates it
+ * to produce a visual translucency that does not side-effect (or get affected by)
+ * the real alpha property. This value is composited with the other alpha value
+ * (and the AlphaAnimation value, when that is present) to produce a final visual
+ * translucency result, which is what is passed into the DisplayList.
*/
- @UnsupportedAppUsage
public void setTransitionAlpha(float alpha) {
ensureTransformationInfo();
if (mTransformationInfo.mTransitionAlpha != alpha) {
@@ -15760,16 +15757,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * This property is hidden and intended only for use by the Fade transition, which
- * animates it to produce a visual translucency that does not side-effect (or get
- * affected by) the real alpha property. This value is composited with the other
- * alpha value (and the AlphaAnimation value, when that is present) to produce
- * a final visual translucency result, which is what is passed into the DisplayList.
- *
- * @hide
+ * This property is intended only for use by the Fade transition, which animates
+ * it to produce a visual translucency that does not side-effect (or get affected
+ * by) the real alpha property. This value is composited with the other alpha
+ * value (and the AlphaAnimation value, when that is present) to produce a final
+ * visual translucency result, which is what is passed into the DisplayList.
*/
@ViewDebug.ExportedProperty(category = "drawing")
- @UnsupportedAppUsage
public float getTransitionAlpha() {
return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
}
@@ -16288,9 +16282,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
- /** @hide */
- @UnsupportedAppUsage
- public void setAnimationMatrix(Matrix matrix) {
+ /**
+ * Changes the transformation matrix on the view. This is used in animation frameworks,
+ * such as {@link android.transition.Transition}. When the animation finishes, the matrix
+ * should be cleared by calling this method with <code>null</code> as the matrix parameter.
+ * Application developers should use transformation methods like {@link #setRotation(float)},
+ * {@link #setScaleX(float)}, {@link #setScaleX(float)}, {@link #setTranslationX(float)}}
+ * and {@link #setTranslationY(float)} (float)}} instead.
+ *
+ * @param matrix The matrix, null indicates that the matrix should be cleared.
+ */
+ public void setAnimationMatrix(@Nullable Matrix matrix) {
invalidateViewProperty(true, false);
mRenderNode.setAnimationMatrix(matrix);
invalidateViewProperty(false, true);
@@ -21460,7 +21462,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* previous ones
* {@hide}
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
protected boolean setFrame(int left, int top, int right, int bottom) {
boolean changed = false;
@@ -21537,7 +21539,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @see #setLeft(int), #setRight(int), #setTop(int), #setBottom(int)
*/
- public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
+ public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {
setFrame(left, top, right, bottom);
}
@@ -23545,6 +23547,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Get the identifier used for this view by the drawing system.
+ *
+ * @see RenderNode#getUniqueId()
+ * @return A long that uniquely identifies this view's drawing component
+ */
+ public long getUniqueDrawingId() {
+ return mRenderNode.getUniqueId();
+ }
+
+ /**
* Returns this view's tag.
*
* @return the Object stored in this view as a tag, or {@code null} if not
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1e91aa87bfb7..741510e67130 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -7042,10 +7042,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* suppression is disabled with a later call to suppressLayout(false).
* When layout suppression is disabled, a requestLayout() call is sent
* if layout() was attempted while layout was being suppressed.
- *
- * @hide
*/
- @UnsupportedAppUsage
public void suppressLayout(boolean suppress) {
mSuppressLayout = suppress;
if (!suppress) {
@@ -7061,8 +7058,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* suppressed, due to an earlier call to {@link #suppressLayout(boolean)}.
*
* @return true if layout calls are currently suppressed, false otherwise.
- *
- * @hide
*/
public boolean isLayoutSuppressed() {
return mSuppressLayout;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index d9d52c01924f..937e23813cec 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -459,7 +459,7 @@ public final class ViewRootImpl implements ViewParent,
final DisplayCutout.ParcelableWrapper mPendingDisplayCutout =
new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
boolean mPendingAlwaysConsumeNavBar;
- private InsetsState mPendingInsets;
+ private InsetsState mPendingInsets = new InsetsState();
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8d8a37061035..45c36516b885 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1752,15 +1752,6 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY = 0x00100000;
/**
- * If this flag is set on the window, window manager will acquire a sleep token that puts
- * all activities to sleep as long as this window is visible. When this flag is set, the
- * window needs to occlude all activity windows.
- * @hide
- */
- @RequiresPermission(permission.DEVICE_POWER)
- public static final int PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN = 0x00200000;
-
- /**
* Flag to indicate that this window should be considered a screen decoration similar to the
* nav bar and status bar. This will cause this window to affect the window insets reported
* to other windows when it is visible.
@@ -1872,10 +1863,6 @@ public interface WindowManager extends ViewManager {
equals = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY,
name = "IS_ROUNDED_CORNERS_OVERLAY"),
@ViewDebug.FlagToString(
- mask = PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN,
- equals = PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN,
- name = "ACQUIRES_SLEEP_TOKEN"),
- @ViewDebug.FlagToString(
mask = PRIVATE_FLAG_IS_SCREEN_DECOR,
equals = PRIVATE_FLAG_IS_SCREEN_DECOR,
name = "IS_SCREEN_DECOR"),
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index 260e93890e3e..16bafe2c4f11 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -44,6 +44,7 @@ public interface WindowManagerPolicyConstants {
int PRESENCE_EXTERNAL = 1 << 1;
// Navigation bar position values
+ int NAV_BAR_INVALID = -1;
int NAV_BAR_LEFT = 1 << 0;
int NAV_BAR_RIGHT = 1 << 1;
int NAV_BAR_BOTTOM = 1 << 2;
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 9ccd3211768d..f78180276373 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Bundle;
import android.os.Trace;
import android.util.AttributeSet;
@@ -107,7 +108,7 @@ public class GridView extends AbsListView {
*/
public static final int AUTO_FIT = -1;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 117521080)
private int mNumColumns = AUTO_FIT;
@UnsupportedAppUsage
@@ -117,7 +118,7 @@ public class GridView extends AbsListView {
@UnsupportedAppUsage
private int mVerticalSpacing = 0;
private int mStretchMode = STRETCH_COLUMN_WIDTH;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 117521079)
private int mColumnWidth;
@UnsupportedAppUsage
private int mRequestedColumnWidth;
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index a28cc403ed56..157992a98a4a 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -18,6 +18,8 @@ package android.widget;
import android.annotation.CallSuper;
import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.Px;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.annotation.Widget;
@@ -30,6 +32,7 @@ import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Bundle;
import android.text.InputFilter;
import android.text.InputType;
@@ -88,6 +91,16 @@ import java.util.Locale;
* of the current value. Tapping on the current value allows to type in a
* desired value.
* </li>
+ * <li>
+ * If the current theme is derived from {@link android.R.style#Theme_Material}
+ * the widget presents the current value as a scrolling vertical selector with
+ * the selected value in the center and the previous and following numbers above
+ * and below, separated by a divider. The value is changed by flinging vertically.
+ * The thickness of the divider can be changed by using the
+ * {@link android.R.attr#selectionDividerHeight} attribute and the color of the
+ * divider can be changed by using the
+ * {@link android.R.attr#colorControlNormal} attribute.
+ * </li>
* </ul>
* <p>
* For an example of using this widget, see {@link android.widget.TimePicker}.
@@ -436,14 +449,14 @@ public class NumberPicker extends LinearLayout {
/**
* Divider for showing item to be selected while scrolling
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
private final Drawable mSelectionDivider;
/**
* The height of the selection divider.
*/
- @UnsupportedAppUsage
- private final int mSelectionDividerHeight;
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ private int mSelectionDividerHeight;
/**
* The current scroll state of the number picker.
@@ -1556,6 +1569,24 @@ public class NumberPicker extends LinearLayout {
return mSelectorIndexToStringCache.get(getValue());
}
+ /**
+ * Set the height for the divider that separates the currently selected value from the others.
+ * @param height The height to be set
+ */
+ public void setSelectionDividerHeight(@IntRange(from = 0) @Px int height) {
+ mSelectionDividerHeight = height;
+ invalidate();
+ }
+
+ /**
+ * Retrieve the height for the divider that separates the currently selected value from the
+ * others.
+ * @return The height of the divider
+ */
+ public int getSelectionDividerHeight() {
+ return mSelectionDividerHeight;
+ }
+
@Override
protected float getTopFadingEdgeStrength() {
return TOP_AND_BOTTOM_FADING_EDGE_STRENGTH;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 85d851a3116c..1deee8af3d75 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6254,8 +6254,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mHint;
}
- @UnsupportedAppUsage
- boolean isSingleLine() {
+ /**
+ * Returns if the text is constrained to a single horizontally scrolling line ignoring new
+ * line characters instead of letting it wrap onto multiple lines.
+ *
+ * @attr ref android.R.styleable#TextView_singleLine
+ */
+ public boolean isSingleLine() {
return mSingleLine;
}
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 34e8ed406200..875d7c9ee7a6 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -52,17 +52,23 @@ public class BinderCallsStats implements BinderInternal.Observer {
public static final boolean ENABLED_DEFAULT = false;
public static final boolean DETAILED_TRACKING_DEFAULT = true;
public static final int PERIODIC_SAMPLING_INTERVAL_DEFAULT = 100;
+ public static final int MAX_BINDER_CALL_STATS_COUNT_DEFAULT = 5000;
+
+ private static class OverflowBinder extends Binder {}
private static final String TAG = "BinderCallsStats";
private static final int CALL_SESSIONS_POOL_SIZE = 100;
private static final int MAX_EXCEPTION_COUNT_SIZE = 50;
private static final String EXCEPTION_COUNT_OVERFLOW_NAME = "overflow";
+ private static final Class<? extends Binder> OVERFLOW_BINDER = OverflowBinder.class;
+ private static final int OVERFLOW_TRANSACTION_CODE = -1;
// Whether to collect all the data: cpu + exceptions + reply/request sizes.
private boolean mDetailedTracking = DETAILED_TRACKING_DEFAULT;
// Sampling period to control how often to track CPU usage. 1 means all calls, 100 means ~1 out
// of 100 requests.
private int mPeriodicSamplingInterval = PERIODIC_SAMPLING_INTERVAL_DEFAULT;
+ private int mMaxBinderCallStatsCount = MAX_BINDER_CALL_STATS_COUNT_DEFAULT;
@GuardedBy("mLock")
private final SparseArray<UidEntry> mUidEntries = new SparseArray<>();
@GuardedBy("mLock")
@@ -71,6 +77,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
private final Object mLock = new Object();
private final Random mRandom;
private long mStartTime = System.currentTimeMillis();
+ private long mCallStatsCount = 0;
private CachedDeviceState.Readonly mDeviceState;
@@ -158,7 +165,13 @@ public class BinderCallsStats implements BinderInternal.Observer {
final CallStat callStat = uidEntry.getOrCreate(
callingUid, s.binderClass, s.transactionCode,
- mDeviceState.isScreenInteractive());
+ mDeviceState.isScreenInteractive(),
+ mCallStatsCount >= mMaxBinderCallStatsCount);
+ final boolean isNewCallStat = callStat.callCount == 0;
+ if (isNewCallStat) {
+ mCallStatsCount++;
+ }
+
callStat.callCount++;
callStat.recordedCallCount++;
callStat.cpuTimeMicros += duration;
@@ -444,6 +457,24 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
}
+ /**
+ * Sets the maximum number of items to track.
+ */
+ public void setMaxBinderCallStats(int maxKeys) {
+ if (maxKeys <= 0) {
+ Slog.w(TAG, "Ignored invalid max value (value must be positive): "
+ + maxKeys);
+ return;
+ }
+
+ synchronized (mLock) {
+ if (maxKeys != mMaxBinderCallStatsCount) {
+ mMaxBinderCallStatsCount = maxKeys;
+ reset();
+ }
+ }
+ }
+
public void setSamplingInterval(int samplingInterval) {
if (samplingInterval <= 0) {
Slog.w(TAG, "Ignored invalid sampling interval (value must be positive): "
@@ -461,6 +492,7 @@ public class BinderCallsStats implements BinderInternal.Observer {
public void reset() {
synchronized (mLock) {
+ mCallStatsCount = 0;
mUidEntries.clear();
mExceptionCounts.clear();
mStartTime = System.currentTimeMillis();
@@ -595,10 +627,21 @@ public class BinderCallsStats implements BinderInternal.Observer {
}
CallStat getOrCreate(int callingUid, Class<? extends Binder> binderClass,
- int transactionCode, boolean screenInteractive) {
+ int transactionCode, boolean screenInteractive, boolean maxCallStatsReached) {
CallStat mapCallStat = get(callingUid, binderClass, transactionCode, screenInteractive);
- // Only create CallStat if it's a new entry, otherwise update existing instance
+ // Only create CallStat if it's a new entry, otherwise update existing instance.
if (mapCallStat == null) {
+ if (maxCallStatsReached) {
+ mapCallStat = get(callingUid, OVERFLOW_BINDER, OVERFLOW_TRANSACTION_CODE,
+ screenInteractive);
+ if (mapCallStat != null) {
+ return mapCallStat;
+ }
+
+ binderClass = OVERFLOW_BINDER;
+ transactionCode = OVERFLOW_TRANSACTION_CODE;
+ }
+
mapCallStat = new CallStat(callingUid, binderClass, transactionCode,
screenInteractive);
CallStatKey key = new CallStatKey();
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReader.java b/core/java/com/android/internal/os/KernelCpuThreadReader.java
index 2e901e4520e6..2742b7cdf872 100644
--- a/core/java/com/android/internal/os/KernelCpuThreadReader.java
+++ b/core/java/com/android/internal/os/KernelCpuThreadReader.java
@@ -108,13 +108,6 @@ public class KernelCpuThreadReader {
private static final Predicate<Integer> DEFAULT_UID_PREDICATE = uid -> uid == 1000;
/**
- * Do not report any threads that have a total CPU usage (across all frequencies) less than or
- * equal to this number. This significantly reduces the amount of reported threads without
- * losing any important information
- */
- private static final int TOTAL_CPU_USAGE_THRESHOLD_MILLIS = 20;
-
- /**
* Value returned when there was an error getting an integer ID value (e.g. PID, UID)
*/
private static final int ID_ERROR = -1;
@@ -345,15 +338,6 @@ public class KernelCpuThreadReader {
}
int[] cpuUsages = mFrequencyBucketCreator.getBucketedValues(cpuUsagesLong);
- // Filter threads that have low total CPU usage
- int cpuUsageSum = 0;
- for (int i = 0; i < cpuUsages.length; i++) {
- cpuUsageSum += cpuUsages[i];
- }
- if (cpuUsageSum <= TOTAL_CPU_USAGE_THRESHOLD_MILLIS) {
- return null;
- }
-
return new ThreadCpuUsage(threadId, threadName, cpuUsages);
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 3b7ce0a22b18..488b9912ee49 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -41,6 +41,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Color;
@@ -1891,7 +1892,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return true;
}
// These are all the recognized media key codes in
- // KeyEvent.isMediaKey()
+ // KeyEvent.isMediaSessionKey()
case KeyEvent.KEYCODE_MEDIA_PLAY:
case KeyEvent.KEYCODE_MEDIA_PAUSE:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
@@ -1992,7 +1993,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return true;
}
// These are all the recognized media key codes in
- // KeyEvent.isMediaKey()
+ // KeyEvent.isMediaSessionKey()
case KeyEvent.KEYCODE_MEDIA_PLAY:
case KeyEvent.KEYCODE_MEDIA_PAUSE:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
diff --git a/core/java/com/android/internal/policy/ScreenDecorationsUtils.java b/core/java/com/android/internal/policy/ScreenDecorationsUtils.java
new file mode 100644
index 000000000000..100c6ee6763b
--- /dev/null
+++ b/core/java/com/android/internal/policy/ScreenDecorationsUtils.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.policy;
+
+import com.android.internal.R;
+
+import android.content.res.Resources;
+
+/**
+ * Utility functions for screen decorations used by both window manager and System UI.
+ */
+public class ScreenDecorationsUtils {
+
+ /**
+ * Corner radius that should be used on windows in order to cover the display.
+ * These values are expressed in pixels because they should not respect display or font
+ * scaling, this means that we don't have to reload them on config changes.
+ */
+ public static float getWindowCornerRadius(Resources resources) {
+ // Radius that should be used in case top or bottom aren't defined.
+ float defaultRadius = resources.getDimension(R.dimen.rounded_corner_radius);
+
+ float topRadius = resources.getDimension(R.dimen.rounded_corner_radius_top);
+ if (topRadius == 0) {
+ topRadius = defaultRadius;
+ }
+ float bottomRadius = resources.getDimension(R.dimen.rounded_corner_radius_bottom);
+ if (bottomRadius == 0) {
+ bottomRadius = defaultRadius;
+ }
+
+ // Always use the smallest radius to make sure the rounded corners will
+ // completely cover the display.
+ return Math.min(topRadius, bottomRadius);
+ }
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 604537ffee03..600b1b324257 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -18,7 +18,7 @@ package com.android.internal.statusbar;
import android.content.ComponentName;
import android.graphics.Rect;
-import android.hardware.biometrics.IBiometricPromptReceiver;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
@@ -141,7 +141,7 @@ oneway interface IStatusBar
void showShutdownUi(boolean isReboot, String reason);
// Used to show the dialog when BiometricService starts authentication
- void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
+ void showBiometricDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver, int type,
boolean requireConfirmation, int userId);
// Used to hide the dialog when a biometric is authenticated
void onBiometricAuthenticated();
@@ -151,4 +151,6 @@ oneway interface IStatusBar
void onBiometricError(String error);
// Used to hide the biometric dialog when the AuthenticationClient is stopped
void hideBiometricDialog();
+ // Used to request the "try again" button for authentications which requireConfirmation=true
+ void showBiometricTryAgain();
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index b7ffb5768a31..bf82dc610ad4 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -21,7 +21,7 @@ import android.content.ComponentName;
import android.graphics.Rect;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
-import android.hardware.biometrics.IBiometricPromptReceiver;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
@@ -92,7 +92,7 @@ interface IStatusBarService
void showPinningEscapeToast();
// Used to show the dialog when BiometricService starts authentication
- void showBiometricDialog(in Bundle bundle, IBiometricPromptReceiver receiver, int type,
+ void showBiometricDialog(in Bundle bundle, IBiometricServiceReceiverInternal receiver, int type,
boolean requireConfirmation, int userId);
// Used to hide the dialog when a biometric is authenticated
void onBiometricAuthenticated();
@@ -102,4 +102,6 @@ interface IStatusBarService
void onBiometricError(String error);
// Used to hide the biometric dialog when the AuthenticationClient is stopped
void hideBiometricDialog();
+ // Used to request the "try again" button for authentications which requireConfirmation=true
+ void showBiometricTryAgain();
}
diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java
index 17d5a2e36974..61581458f98a 100644
--- a/core/java/com/android/internal/util/BitUtils.java
+++ b/core/java/com/android/internal/util/BitUtils.java
@@ -28,7 +28,7 @@ import java.util.function.IntFunction;
/**
* A utility class for handling unsigned integers and unsigned arithmetics, as well as syntactic
- * sugar methods for ByteBuffer. Useful for networking and packet manipulations.
+ * sugar methods for {@link ByteBuffer}. Useful for networking and packet manipulations.
* {@hide}
*/
public final class BitUtils {
@@ -151,4 +151,11 @@ public final class BitUtils {
TextUtils.wrap(builder, "[", "]");
return builder.toString();
}
+
+ /**
+ * Converts long to byte array
+ */
+ public static byte[] toBytes(long l) {
+ return ByteBuffer.allocate(8).putLong(l).array();
+ }
}
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index 083c0c9736f9..151901be7b5b 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -190,6 +191,13 @@ public class CollectionUtils {
}
/**
+ * Returns the size of the given map, or 0 if null
+ */
+ public static int size(@Nullable Map<?, ?> cur) {
+ return cur != null ? cur.size() : 0;
+ }
+
+ /**
* Returns whether the given collection {@link Collection#isEmpty is empty} or {@code null}
*/
public static boolean isEmpty(@Nullable Collection<?> cur) {
diff --git a/core/java/com/android/internal/util/function/NonaConsumer.java b/core/java/com/android/internal/util/function/NonaConsumer.java
new file mode 100644
index 000000000000..3e7ce2b405a7
--- /dev/null
+++ b/core/java/com/android/internal/util/function/NonaConsumer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.function;
+
+import java.util.function.Consumer;
+
+/**
+ * A 9-argument {@link Consumer}
+ *
+ * @hide
+ */
+public interface NonaConsumer<A, B, C, D, E, F, G, H, I> {
+ void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+}
diff --git a/core/java/com/android/internal/util/function/NonaFunction.java b/core/java/com/android/internal/util/function/NonaFunction.java
new file mode 100644
index 000000000000..560b4f157ee1
--- /dev/null
+++ b/core/java/com/android/internal/util/function/NonaFunction.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.function;
+
+import java.util.function.Function;
+
+/**
+ * A 9-argument {@link Function}
+ *
+ * @hide
+ */
+public interface NonaFunction<A, B, C, D, E, F, G, H, I, R> {
+ R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+}
diff --git a/core/java/com/android/internal/util/function/NonaPredicate.java b/core/java/com/android/internal/util/function/NonaPredicate.java
new file mode 100644
index 000000000000..c1e6f377e7ae
--- /dev/null
+++ b/core/java/com/android/internal/util/function/NonaPredicate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.function;
+
+import java.util.function.Predicate;
+
+/**
+ * A 9-argument {@link Predicate}
+ *
+ * @hide
+ */
+public interface NonaPredicate<A, B, C, D, E, F, G, H, I> {
+ boolean test(A a, B b, C c, D d, E e, F f, G g, H h, I i);
+}
diff --git a/core/java/com/android/internal/util/function/OctConsumer.java b/core/java/com/android/internal/util/function/OctConsumer.java
new file mode 100644
index 000000000000..83ee30530c26
--- /dev/null
+++ b/core/java/com/android/internal/util/function/OctConsumer.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.function;
+
+import java.util.function.Consumer;
+
+/**
+ * A 8-argument {@link Consumer}
+ *
+ * @hide
+ */
+public interface OctConsumer<A, B, C, D, E, F, G, H> {
+ void accept(A a, B b, C c, D d, E e, F f, G g, H h);
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl b/core/java/com/android/internal/util/function/OctFunction.java
index 27d25b86b859..cb16624725b7 100644
--- a/core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl
+++ b/core/java/com/android/internal/util/function/OctFunction.java
@@ -13,12 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.hardware.biometrics;
+
+package com.android.internal.util.function;
+
+import java.util.function.Function;
/**
- * Communication channel from the BiometricPrompt (SysUI) back to AuthenticationClient.
+ * A 8-argument {@link Function}
+ *
* @hide
*/
-oneway interface IBiometricPromptReceiver {
- void onDialogDismissed(int reason);
+public interface OctFunction<A, B, C, D, E, F, G, H, R> {
+ R apply(A a, B b, C c, D d, E e, F f, G g, H h);
}
diff --git a/core/java/com/android/internal/util/function/OctPredicate.java b/core/java/com/android/internal/util/function/OctPredicate.java
new file mode 100644
index 000000000000..7f36d6acc066
--- /dev/null
+++ b/core/java/com/android/internal/util/function/OctPredicate.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util.function;
+
+import java.util.function.Predicate;
+
+/**
+ * A 8-argument {@link Predicate}
+ *
+ * @hide
+ */
+public interface OctPredicate<A, B, C, D, E, F, G, H> {
+ boolean test(A a, B b, C c, D d, E e, F f, G g, H h);
+}
diff --git a/core/java/com/android/internal/util/function/pooled/OmniFunction.java b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
index 4ffe44194958..d74e715605bb 100755
--- a/core/java/com/android/internal/util/function/pooled/OmniFunction.java
+++ b/core/java/com/android/internal/util/function/pooled/OmniFunction.java
@@ -22,6 +22,10 @@ import com.android.internal.util.function.HeptConsumer;
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexConsumer;
import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.NonaConsumer;
+import com.android.internal.util.function.NonaFunction;
+import com.android.internal.util.function.OctConsumer;
+import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadConsumer;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintConsumer;
@@ -39,61 +43,62 @@ import java.util.function.Function;
*
* @hide
*/
-abstract class OmniFunction<A, B, C, D, E, F, G, R> implements
+abstract class OmniFunction<A, B, C, D, E, F, G, H, I, R> implements
PooledFunction<A, R>, BiFunction<A, B, R>, TriFunction<A, B, C, R>,
QuadFunction<A, B, C, D, R>, QuintFunction<A, B, C, D, E, R>,
HexFunction<A, B, C, D, E, F, R>, HeptFunction<A, B, C, D, E, F, G, R>,
+ OctFunction<A, B, C, D, E, F, G, H, R>, NonaFunction<A, B, C, D, E, F, G, H, I, R>,
PooledConsumer<A>, BiConsumer<A, B>, TriConsumer<A, B, C>, QuadConsumer<A, B, C, D>,
QuintConsumer<A, B, C, D, E>, HexConsumer<A, B, C, D, E, F>,
- HeptConsumer<A, B, C, D, E, F, G>,
- PooledPredicate<A>, BiPredicate<A, B>,
+ HeptConsumer<A, B, C, D, E, F, G>, OctConsumer<A, B, C, D, E, F, G, H>,
+ NonaConsumer<A, B, C, D, E, F, G, H, I>, PooledPredicate<A>, BiPredicate<A, B>,
PooledSupplier<R>, PooledRunnable, ThrowingRunnable, ThrowingSupplier<R>,
PooledSupplier.OfInt, PooledSupplier.OfLong, PooledSupplier.OfDouble {
- abstract R invoke(A a, B b, C c, D d, E e, F f, G g);
+ abstract R invoke(A a, B b, C c, D d, E e, F f, G g, H h, I i);
@Override
public R apply(A o, B o2) {
- return invoke(o, o2, null, null, null, null, null);
+ return invoke(o, o2, null, null, null, null, null, null, null);
}
@Override
public R apply(A o) {
- return invoke(o, null, null, null, null, null, null);
+ return invoke(o, null, null, null, null, null, null, null, null);
}
- public abstract <V> OmniFunction<A, B, C, D, E, F, G, V> andThen(
+ public abstract <V> OmniFunction<A, B, C, D, E, F, G, H, I, V> andThen(
Function<? super R, ? extends V> after);
- public abstract OmniFunction<A, B, C, D, E, F, G, R> negate();
+ public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> negate();
@Override
public void accept(A o, B o2) {
- invoke(o, o2, null, null, null, null, null);
+ invoke(o, o2, null, null, null, null, null, null, null);
}
@Override
public void accept(A o) {
- invoke(o, null, null, null, null, null, null);
+ invoke(o, null, null, null, null, null, null, null, null);
}
@Override
public void run() {
- invoke(null, null, null, null, null, null, null);
+ invoke(null, null, null, null, null, null, null, null, null);
}
@Override
public R get() {
- return invoke(null, null, null, null, null, null, null);
+ return invoke(null, null, null, null, null, null, null, null, null);
}
@Override
public boolean test(A o, B o2) {
- return (Boolean) invoke(o, o2, null, null, null, null, null);
+ return (Boolean) invoke(o, o2, null, null, null, null, null, null, null);
}
@Override
public boolean test(A o) {
- return (Boolean) invoke(o, null, null, null, null, null, null);
+ return (Boolean) invoke(o, null, null, null, null, null, null, null, null);
}
@Override
@@ -108,52 +113,72 @@ abstract class OmniFunction<A, B, C, D, E, F, G, R> implements
@Override
public R apply(A a, B b, C c) {
- return invoke(a, b, c, null, null, null, null);
+ return invoke(a, b, c, null, null, null, null, null, null);
}
@Override
public void accept(A a, B b, C c) {
- invoke(a, b, c, null, null, null, null);
+ invoke(a, b, c, null, null, null, null, null, null);
}
@Override
public R apply(A a, B b, C c, D d) {
- return invoke(a, b, c, d, null, null, null);
+ return invoke(a, b, c, d, null, null, null, null, null);
}
@Override
public R apply(A a, B b, C c, D d, E e) {
- return invoke(a, b, c, d, e, null, null);
+ return invoke(a, b, c, d, e, null, null, null, null);
}
@Override
public R apply(A a, B b, C c, D d, E e, F f) {
- return invoke(a, b, c, d, e, f, null);
+ return invoke(a, b, c, d, e, f, null, null, null);
}
@Override
public R apply(A a, B b, C c, D d, E e, F f, G g) {
- return invoke(a, b, c, d, e, f, g);
+ return invoke(a, b, c, d, e, f, g, null, null);
+ }
+
+ @Override
+ public R apply(A a, B b, C c, D d, E e, F f, G g, H h) {
+ return invoke(a, b, c, d, e, f, g, h, null);
+ }
+
+ @Override
+ public R apply(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
+ return invoke(a, b, c, d, e, f, g, h, i);
}
@Override
public void accept(A a, B b, C c, D d) {
- invoke(a, b, c, d, null, null, null);
+ invoke(a, b, c, d, null, null, null, null, null);
}
@Override
public void accept(A a, B b, C c, D d, E e) {
- invoke(a, b, c, d, e, null, null);
+ invoke(a, b, c, d, e, null, null, null, null);
}
@Override
public void accept(A a, B b, C c, D d, E e, F f) {
- invoke(a, b, c, d, e, f, null);
+ invoke(a, b, c, d, e, f, null, null, null);
}
@Override
public void accept(A a, B b, C c, D d, E e, F f, G g) {
- invoke(a, b, c, d, e, f, g);
+ invoke(a, b, c, d, e, f, g, null, null);
+ }
+
+ @Override
+ public void accept(A a, B b, C c, D d, E e, F f, G g, H h) {
+ invoke(a, b, c, d, e, f, g, h, null);
+ }
+
+ @Override
+ public void accept(A a, B b, C c, D d, E e, F f, G g, H h, I i) {
+ invoke(a, b, c, d, e, f, g, h, i);
}
@Override
@@ -167,5 +192,5 @@ abstract class OmniFunction<A, B, C, D, E, F, G, R> implements
}
@Override
- public abstract OmniFunction<A, B, C, D, E, F, G, R> recycleOnUse();
+ public abstract OmniFunction<A, B, C, D, E, F, G, H, I, R> recycleOnUse();
}
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambda.java b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
index af3c7527c432..c00932e7a8aa 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambda.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambda.java
@@ -25,6 +25,10 @@ import com.android.internal.util.function.HeptConsumer;
import com.android.internal.util.function.HeptFunction;
import com.android.internal.util.function.HexConsumer;
import com.android.internal.util.function.HexFunction;
+import com.android.internal.util.function.NonaConsumer;
+import com.android.internal.util.function.NonaFunction;
+import com.android.internal.util.function.OctConsumer;
+import com.android.internal.util.function.OctFunction;
import com.android.internal.util.function.QuadConsumer;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuintConsumer;
@@ -176,7 +180,8 @@ public interface PooledLambda {
Consumer<? super A> function,
A arg1) {
return acquire(PooledLambdaImpl.sPool,
- function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null);
+ function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
+ null);
}
/**
@@ -192,7 +197,8 @@ public interface PooledLambda {
Predicate<? super A> function,
A arg1) {
return acquire(PooledLambdaImpl.sPool,
- function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null);
+ function, 1, 0, ReturnType.BOOLEAN, arg1, null, null, null, null, null, null, null,
+ null);
}
/**
@@ -208,7 +214,8 @@ public interface PooledLambda {
Function<? super A, ? extends R> function,
A arg1) {
return acquire(PooledLambdaImpl.sPool,
- function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null);
+ function, 1, 0, ReturnType.OBJECT, arg1, null, null, null, null, null, null, null,
+ null);
}
/**
@@ -238,7 +245,8 @@ public interface PooledLambda {
A arg1) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null);
+ function, 1, 0, ReturnType.VOID, arg1, null, null, null, null, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -257,7 +265,8 @@ public interface PooledLambda {
BiConsumer<? super A, ? super B> function,
A arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+ function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -274,7 +283,8 @@ public interface PooledLambda {
BiPredicate<? super A, ? super B> function,
A arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
+ function, 2, 0, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -291,7 +301,8 @@ public interface PooledLambda {
BiFunction<? super A, ? super B, ? extends R> function,
A arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
+ function, 2, 0, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -308,7 +319,8 @@ public interface PooledLambda {
BiConsumer<? super A, ? super B> function,
ArgumentPlaceholder<A> arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -325,7 +337,8 @@ public interface PooledLambda {
BiPredicate<? super A, ? super B> function,
ArgumentPlaceholder<A> arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -342,7 +355,8 @@ public interface PooledLambda {
BiFunction<? super A, ? super B, ? extends R> function,
ArgumentPlaceholder<A> arg1, B arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -359,7 +373,8 @@ public interface PooledLambda {
BiConsumer<? super A, ? super B> function,
A arg1, ArgumentPlaceholder<B> arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -376,7 +391,8 @@ public interface PooledLambda {
BiPredicate<? super A, ? super B> function,
A arg1, ArgumentPlaceholder<B> arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.BOOLEAN, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -393,7 +409,8 @@ public interface PooledLambda {
BiFunction<? super A, ? super B, ? extends R> function,
A arg1, ArgumentPlaceholder<B> arg2) {
return acquire(PooledLambdaImpl.sPool,
- function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null);
+ function, 2, 1, ReturnType.OBJECT, arg1, arg2, null, null, null, null, null, null,
+ null);
}
/**
@@ -424,7 +441,8 @@ public interface PooledLambda {
A arg1, B arg2) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null);
+ function, 2, 0, ReturnType.VOID, arg1, arg2, null, null, null, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -444,7 +462,8 @@ public interface PooledLambda {
TriConsumer<? super A, ? super B, ? super C> function,
A arg1, B arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -462,7 +481,8 @@ public interface PooledLambda {
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
A arg1, B arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 0, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -480,7 +500,8 @@ public interface PooledLambda {
TriConsumer<? super A, ? super B, ? super C> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -498,7 +519,8 @@ public interface PooledLambda {
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -516,7 +538,8 @@ public interface PooledLambda {
TriConsumer<? super A, ? super B, ? super C> function,
A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -534,7 +557,8 @@ public interface PooledLambda {
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
A arg1, ArgumentPlaceholder<B> arg2, C arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -552,7 +576,8 @@ public interface PooledLambda {
TriConsumer<? super A, ? super B, ? super C> function,
A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -570,7 +595,8 @@ public interface PooledLambda {
TriFunction<? super A, ? super B, ? super C, ? extends R> function,
A arg1, B arg2, ArgumentPlaceholder<C> arg3) {
return acquire(PooledLambdaImpl.sPool,
- function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 1, ReturnType.OBJECT, arg1, arg2, arg3, null, null, null, null, null,
+ null);
}
/**
@@ -602,7 +628,8 @@ public interface PooledLambda {
A arg1, B arg2, C arg3) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null);
+ function, 3, 0, ReturnType.VOID, arg1, arg2, arg3, null, null, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -623,7 +650,8 @@ public interface PooledLambda {
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
A arg1, B arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -642,7 +670,8 @@ public interface PooledLambda {
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
A arg1, B arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -661,7 +690,8 @@ public interface PooledLambda {
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -680,7 +710,8 @@ public interface PooledLambda {
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
ArgumentPlaceholder<A> arg1, B arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -699,7 +730,8 @@ public interface PooledLambda {
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -718,7 +750,8 @@ public interface PooledLambda {
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
A arg1, ArgumentPlaceholder<B> arg2, C arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -737,7 +770,8 @@ public interface PooledLambda {
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -756,7 +790,8 @@ public interface PooledLambda {
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
A arg1, B arg2, ArgumentPlaceholder<C> arg3, D arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -775,7 +810,8 @@ public interface PooledLambda {
QuadConsumer<? super A, ? super B, ? super C, ? super D> function,
A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -794,7 +830,8 @@ public interface PooledLambda {
QuadFunction<? super A, ? super B, ? super C, ? super D, ? extends R> function,
A arg1, B arg2, C arg3, ArgumentPlaceholder<D> arg4) {
return acquire(PooledLambdaImpl.sPool,
- function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 1, ReturnType.OBJECT, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
}
/**
@@ -827,7 +864,8 @@ public interface PooledLambda {
A arg1, B arg2, C arg3, D arg4) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null);
+ function, 4, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, null, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -849,7 +887,8 @@ public interface PooledLambda {
QuintConsumer<? super A, ? super B, ? super C, ? super D, ? super E> function,
A arg1, B arg2, C arg3, D arg4, E arg5) {
return acquire(PooledLambdaImpl.sPool,
- function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null);
+ function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
+ null);
}
/**
@@ -869,7 +908,8 @@ public interface PooledLambda {
QuintFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? extends R>
function, A arg1, B arg2, C arg3, D arg4, E arg5) {
return acquire(PooledLambdaImpl.sPool,
- function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null);
+ function, 5, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, null, null, null,
+ null);
}
/**
@@ -904,7 +944,8 @@ public interface PooledLambda {
A arg1, B arg2, C arg3, D arg4, E arg5) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null);
+ function, 5, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, null, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -927,7 +968,8 @@ public interface PooledLambda {
HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
return acquire(PooledLambdaImpl.sPool,
- function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null);
+ function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
+ null);
}
/**
@@ -948,7 +990,8 @@ public interface PooledLambda {
HexFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
? extends R> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
return acquire(PooledLambdaImpl.sPool,
- function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null);
+ function, 6, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
+ null);
}
/**
@@ -984,7 +1027,8 @@ public interface PooledLambda {
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null);
+ function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
+ null);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
@@ -1008,7 +1052,8 @@ public interface PooledLambda {
HeptConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
return acquire(PooledLambdaImpl.sPool,
- function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
+ null);
}
/**
@@ -1031,7 +1076,8 @@ public interface PooledLambda {
? super G, ? extends R> function,
A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
return acquire(PooledLambdaImpl.sPool,
- function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ function, 7, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
+ null);
}
/**
@@ -1068,7 +1114,195 @@ public interface PooledLambda {
? super G> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7) {
synchronized (Message.sPoolSync) {
PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
- function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+ function, 7, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, null,
+ null);
+ return Message.obtain().setCallback(callback.recycleOnUse());
+ }
+ }
+
+ /**
+ * {@link PooledRunnable} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @return a {@link PooledRunnable}, equivalent to lambda:
+ * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) }
+ */
+ static <A, B, C, D, E, F, G, H> PooledRunnable obtainRunnable(
+ OctConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, ? super G,
+ ? super H> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7,
+ H arg8) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ null);
+ }
+
+ /**
+ * {@link PooledSupplier} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @return a {@link PooledSupplier}, equivalent to lambda:
+ * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) }
+ */
+ static <A, B, C, D, E, F, G, H, R> PooledSupplier<R> obtainSupplier(
+ OctFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+ ? super G, ? super H, ? extends R> function,
+ A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 8, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ null);
+ }
+
+ /**
+ * Factory of {@link Message}s that contain an
+ * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+ * {@link Message#getCallback internal callback}.
+ *
+ * The callback is equivalent to one obtainable via
+ * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+ *
+ * Note that using this method with {@link android.os.Handler#handleMessage}
+ * is more efficient than the alternative of {@link android.os.Handler#post}
+ * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+ * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+ *
+ * You may optionally set a {@link Message#what} for the message if you want to be
+ * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+ * there's no need to do so
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+ * arg7, arg8) } when handled
+ */
+ static <A, B, C, D, E, F, G, H> Message obtainMessage(
+ OctConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F, ? super G,
+ ? super H> function, A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7,
+ H arg8) {
+ synchronized (Message.sPoolSync) {
+ PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+ function, 8, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ null);
+ return Message.obtain().setCallback(callback.recycleOnUse());
+ }
+ }
+
+ /**
+ * {@link PooledRunnable} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @param arg9 parameter supplied to {@code function} on call
+ * @return a {@link PooledRunnable}, equivalent to lambda:
+ * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) }
+ */
+ static <A, B, C, D, E, F, G, H, I> PooledRunnable obtainRunnable(
+ NonaConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+ ? super G, ? super H, ? super I> function, A arg1, B arg2, C arg3, D arg4,
+ E arg5, F arg6, G arg7, H arg8, I arg9) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ arg9);
+ }
+
+ /**
+ * {@link PooledSupplier} factory
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @param arg9 parameter supplied to {@code function} on call
+ * @return a {@link PooledSupplier}, equivalent to lambda:
+ * {@code () -> function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) }
+ */
+ static <A, B, C, D, E, F, G, H, I, R> PooledSupplier<R> obtainSupplier(
+ NonaFunction<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+ ? super G, ? super H, ? super I, ? extends R> function,
+ A arg1, B arg2, C arg3, D arg4, E arg5, F arg6, G arg7, H arg8, I arg9) {
+ return acquire(PooledLambdaImpl.sPool,
+ function, 9, 0, ReturnType.OBJECT, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ arg9);
+ }
+
+ /**
+ * Factory of {@link Message}s that contain an
+ * ({@link PooledLambda#recycleOnUse auto-recycling}) {@link PooledRunnable} as its
+ * {@link Message#getCallback internal callback}.
+ *
+ * The callback is equivalent to one obtainable via
+ * {@link #obtainRunnable(QuintConsumer, Object, Object, Object, Object, Object)}
+ *
+ * Note that using this method with {@link android.os.Handler#handleMessage}
+ * is more efficient than the alternative of {@link android.os.Handler#post}
+ * with a {@link PooledRunnable} due to the lack of 2 separate synchronization points
+ * when obtaining {@link Message} and {@link PooledRunnable} from pools separately
+ *
+ * You may optionally set a {@link Message#what} for the message if you want to be
+ * able to cancel it via {@link android.os.Handler#removeMessages}, but otherwise
+ * there's no need to do so
+ *
+ * @param function non-capturing lambda(typically an unbounded method reference)
+ * to be invoked on call
+ * @param arg1 parameter supplied to {@code function} on call
+ * @param arg2 parameter supplied to {@code function} on call
+ * @param arg3 parameter supplied to {@code function} on call
+ * @param arg4 parameter supplied to {@code function} on call
+ * @param arg5 parameter supplied to {@code function} on call
+ * @param arg6 parameter supplied to {@code function} on call
+ * @param arg7 parameter supplied to {@code function} on call
+ * @param arg8 parameter supplied to {@code function} on call
+ * @param arg9 parameter supplied to {@code function} on call
+ * @return a {@link Message} invoking {@code function(arg1, arg2, arg3, arg4, arg5, arg6,
+ * arg7, arg8, arg9) } when handled
+ */
+ static <A, B, C, D, E, F, G, H, I> Message obtainMessage(
+ NonaConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F,
+ ? super G, ? super H, ? super I> function, A arg1, B arg2, C arg3, D arg4,
+ E arg5, F arg6, G arg7, H arg8, I arg9) {
+ synchronized (Message.sPoolSync) {
+ PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
+ function, 9, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+ arg9);
return Message.obtain().setCallback(callback.recycleOnUse());
}
}
diff --git a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
index eea1e5f0ac5c..6be626a5134a 100755
--- a/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
+++ b/core/java/com/android/internal/util/function/pooled/PooledLambdaImpl.java
@@ -30,6 +30,12 @@ import com.android.internal.util.function.HeptPredicate;
import com.android.internal.util.function.HexConsumer;
import com.android.internal.util.function.HexFunction;
import com.android.internal.util.function.HexPredicate;
+import com.android.internal.util.function.NonaConsumer;
+import com.android.internal.util.function.NonaFunction;
+import com.android.internal.util.function.NonaPredicate;
+import com.android.internal.util.function.OctConsumer;
+import com.android.internal.util.function.OctFunction;
+import com.android.internal.util.function.OctPredicate;
import com.android.internal.util.function.QuadConsumer;
import com.android.internal.util.function.QuadFunction;
import com.android.internal.util.function.QuadPredicate;
@@ -54,12 +60,12 @@ import java.util.function.Supplier;
* @hide
*/
final class PooledLambdaImpl<R> extends OmniFunction<Object,
- Object, Object, Object, Object, Object, Object, R> {
+ Object, Object, Object, Object, Object, Object, Object, Object, R> {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "PooledLambdaImpl";
- private static final int MAX_ARGS = 7;
+ private static final int MAX_ARGS = 9;
private static final int MAX_POOL_SIZE = 50;
@@ -125,7 +131,7 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
/**
* Bit schema:
- * AAAAAAABCDEEEEEEFFFFFF
+ * AAAAAAAAABCDEEEEEEFFFFFF
*
* Where:
* A - whether {@link #mArgs arg} at corresponding index was specified at
@@ -161,17 +167,19 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
}
@Override
- R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) {
+ R invoke(Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7,
+ Object a8, Object a9) {
checkNotRecycled();
if (DEBUG) {
Log.i(LOG_TAG, this + ".invoke("
+ commaSeparateFirstN(
- new Object[] { a1, a2, a3, a4, a5, a6, a7 },
+ new Object[] { a1, a2, a3, a4, a5, a6, a7, a8, a9 },
LambdaType.decodeArgCount(getFlags(MASK_EXPOSED_AS)))
+ ")");
}
- final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3)
- && fillInArg(a4) && fillInArg(a5) && fillInArg(a6) && fillInArg(a7);
+ final boolean notUsed = fillInArg(a1) && fillInArg(a2) && fillInArg(a3) && fillInArg(a4)
+ && fillInArg(a5) && fillInArg(a6) && fillInArg(a7) && fillInArg(a8)
+ && fillInArg(a9);
int argCount = LambdaType.decodeArgCount(getFlags(MASK_FUNC_TYPE));
if (argCount != LambdaType.MASK_ARG_COUNT) {
for (int i = 0; i < argCount; i++) {
@@ -335,7 +343,7 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
popArg(2), popArg(3), popArg(4), popArg(5));
}
}
- }
+ } break;
case 7: {
switch (returnType) {
@@ -356,7 +364,49 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
popArg(5), popArg(6));
}
}
- }
+ } break;
+
+ case 8: {
+ switch (returnType) {
+ case LambdaType.ReturnType.VOID: {
+ ((OctConsumer) mFunc).accept(popArg(0), popArg(1),
+ popArg(2), popArg(3), popArg(4),
+ popArg(5), popArg(6), popArg(7));
+ return null;
+ }
+ case LambdaType.ReturnType.BOOLEAN: {
+ return (R) (Object) ((OctPredicate) mFunc).test(popArg(0),
+ popArg(1), popArg(2), popArg(3),
+ popArg(4), popArg(5), popArg(6), popArg(7));
+ }
+ case LambdaType.ReturnType.OBJECT: {
+ return (R) ((OctFunction) mFunc).apply(popArg(0), popArg(1),
+ popArg(2), popArg(3), popArg(4),
+ popArg(5), popArg(6), popArg(7));
+ }
+ }
+ } break;
+
+ case 9: {
+ switch (returnType) {
+ case LambdaType.ReturnType.VOID: {
+ ((NonaConsumer) mFunc).accept(popArg(0), popArg(1),
+ popArg(2), popArg(3), popArg(4), popArg(5),
+ popArg(6), popArg(7), popArg(8));
+ return null;
+ }
+ case LambdaType.ReturnType.BOOLEAN: {
+ return (R) (Object) ((NonaPredicate) mFunc).test(popArg(0),
+ popArg(1), popArg(2), popArg(3), popArg(4),
+ popArg(5), popArg(6), popArg(7), popArg(8));
+ }
+ case LambdaType.ReturnType.OBJECT: {
+ return (R) ((NonaFunction) mFunc).apply(popArg(0), popArg(1),
+ popArg(2), popArg(3), popArg(4), popArg(5),
+ popArg(6), popArg(7), popArg(8));
+ }
+ }
+ } break;
}
throw new IllegalStateException("Unknown function type: " + LambdaType.toString(funcType));
}
@@ -419,8 +469,8 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
* Internal non-typesafe factory method for {@link PooledLambdaImpl}
*/
static <E extends PooledLambda> E acquire(Pool pool, Object func,
- int fNumArgs, int numPlaceholders, int fReturnType,
- Object a, Object b, Object c, Object d, Object e, Object f, Object g) {
+ int fNumArgs, int numPlaceholders, int fReturnType, Object a, Object b, Object c,
+ Object d, Object e, Object f, Object g, Object h, Object i) {
PooledLambdaImpl r = acquire(pool);
if (DEBUG) {
Log.i(LOG_TAG,
@@ -436,6 +486,8 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
+ ", e = " + e
+ ", f = " + f
+ ", g = " + g
+ + ", h = " + h
+ + ", i = " + i
+ ")");
}
r.mFunc = func;
@@ -449,6 +501,8 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
setIfInBounds(r.mArgs, 4, e);
setIfInBounds(r.mArgs, 5, f);
setIfInBounds(r.mArgs, 6, g);
+ setIfInBounds(r.mArgs, 7, h);
+ setIfInBounds(r.mArgs, 8, i);
return (E) r;
}
@@ -474,13 +528,14 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
}
@Override
- public OmniFunction<Object, Object, Object, Object, Object, Object, Object, R> negate() {
+ public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
+ R> negate() {
throw new UnsupportedOperationException();
}
@Override
- public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, V> andThen(
- Function<? super R, ? extends V> after) {
+ public <V> OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
+ V> andThen(Function<? super R, ? extends V> after) {
throw new UnsupportedOperationException();
}
@@ -500,7 +555,8 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
}
@Override
- public OmniFunction<Object, Object, Object, Object, Object, Object, Object, R> recycleOnUse() {
+ public OmniFunction<Object, Object, Object, Object, Object, Object, Object, Object, Object,
+ R> recycleOnUse() {
if (DEBUG) Log.i(LOG_TAG, this + ".recycleOnUse()");
mFlags |= FLAG_RECYCLE_ON_USE;
return this;
@@ -584,6 +640,8 @@ final class PooledLambdaImpl<R> extends OmniFunction<Object,
case 5: return "Quint";
case 6: return "Hex";
case 7: return "Hept";
+ case 8: return "Oct";
+ case 9: return "Nona";
default: throw new IllegalArgumentException("" + argCount);
}
}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 849585004bc3..b97a9fa8d1cc 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -934,7 +934,7 @@ public class SystemConfig {
// If the storage model feature flag is disabled, we need to fiddle
// around with permission definitions to return us to pre-Q behavior.
// STOPSHIP(b/112545973): remove once feature enabled by default
- if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+ if (!StorageManager.hasIsolatedStorage()) {
if (newPermissions.contains(android.Manifest.permission.READ_MEDIA_AUDIO) ||
newPermissions.contains(android.Manifest.permission.READ_MEDIA_VIDEO) ||
newPermissions.contains(android.Manifest.permission.READ_MEDIA_IMAGES)) {
diff --git a/core/jni/android_hardware_display_DisplayViewport.cpp b/core/jni/android_hardware_display_DisplayViewport.cpp
index 05f6556bfb35..e74aafe61e00 100644
--- a/core/jni/android_hardware_display_DisplayViewport.cpp
+++ b/core/jni/android_hardware_display_DisplayViewport.cpp
@@ -40,6 +40,7 @@ static struct {
jfieldID deviceWidth;
jfieldID deviceHeight;
jfieldID uniqueId;
+ jfieldID physicalPort;
jfieldID type;
} gDisplayViewportClassInfo;
@@ -54,6 +55,9 @@ static struct {
status_t android_hardware_display_DisplayViewport_toNative(JNIEnv* env, jobject viewportObj,
DisplayViewport* viewport) {
+ static const jclass byteClass = FindClassOrDie(env, "java/lang/Byte");
+ static const jmethodID byteValue = env->GetMethodID(byteClass, "byteValue", "()B");
+
viewport->displayId = env->GetIntField(viewportObj, gDisplayViewportClassInfo.displayId);
viewport->orientation = env->GetIntField(viewportObj, gDisplayViewportClassInfo.orientation);
viewport->deviceWidth = env->GetIntField(viewportObj, gDisplayViewportClassInfo.deviceWidth);
@@ -65,6 +69,12 @@ status_t android_hardware_display_DisplayViewport_toNative(JNIEnv* env, jobject
viewport->uniqueId = ScopedUtfChars(env, uniqueId).c_str();
}
+ viewport->physicalPort = std::nullopt;
+ jobject physicalPort = env->GetObjectField(viewportObj, gDisplayViewportClassInfo.physicalPort);
+ if (physicalPort != nullptr) {
+ viewport->physicalPort = std::make_optional(env->CallByteMethod(physicalPort, byteValue));
+ }
+
viewport->type = static_cast<ViewportType>(env->GetIntField(viewportObj,
gDisplayViewportClassInfo.type));
@@ -112,6 +122,9 @@ int register_android_hardware_display_DisplayViewport(JNIEnv* env) {
gDisplayViewportClassInfo.uniqueId = GetFieldIDOrDie(env,
gDisplayViewportClassInfo.clazz, "uniqueId", "Ljava/lang/String;");
+ gDisplayViewportClassInfo.physicalPort = GetFieldIDOrDie(env,
+ gDisplayViewportClassInfo.clazz, "physicalPort", "Ljava/lang/Byte;");
+
gDisplayViewportClassInfo.type = GetFieldIDOrDie(env,
gDisplayViewportClassInfo.clazz, "type", "I");
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 49d500754290..fa1da4bfbf3a 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -33,8 +33,6 @@
#include <iomanip>
#include <string>
-#include <android-base/stringprintf.h>
-#include <android-base/unique_fd.h>
#include <debuggerd/client.h>
#include <log/log.h>
#include <utils/misc.h>
@@ -50,10 +48,6 @@
namespace android
{
-static inline UniqueFile MakeUniqueFile(const char* path, const char* mode) {
- return UniqueFile(fopen(path, mode), safeFclose);
-}
-
enum {
HEAP_UNKNOWN,
HEAP_DALVIK,
diff --git a/core/jni/android_os_Debug.h b/core/jni/android_os_Debug.h
index 81270ca994bb..c7b731bdb615 100644
--- a/core/jni/android_os_Debug.h
+++ b/core/jni/android_os_Debug.h
@@ -19,6 +19,8 @@
#include <memory>
#include <stdio.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
namespace android {
@@ -27,6 +29,11 @@ inline void safeFclose(FILE* fp) {
}
using UniqueFile = std::unique_ptr<FILE, decltype(&safeFclose)>;
+
+inline UniqueFile MakeUniqueFile(const char* path, const char* mode) {
+ return UniqueFile(fopen(path, mode), safeFclose);
+}
+
UniqueFile OpenSmapsOrRollup(int pid);
} // namespace android
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 8885aac49064..c6ea4e10f63e 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -25,9 +25,10 @@
#include "unicode/uchar.h"
#define PROPERTY_UNDEFINED (-1)
+#define JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY 18
// ICU => JDK mapping
-static int directionality_map[U_CHAR_DIRECTION_COUNT] = {
+static int directionality_map[JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY + 1] = {
0, // U_LEFT_TO_RIGHT (0) => DIRECTIONALITY_LEFT_TO_RIGHT (0)
1, // U_RIGHT_TO_LEFT (1) => DIRECTIONALITY_RIGHT_TO_LEFT (1)
3, // U_EUROPEAN_NUMBER (2) => DIRECTIONALITY_EUROPEAN_NUMBER (3)
@@ -75,7 +76,8 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
int c = 0x00010000 + ((src[i] - 0xD800) << 10) +
(src[i + 1] & 0x3FF);
int dir = u_charDirection(c);
- if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT)
+ if (dir < 0 || dir > JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY
+ || u_charType(c) == U_UNASSIGNED)
dir = PROPERTY_UNDEFINED;
else
dir = directionality_map[dir];
@@ -85,7 +87,8 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
} else {
int c = src[i];
int dir = u_charDirection(c);
- if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT)
+ if (dir < 0 || dir > JAVA_LANG_CHARACTER_MAX_DIRECTIONALITY
+ || u_charType(c) == U_UNASSIGNED)
dest[i] = PROPERTY_UNDEFINED;
else
dest[i] = directionality_map[dir];
@@ -96,7 +99,7 @@ static void getDirectionalities(JNIEnv* env, jobject obj, jcharArray srcArray,
static jint getEastAsianWidth(JNIEnv* env, jobject obj, jchar input)
{
int width = u_getIntPropertyValue(input, UCHAR_EAST_ASIAN_WIDTH);
- if (width < 0 || width >= U_EA_COUNT)
+ if (width < 0 || width > u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH))
width = PROPERTY_UNDEFINED;
return width;
@@ -121,6 +124,7 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
return;
}
+ int maxWidth = u_getIntPropertyMaxValue(UCHAR_EAST_ASIAN_WIDTH);
for (int i = 0; i < count; i++) {
const int srci = start + i;
if (src[srci] >= 0xD800 && src[srci] <= 0xDBFF &&
@@ -129,7 +133,7 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
int c = 0x00010000 + ((src[srci] - 0xD800) << 10) +
(src[srci + 1] & 0x3FF);
int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH);
- if (width < 0 || width >= U_EA_COUNT)
+ if (width < 0 || width > maxWidth)
width = PROPERTY_UNDEFINED;
dest[i++] = width;
@@ -137,7 +141,7 @@ static void getEastAsianWidths(JNIEnv* env, jobject obj, jcharArray srcArray,
} else {
int c = src[srci];
int width = u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH);
- if (width < 0 || width >= U_EA_COUNT)
+ if (width < 0 || width > maxWidth)
width = PROPERTY_UNDEFINED;
dest[i] = width;
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 4c7defbf7358..377e65c33dd0 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -1128,6 +1128,39 @@ static jlong android_os_Process_getPss(JNIEnv* env, jobject clazz, jint pid)
return pss * 1024;
}
+static jlongArray android_os_Process_getRss(JNIEnv* env, jobject clazz, jint pid)
+{
+ // total, file, anon, swap
+ jlong rss[4] = {0, 0, 0, 0};
+ std::string status_path =
+ android::base::StringPrintf("/proc/%d/status", pid);
+ UniqueFile file = MakeUniqueFile(status_path.c_str(), "re");
+
+ char line[256];
+ while (fgets(line, sizeof(line), file.get())) {
+ jlong v;
+ if ( sscanf(line, "VmRSS: %" SCNd64 " kB", &v) == 1) {
+ rss[0] = v;
+ } else if ( sscanf(line, "RssFile: %" SCNd64 " kB", &v) == 1) {
+ rss[1] = v;
+ } else if ( sscanf(line, "RssAnon: %" SCNd64 " kB", &v) == 1) {
+ rss[2] = v;
+ } else if ( sscanf(line, "VmSwap: %" SCNd64 " kB", &v) == 1) {
+ rss[3] = v;
+ }
+ }
+
+ jlongArray rssArray = env->NewLongArray(4);
+ if (rssArray == NULL) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ return NULL;
+ }
+
+ env->SetLongArrayRegion(rssArray, 0, 4, rss);
+
+ return rssArray;
+}
+
jintArray android_os_Process_getPidsForCommands(JNIEnv* env, jobject clazz,
jobjectArray commandNames)
{
@@ -1253,6 +1286,7 @@ static const JNINativeMethod methods[] = {
{"parseProcLine", "([BII[I[Ljava/lang/String;[J[F)Z", (void*)android_os_Process_parseProcLine},
{"getElapsedCpuTime", "()J", (void*)android_os_Process_getElapsedCpuTime},
{"getPss", "(I)J", (void*)android_os_Process_getPss},
+ {"getRss", "(I)[J", (void*)android_os_Process_getRss},
{"getPidsForCommands", "([Ljava/lang/String;)[I", (void*)android_os_Process_getPidsForCommands},
//{"setApplicationObject", "(Landroid/os/IBinder;)V", (void*)android_os_Process_setApplicationObject},
{"killProcessGroup", "(II)I", (void*)android_os_Process_killProcessGroup},
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index e89b5933fdc8..752624b0a0be 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -468,6 +468,10 @@ static jboolean android_view_RenderNode_getAllowForceDark(jlong renderNodePtr) {
return reinterpret_cast<RenderNode*>(renderNodePtr)->stagingProperties().getAllowForceDark();
}
+static jlong android_view_RenderNode_getUniqueId(jlong renderNodePtr) {
+ return reinterpret_cast<RenderNode*>(renderNodePtr)->uniqueId();
+}
+
// ----------------------------------------------------------------------------
// RenderProperties - Animations
// ----------------------------------------------------------------------------
@@ -694,6 +698,7 @@ static const JNINativeMethod gMethods[] = {
{ "nGetHeight", "(J)I", (void*) android_view_RenderNode_getHeight },
{ "nSetAllowForceDark", "(JZ)Z", (void*) android_view_RenderNode_setAllowForceDark },
{ "nGetAllowForceDark", "(J)Z", (void*) android_view_RenderNode_getAllowForceDark },
+ { "nGetUniqueId", "(J)J", (void*) android_view_RenderNode_getUniqueId },
};
int register_android_view_RenderNode(JNIEnv* env) {
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index ec9c8606e8df..ea6e0178bd9c 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -377,6 +377,14 @@ static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong transactionObj,
transaction->setCrop_legacy(ctrl, crop);
}
+static void nativeSetCornerRadius(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jfloat cornerRadius) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ transaction->setCornerRadius(ctrl, cornerRadius);
+}
+
static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint layerStack) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -883,6 +891,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetFlags },
{"nativeSetWindowCrop", "(JJIIII)V",
(void*)nativeSetWindowCrop },
+ {"nativeSetCornerRadius", "(JJF)V",
+ (void*)nativeSetCornerRadius },
{"nativeSetLayerStack", "(JJI)V",
(void*)nativeSetLayerStack },
{"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index 6e661e1ce5b2..b465fb4f7eba 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -234,6 +234,14 @@ message SecureSettingsProto {
}
optional Location location = 31;
+ message LocationAccessCheck {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ optional SettingProto interval_millis = 1 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto delay_millis = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ }
+ optional LocationAccessCheck location_access_check = 73;
+
message LockScreen {
option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -515,5 +523,5 @@ message SecureSettingsProto {
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 73;
+ // Next tag = 74;
}
diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto
index fba2e51937b3..477716982008 100644
--- a/core/proto/android/telephony/enums.proto
+++ b/core/proto/android/telephony/enums.proto
@@ -51,6 +51,7 @@ enum NetworkTypeEnum {
NETWORK_TYPE_TD_SCDMA = 17;
NETWORK_TYPE_IWLAN = 18;
NETWORK_TYPE_LTE_CA = 19;
+ NETWORK_TYPE_NR = 20;
}
// Signal strength levels, primarily used by android/telephony/SignalStrength.java.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6c3085ff2919..b4d5f67e945e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -627,6 +627,13 @@
<!-- ====================================================================== -->
<eat-comment />
+ <!-- Grouping for platform runtime permissions is not accessible to apps
+ @hide
+ @SystemApi
+ -->
+ <permission-group android:name="android.permission-group.UNDEFINED"
+ android:priority="100" />
+
<!-- ====================================================================== -->
<!-- Permissions for accessing user's contacts including personal profile -->
<!-- ====================================================================== -->
@@ -645,14 +652,17 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CONTACTS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readContacts"
android:description="@string/permdesc_readContacts"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows an application to write the user's contacts data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CONTACTS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_writeContacts"
android:description="@string/permdesc_writeContacts"
android:protectionLevel="dangerous" />
@@ -674,14 +684,17 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CALENDAR"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readCalendar"
android:description="@string/permdesc_readCalendar"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows an application to write the user's calendar data.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CALENDAR"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_writeCalendar"
android:description="@string/permdesc_writeCalendar"
android:protectionLevel="dangerous" />
@@ -703,6 +716,7 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.SEND_SMS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_sendSms"
android:description="@string/permdesc_sendSms"
android:permissionFlags="costsMoney"
@@ -712,33 +726,41 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_SMS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_receiveSms"
android:description="@string/permdesc_receiveSms"
- android:protectionLevel="dangerous"/>
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows an application to read SMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_SMS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readSms"
android:description="@string/permdesc_readSms"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows an application to receive WAP push messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_WAP_PUSH"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_receiveWapPush"
android:description="@string/permdesc_receiveWapPush"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows an application to monitor incoming MMS messages.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECEIVE_MMS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_receiveMms"
android:description="@string/permdesc_receiveMms"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- @SystemApi @TestApi Allows an application to read previously received cell broadcast
messages and to register a content observer to get notifications when
@@ -753,9 +775,11 @@
<p>Protection level: dangerous
@hide Pending API council approval -->
<permission android:name="android.permission.READ_CELL_BROADCASTS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readCellBroadcasts"
android:description="@string/permdesc_readCellBroadcasts"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- ====================================================================== -->
<!-- Permissions for accessing external storage -->
@@ -794,6 +818,7 @@
@deprecated replaced by new strongly-typed permission groups in Q.
-->
<permission android:name="android.permission.READ_EXTERNAL_STORAGE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_sdcardRead"
android:description="@string/permdesc_sdcardRead"
android:protectionLevel="dangerous"
@@ -815,6 +840,7 @@
@deprecated replaced by new strongly-typed permission groups in Q.
-->
<permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_sdcardWrite"
android:description="@string/permdesc_sdcardWrite"
android:protectionLevel="dangerous"
@@ -831,9 +857,11 @@
<!-- Allows an application to read the user's shared audio collection. -->
<permission android:name="android.permission.READ_MEDIA_AUDIO"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_audioRead"
android:description="@string/permdesc_audioRead"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Runtime permission controlling access to the user's shared visual media
collection, including images and videos. -->
@@ -846,22 +874,28 @@
<!-- Allows an application to read the user's shared images collection. -->
<permission android:name="android.permission.READ_MEDIA_IMAGES"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_imagesRead"
android:description="@string/permdesc_imagesRead"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows an application to read the user's shared video collection. -->
<permission android:name="android.permission.READ_MEDIA_VIDEO"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_videoRead"
android:description="@string/permdesc_videoRead"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows an application to access any geographic locations persisted in the
user's shared collection. -->
<permission android:name="android.permission.ACCESS_MEDIA_LOCATION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_mediaLocation"
android:description="@string/permdesc_mediaLocation"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- @hide @SystemApi
Allows an application to modify OBB files visible to other apps. -->
@@ -889,20 +923,24 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_FINE_LOCATION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_accessFineLocation"
android:description="@string/permdesc_accessFineLocation"
android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION"
- android:protectionLevel="dangerous|instant" />
+ android:protectionLevel="dangerous|instant"
+ android:usageInfoRequired="true" />
<!-- Allows an app to access approximate location.
Alternatively, you might want {@link #ACCESS_FINE_LOCATION}.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_COARSE_LOCATION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_accessCoarseLocation"
android:description="@string/permdesc_accessCoarseLocation"
android:backgroundPermission="android.permission.ACCESS_BACKGROUND_LOCATION"
- android:protectionLevel="dangerous|instant" />
+ android:protectionLevel="dangerous|instant"
+ android:usageInfoRequired="true" />
<!-- Allows an app to access location in the background. If you
are requesting this, you should also request {@link #ACCESS_FINE_LOCATION}.
@@ -911,9 +949,11 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_accessBackgroundLocation"
android:description="@string/permdesc_accessBackgroundLocation"
- android:protectionLevel="dangerous|instant" />
+ android:protectionLevel="dangerous|instant"
+ android:usageInfoRequired="true" />
<!-- ====================================================================== -->
<!-- Permissions for accessing the call log -->
@@ -951,9 +991,11 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_CALL_LOG"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readCallLog"
android:description="@string/permdesc_readCallLog"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows an application to write (but not read) the user's
call log data.
@@ -969,6 +1011,7 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.WRITE_CALL_LOG"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_writeCallLog"
android:description="@string/permdesc_writeCallLog"
android:protectionLevel="dangerous" />
@@ -979,9 +1022,11 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.PROCESS_OUTGOING_CALLS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_processOutgoingCalls"
android:description="@string/permdesc_processOutgoingCalls"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- ====================================================================== -->
<!-- Permissions for accessing the device telephony -->
@@ -1010,23 +1055,28 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.READ_PHONE_STATE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readPhoneState"
android:description="@string/permdesc_readPhoneState"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows read access to the device's phone number(s). This is a subset of the capabilities
granted by {@link #READ_PHONE_STATE} but is exposed to instant applications.
<p>Protection level: dangerous-->
<permission android:name="android.permission.READ_PHONE_NUMBERS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_readPhoneNumbers"
android:description="@string/permdesc_readPhoneNumbers"
- android:protectionLevel="dangerous|instant" />
+ android:protectionLevel="dangerous|instant"
+ android:usageInfoRequired="true" />
<!-- Allows an application to initiate a phone call without going through
the Dialer user interface for the user to confirm the call.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.CALL_PHONE"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:permissionFlags="costsMoney"
android:label="@string/permlab_callPhone"
android:description="@string/permdesc_callPhone"
@@ -1036,6 +1086,7 @@
<p>Protection level: dangerous
-->
<permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_addVoicemail"
android:description="@string/permdesc_addVoicemail"
android:protectionLevel="dangerous" />
@@ -1044,6 +1095,7 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.USE_SIP"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:description="@string/permdesc_use_sip"
android:label="@string/permlab_use_sip"
android:protectionLevel="dangerous"/>
@@ -1052,6 +1104,7 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ANSWER_PHONE_CALLS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_answerPhoneCalls"
android:description="@string/permdesc_answerPhoneCalls"
android:protectionLevel="dangerous|runtime" />
@@ -1079,6 +1132,7 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCEPT_HANDOVER"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android.label="@string/permlab_acceptHandover"
android:description="@string/permdesc_acceptHandovers"
android:protectionLevel="dangerous" />
@@ -1102,9 +1156,11 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.RECORD_AUDIO"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_recordAudio"
android:description="@string/permdesc_recordAudio"
- android:protectionLevel="dangerous|instant"/>
+ android:protectionLevel="dangerous|instant"
+ android:usageInfoRequired="true" />
<!-- ====================================================================== -->
<!-- Permissions for activity recognition -->
@@ -1123,9 +1179,11 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACTIVITY_RECOGNITION"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_activityRecognition"
android:description="@string/permdesc_activityRecognition"
- android:protectionLevel="dangerous|instant" />
+ android:protectionLevel="dangerous|instant"
+ android:usageInfoRequired="true" />
<!-- ====================================================================== -->
<!-- Permissions for accessing the UCE Service -->
@@ -1171,9 +1229,11 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.CAMERA"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_camera"
android:description="@string/permdesc_camera"
- android:protectionLevel="dangerous|instant" />
+ android:protectionLevel="dangerous|instant"
+ android:usageInfoRequired="true" />
<!-- ====================================================================== -->
@@ -1194,9 +1254,11 @@
measure what is happening inside his/her body, such as heart rate.
<p>Protection level: dangerous -->
<permission android:name="android.permission.BODY_SENSORS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:label="@string/permlab_bodySensors"
android:description="@string/permdesc_bodySensors"
- android:protectionLevel="dangerous" />
+ android:protectionLevel="dangerous"
+ android:usageInfoRequired="true" />
<!-- Allows an app to use fingerprint hardware.
<p>Protection level: normal
@@ -1680,9 +1742,11 @@
<p>Protection level: dangerous
-->
<permission android:name="android.permission.GET_ACCOUNTS"
+ android:permissionGroup="android.permission-group.UNDEFINED"
android:protectionLevel="dangerous"
android:description="@string/permdesc_getAccounts"
- android:label="@string/permlab_getAccounts" />
+ android:label="@string/permlab_getAccounts"
+ android:usageInfoRequired="true" />
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!-- @SystemApi Allows applications to call into AccountAuthenticators.
@@ -4206,6 +4270,12 @@
<permission android:name="android.permission.SMS_FINANCIAL_TRANSACTIONS"
android:protectionLevel="signature|appop" />
+ <!-- Required for apps targeting {@link android.os.Build.VERSION_CODES#P} that want to use
+ {@link android.app.Notification.Builder#setFullScreenIntent notification full screen
+ intents}. -->
+ <permission android:name="android.permission.USE_FULL_SCREEN_INTENT"
+ android:protectionLevel="normal" />
+
<!-- @SystemApi Allows requesting the framework broadcast the
{@link Intent#ACTION_DEVICE_CUSTOMIZATION_READY} intent.
@hide -->
@@ -4217,6 +4287,10 @@
@hide -->
<permission android:name="android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY"
android:protectionLevel="signature|preinstalled" />
+ <!-- @SystemApi Allows wallpaper to be rendered in ambient mode.
+ @hide -->
+ <permission android:name="android.permission.AMBIENT_WALLPAPER"
+ android:protectionLevel="signature|preinstalled" />
<application android:process="system"
android:persistent="true"
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 433ae399c88c..4bf1ad6651ee 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -126,7 +126,6 @@
android:visibility="gone"
android:contentDescription="@string/notification_alerted_content_description"
android:src="@drawable/ic_notifications_alerted"
- android:tint="@color/notification_secondary_text_color_light"
/>
<ImageView
android:id="@+id/profile_badge"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 470e1ccf36e8..244728954aa0 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5532,7 +5532,7 @@
<attr name="solidColor" format="color|reference" />
<!-- @hide The divider for making the selection area. -->
<attr name="selectionDivider" format="reference" />
- <!-- @hide The height of the selection divider. -->
+ <!-- The height of the selection divider. -->
<attr name="selectionDividerHeight" format="dimension" />
<!-- @hide The distance between the two selection dividers. -->
<attr name="selectionDividersDistance" format="dimension" />
@@ -7935,7 +7935,9 @@
wallpaper. -->
<attr name="showMetadataInPreview" format="boolean" />
- <!-- Wallpapers optimized and capable of drawing in ambient mode will return true. -->
+ <!-- Wallpapers optimized and capable of drawing in ambient mode will return true.
+ This feature requires the android.permission.AMBIENT_WALLPAPER permission.
+ @hide @SystemApi -->
<attr name="supportsAmbientMode" format="boolean" />
<!-- Uri that specifies a settings Slice for this wallpaper. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 18d1d5dbdbe3..089c59f3a09f 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1601,6 +1601,10 @@
<attr name="request" />
<attr name="protectionLevel" />
<attr name="permissionFlags" />
+ <!-- If {@code true} applications that target Q <em>must</em> specify the permission usage
+ attributes in their {@code uses-permission} elements or the permission will not be
+ granted. -->
+ <attr name="usageInfoRequired" format="boolean" />
</declare-styleable>
<!-- The <code>permission-group</code> tag declares a logical grouping of
@@ -1700,6 +1704,81 @@
requested. If it does support the feature, it will be as if the manifest didn't
request it at all. -->
<attr name="requiredNotFeature" format="string" />
+
+ <!-- Specify if the app uploads data, or derived data, guarded by this permission.
+
+ If the permission is defined with {@link android.R.attr#usageInfoRequired}
+ {@code true} this <em>must</em> be specified by apps that target Android Q or the
+ permission will not be granted, it will be as if the manifest didn't request it at all.
+ -->
+ <attr name="dataSentOffDevice">
+ <!-- The application may send data, or derived data, guarded by this permission off of the
+ device. -->
+ <enum name="yes" value="1" />
+ <!-- The application may send data, or derived data, guarded by this permission off of the
+ device, however it will only do so when explicitly triggered by a user action. -->
+ <enum name="userTriggered" value="2" />
+ <!-- The application does not send data, or derived data, guarded by this permission off
+ of the device. -->
+ <enum name="no" value="3" />
+ </attr>
+
+ <!-- Specify if the application or its related off-device services provide data,
+ or derived data, guarded by this permission to third parties outside of the developer's
+ organization that do not qualify as data processors.
+
+ If the permission is defined with {@link android.R.attr#usageInfoRequired}
+ {@code true} this <em>must</em> be specified by apps that target Android Q or the
+ permission will not be granted, it will be as if the manifest didn't request it at all.
+ -->
+ <attr name="dataSharedWithThirdParty">
+ <!-- The application or its services may provide data, or derived data, guarded by this
+ permission to third party organizations. -->
+ <enum name="yes" value="1" />
+ <!-- The application or its services may provide data, or derived data, guarded by this
+ permission to third party organizations, however it will only do so when explicitly
+ triggered by a user action. -->
+ <enum name="userTriggered" value="2" />
+ <!-- The application or its services does not provide data, or derived data, guarded by
+ this permission to third party organizations. -->
+ <enum name="no" value="3" />
+ </attr>
+
+ <!-- Specify if the application or its related off-device services use data,
+ or derived data, guarded by this permission for monetization purposes.
+
+ For example, if the data is sold to another party or used for targeting advertisements
+ this must be set to {@code yes}.
+
+ If the permission is defined with {@link android.R.attr#usageInfoRequired}
+ {@code true} this <em>must</em> be specified by apps that target Android Q or the
+ permission will not be granted, it will be as if the manifest didn't request it at all.
+ -->
+ <attr name="dataUsedForMonetization">
+ <!-- The application or its services may use data, or derived data, guarded by this
+ permission for monetization purposes. -->
+ <enum name="yes" value="1" />
+ <!-- The application or its services may use data, or derived data, guarded by this
+ permission for monetization purposes, however it will only do so when explicity
+ triggered by a user action. -->
+ <enum name="userTriggered" value="2" />
+ <!-- The application or its services does not use data, or derived data, guarded by
+ this permission for monetization purposes. -->
+ <enum name="no" value="3" />
+ </attr>
+
+ <!-- Specify how long the application or its related off-device services store
+ data, or derived data, guarded by this permission.
+
+ This can be one of "notRetained", "userSelected", "unlimited", or a number
+ representing the number of weeks the data is retained.
+
+ If the permission is defined with {@link android.R.attr#usageInfoRequired}
+ {@code true} this <em>must</em> be specified by apps that target Android Q or the
+ permission will not be granted, it will be as if the manifest didn't request it at all.
+ -->
+ <attr name="dataRetentionTime" format="string" />
+
</declare-styleable>
<!-- The <code>uses-configuration</code> tag specifies
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index f7b9961c39e8..05a156b69371 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -430,7 +430,7 @@
<dimen name="notification_badge_size">12dp</dimen>
<!-- Size of the alerted icon for notifications -->
- <dimen name="notification_alerted_size">18dp</dimen>
+ <dimen name="notification_alerted_size">12dp</dimen>
<!-- Keyguard dimensions -->
<!-- TEMP -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 63cac5172f8a..5e8af62d1da9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2909,6 +2909,7 @@
<public name="opticalInsetRight" />
<public name="opticalInsetBottom" />
<public name="forceDarkAllowed" />
+ <!-- @hide @SystemApi -->
<public name="supportsAmbientMode" />
<!-- @hide For use by platform and tools only. Developers should not specify this value. -->
<public name="usesNonSdkApi" />
@@ -2922,6 +2923,12 @@
<public name="importantForContentCapture" />
<public name="supportsMultipleDisplays" />
<public name="useAppZygote" />
+ <public name="usageInfoRequired" />
+ <public name="dataSentOffDevice" />
+ <public name="dataSharedWithThirdParty" />
+ <public name="dataUsedForMonetization" />
+ <public name="dataRetentionTime" />
+ <public name="selectionDividerHeight" />
</public-group>
<public-group type="drawable" first-id="0x010800b4">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index bd6d97622a4d..a33f6b2fbf9c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1444,9 +1444,14 @@
<!-- Title shown when the system-provided biometric dialog is shown, asking the user to authenticate. [CHAR LIMIT=40] -->
<string name="biometric_dialog_default_title">Application <xliff:g id="app" example="Gmail">%s</xliff:g> wants to authenticate.</string>
-
<!-- Message shown when biometric hardware is not available [CHAR LIMIT=50] -->
<string name="biometric_error_hw_unavailable">Biometric hardware unavailable</string>
+ <!-- Message shown when biometric authentication was canceled by the user [CHAR LIMIT=50] -->
+ <string name="biometric_error_user_canceled">Authentication canceled</string>
+ <!-- Message shown by the biometric dialog when biometric is not recognized -->
+ <string name="biometric_not_recognized">Not recognized</string>
+ <!-- Message shown when biometric authentication has been canceled [CHAR LIMIT=50] -->
+ <string name="biometric_error_canceled">Authentication canceled</string>
<!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized -->
<string name="fingerprint_acquired_partial">Partial fingerprint detected. Please try again.</string>
@@ -1462,8 +1467,6 @@
<string-array name="fingerprint_acquired_vendor">
</string-array>
- <!-- Message shown by the biometric dialog when biometric is not recognized -->
- <string name="biometric_not_recognized">Not recognized</string>
<!-- Accessibility message announced when a fingerprint has been authenticated [CHAR LIMIT=NONE] -->
<string name="fingerprint_authenticated">Fingerprint authenticated</string>
<!-- Accessibility message announced when a face has been authenticated [CHAR LIMIT=NONE] -->
@@ -1585,14 +1588,14 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_readSyncStats">Allows an app to read the sync stats for an account, including the history of sync events and how much data is synced. </string>
- <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can read from. [CHAR LIMIT=none] -->
<string name="permlab_sdcardRead">read the contents of your shared storage</string>
- <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can read from. [CHAR LIMIT=none] -->
<string name="permdesc_sdcardRead">Allows the app to read the contents of your shared storage.</string>
- <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can write to. [CHAR LIMIT=none] -->
<string name="permlab_sdcardWrite">modify or delete the contents of your shared storage</string>
- <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] -->
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. "shared storage" refers to a storage space on the device that all apps with this permission can write to. [CHAR LIMIT=none] -->
<string name="permdesc_sdcardWrite">Allows the app to write the contents of your shared storage.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
@@ -2983,7 +2986,7 @@
<!-- Label for item in the text selection menu to translate selected text with a translation app. Should be a verb. [CHAR LIMIT=30] -->
<string name="translate">Translate</string>
-
+
<!-- Accessibility description for an item in the text selection menu to translate selected text with a translation app. [CHAR LIMIT=NONE] -->
<string name="translate_desc">Translate selected text</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e251e27a5496..783f1f355e87 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2406,7 +2406,9 @@
<!-- Biometric messages -->
<java-symbol type="string" name="biometric_dialog_default_title" />
<java-symbol type="string" name="biometric_error_hw_unavailable" />
+ <java-symbol type="string" name="biometric_error_user_canceled" />
<java-symbol type="string" name="biometric_not_recognized" />
+ <java-symbol type="string" name="biometric_error_canceled" />
<!-- Fingerprint messages -->
<java-symbol type="string" name="fingerprint_error_unable_to_process" />
@@ -3499,4 +3501,8 @@
<java-symbol type="string" name="config_defaultAssistantComponentName" />
<java-symbol type="id" name="transition_overlay_view_tag" />
+
+ <java-symbol type="dimen" name="rounded_corner_radius" />
+ <java-symbol type="dimen" name="rounded_corner_radius_top" />
+ <java-symbol type="dimen" name="rounded_corner_radius_bottom" />
</resources>
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 305d2af2122d..a8f9e8a5891b 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -664,7 +664,9 @@ public class SettingsBackupTest {
Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE,
Settings.Secure.FLASHLIGHT_AVAILABLE,
Settings.Secure.FLASHLIGHT_ENABLED,
- Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED);
+ Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
+ Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MILLIS,
+ Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS);
@Test
public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/text/AndroidCharacterTest.java b/core/tests/coretests/src/android/text/AndroidCharacterTest.java
new file mode 100644
index 000000000000..0c7e730e78e4
--- /dev/null
+++ b/core/tests/coretests/src/android/text/AndroidCharacterTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,d
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@Presubmit
+@SmallTest
+public class AndroidCharacterTest {
+
+ @Test
+ public void testGetDirectionalities_nonSupplementaryCharacters() {
+ int size = Character.MAX_VALUE + 1
+ - (Character.MAX_SURROGATE - Character.MIN_SURROGATE + 1);
+ char[] chars = new char[size];
+ byte[] java_lang_results = new byte[size];
+ int index = 0;
+ for (int cp = 0; cp <= Character.MAX_VALUE; cp++) {
+ if (cp < Character.MIN_SURROGATE || cp > Character.MAX_SURROGATE) {
+ chars[index] = (char) cp;
+ java_lang_results[index] = Character.getDirectionality(cp);
+ index++;
+ }
+ }
+
+ byte[] android_text_results = new byte[size];
+ AndroidCharacter.getDirectionalities(chars, android_text_results, index);
+ assertArrayEquals(java_lang_results, android_text_results);
+ }
+
+ @Test
+ public void testGetDirectionalities_supplementaryCharacters() {
+ int maxNumberOfChars = Character.MAX_CODE_POINT - Character.MIN_SUPPLEMENTARY_CODE_POINT
+ + 1;
+ int size = maxNumberOfChars * 2;
+ char[] chars = new char[size];
+ byte[] java_lang_results = new byte[size];
+ int index = 0;
+ for (int cp = Character.MIN_SUPPLEMENTARY_CODE_POINT; cp <= Character.MAX_CODE_POINT;
+ cp++) {
+ chars[index] = Character.highSurrogate(cp);
+ chars[index + 1] = Character.lowSurrogate(cp);
+ java_lang_results[index] = java_lang_results[index + 1] = Character
+ .getDirectionality(cp);
+ index += 2;
+ }
+
+ byte[] android_text_results = new byte[size];
+ AndroidCharacter.getDirectionalities(chars, android_text_results, index);
+ assertArrayEquals(java_lang_results, android_text_results);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 30309cf64e96..8691e73f82fb 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -557,6 +557,62 @@ public class BinderCallsStatsTest {
assertEquals(0, bcs.getExceptionCounts().size());
}
+ @Test
+ public void testOverflow_sameEntry() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(true);
+ bcs.setSamplingInterval(1);
+ bcs.setMaxBinderCallStats(2);
+
+ Binder binder = new Binder();
+ CallSession callSession = bcs.callStarted(binder, 1);
+ bcs.time += 10;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ callSession = bcs.callStarted(binder, 1);
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ callSession = bcs.callStarted(binder, 1);
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ BinderCallsStats.UidEntry uidEntry = bcs.getUidEntries().get(WORKSOURCE_UID);
+ List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
+ assertEquals(1, callStatsList.size());
+ BinderCallsStats.CallStat callStats = callStatsList.get(0);
+ assertEquals(3, callStats.callCount);
+ }
+
+ @Test
+ public void testOverflow_overflowEntry() {
+ TestBinderCallsStats bcs = new TestBinderCallsStats();
+ bcs.setDetailedTracking(true);
+ bcs.setSamplingInterval(1);
+ bcs.setMaxBinderCallStats(1);
+
+ Binder binder = new Binder();
+ CallSession callSession = bcs.callStarted(binder, 1);
+ bcs.time += 10;
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ callSession = bcs.callStarted(binder, 2);
+ bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+ List<BinderCallsStats.ExportedCallStat> callStatsList = bcs.getExportedCallStats();
+ assertEquals(2, callStatsList.size());
+ BinderCallsStats.ExportedCallStat callStats = callStatsList.get(0);
+ assertEquals(1, callStats.callCount);
+ assertEquals("1", callStats.methodName);
+ assertEquals("android.os.Binder", callStats.className);
+ assertEquals(CALLING_UID, callStats.callingUid);
+
+ callStats = callStatsList.get(1);
+ assertEquals(1, callStats.callCount);
+ assertEquals("-1", callStats.methodName);
+ assertEquals("com.android.internal.os.BinderCallsStats$OverflowBinder",
+ callStats.className);
+ assertEquals(CALLING_UID, callStats.callingUid);
+ }
+
class TestBinderCallsStats extends BinderCallsStats {
public int callingUid = CALLING_UID;
public int workSourceUid = WORKSOURCE_UID;
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
index 385bad5ab3f9..b242a34cc703 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
@@ -39,9 +39,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
-import java.util.List;
import java.util.function.Predicate;
-import java.util.stream.Collectors;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -58,8 +56,8 @@ public class KernelCpuThreadReaderTest {
1000, 2000, 3000, 4000,
};
private static final int[][] THREAD_CPU_TIMES = {
- {100, 0, 0, 100},
- {0, 0, 9999999, 0},
+ {1, 0, 0, 1},
+ {0, 0, 0, 0},
{1000, 1000, 1000, 1000},
{0, 1, 2, 3},
};
@@ -110,42 +108,6 @@ public class KernelCpuThreadReaderTest {
}
@Test
- public void testReader_filtersLowTotalCpuUsage() throws IOException {
- KernelCpuThreadReader.Injector processUtils =
- new KernelCpuThreadReader.Injector() {
- @Override
- public int myPid() {
- return PROCESS_ID;
- }
-
- @Override
- public int myUid() {
- return UID;
- }
-
- @Override
- public int getUidForPid(int pid) {
- return 0;
- }
- };
- setupDirectory(mProcDirectory.toPath().resolve("self"), new int[]{1, 2}, PROCESS_NAME,
- THREAD_NAMES, new int[]{1000, 2000}, new int[][]{{0, 1}, {100, 0}});
-
- final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader(
- mProcDirectory.toPath(),
- mProcDirectory.toPath().resolve("self/task/1/time_in_state"),
- processUtils);
- final KernelCpuThreadReader.ProcessCpuUsage processCpuUsage =
- kernelCpuThreadReader.getCurrentProcessCpuUsage();
-
- List<Integer> threadIds = processCpuUsage.threadCpuUsages.stream()
- .map(t -> t.threadId)
- .collect(Collectors.toList());
- assertEquals(1, threadIds.size());
- assertEquals(2, (long) threadIds.get(0));
- }
-
- @Test
public void testReader_byUids() throws IOException {
int[] uids = new int[]{0, 2, 3, 4, 5, 6000};
Predicate<Integer> uidPredicate = uid -> uid == 0 || uid >= 4;
@@ -172,7 +134,7 @@ public class KernelCpuThreadReaderTest {
setupDirectory(mProcDirectory.toPath().resolve(String.valueOf(uid)),
new int[]{uid * 10},
"process" + uid, new String[]{"thread" + uid}, new int[]{1000},
- new int[][]{{uid + 100}});
+ new int[][]{{uid}});
}
final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader(
mProcDirectory.toPath(),
@@ -189,7 +151,7 @@ public class KernelCpuThreadReaderTest {
int uid = expectedUids[i];
checkResults(processCpuUsage, kernelCpuThreadReader.getCpuFrequenciesKhz(),
uid, uid, new int[]{uid * 10}, "process" + uid, new String[]{"thread" + uid},
- new int[]{1000}, new int[][]{{uid + 100}});
+ new int[]{1000}, new int[][]{{uid}});
}
}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 3b0dc9d9f125..135c13703131 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -64,7 +64,7 @@ public class Canvas extends BaseCanvas {
public boolean isRecordingFor(Object o) { return false; }
// may be null
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 117521088)
private Bitmap mBitmap;
// optional field set by the caller
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 2e1d81a294e9..bf114b969b67 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -1779,6 +1779,40 @@ public abstract class ColorSpace {
}
/**
+ * <p>Computes the chromatic adaptation transform from the specified
+ * source white point to the specified destination white point.</p>
+ *
+ * <p>The transform is computed using the von Kries method, described
+ * in more details in the documentation of {@link Adaptation}. The
+ * {@link Adaptation} enum provides different matrices that can be
+ * used to perform the adaptation.</p>
+ *
+ * @param adaptation The adaptation method
+ * @param srcWhitePoint The white point to adapt from
+ * @param dstWhitePoint The white point to adapt to
+ * @return A 3x3 matrix as a non-null array of 9 floats
+ */
+ @NonNull
+ @Size(9)
+ public static float[] chromaticAdaptation(@NonNull Adaptation adaptation,
+ @NonNull @Size(min = 2, max = 3) float[] srcWhitePoint,
+ @NonNull @Size(min = 2, max = 3) float[] dstWhitePoint) {
+ float[] srcXyz = srcWhitePoint.length == 3 ?
+ Arrays.copyOf(srcWhitePoint, 3) : xyYToXyz(srcWhitePoint);
+ float[] dstXyz = dstWhitePoint.length == 3 ?
+ Arrays.copyOf(dstWhitePoint, 3) : xyYToXyz(dstWhitePoint);
+
+ if (compare(srcXyz, dstXyz)) {
+ return new float[] {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f
+ };
+ }
+ return chromaticAdaptation(adaptation.mTransform, srcXyz, dstXyz);
+ }
+
+ /**
* Implementation of the CIE XYZ color space. Assumes the white point is D50.
*/
@AnyThread
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 45d7a2178b84..d6f08b92a648 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -1173,6 +1173,22 @@ public final class RenderNode {
return nGetAllowForceDark(mNativeRenderNode);
}
+ /**
+ * Returns the unique ID that identifies this RenderNode. This ID is unique for the
+ * lifetime of the process. IDs are reset on process death, and are unique only within
+ * the process.
+ *
+ * This ID is intended to be used with debugging tools to associate a particular
+ * RenderNode across different debug dumping & inspection tools. For example
+ * a View layout inspector should include the unique ID for any RenderNodes that it owns
+ * to associate the drawing content with the layout content.
+ *
+ * @return the unique ID for this RenderNode
+ */
+ public long getUniqueId() {
+ return nGetUniqueId(mNativeRenderNode);
+ }
+
///////////////////////////////////////////////////////////////////////////
// Animations
///////////////////////////////////////////////////////////////////////////
@@ -1479,4 +1495,7 @@ public final class RenderNode {
@CriticalNative
private static native boolean nGetAllowForceDark(long renderNode);
+
+ @CriticalNative
+ private static native long nGetUniqueId(long renderNode);
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index acb46b39daf5..dbe6e8f4eebb 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -163,9 +163,6 @@ public class Typeface {
private int[] mSupportedAxes;
private static final int[] EMPTY_AXES = {};
- // The underlying font families.
- private final FontFamily[] mFamilies;
-
@UnsupportedAppUsage
private static void setDefault(Typeface t) {
sDefaultTypeface = t;
@@ -655,10 +652,11 @@ public class Typeface {
* Returns the maximum capacity of custom fallback families.
*
* This includes the the first font family passed to the constructor.
+ * It is guaranteed that the value will be greater than or equal to 64.
*
* @return the maximum number of font families for the custom fallback
*/
- public static @IntRange(from = 1) int getMaxCustomFallbackCount() {
+ public static @IntRange(from = 64) int getMaxCustomFallbackCount() {
return MAX_CUSTOM_FALLBACK;
}
@@ -731,21 +729,17 @@ public class Typeface {
public Typeface build() {
final int userFallbackSize = mFamilies.size();
final FontFamily[] fallback = SystemFonts.getSystemFallback(mFallbackName);
- final FontFamily[] fullFamilies = new FontFamily[fallback.length + userFallbackSize];
final long[] ptrArray = new long[fallback.length + userFallbackSize];
for (int i = 0; i < userFallbackSize; ++i) {
ptrArray[i] = mFamilies.get(i).getNativePtr();
- fullFamilies[i] = mFamilies.get(i);
}
for (int i = 0; i < fallback.length; ++i) {
ptrArray[i + userFallbackSize] = fallback[i].getNativePtr();
- fullFamilies[i + userFallbackSize] = fallback[i];
}
final int weight = mStyle == null ? 400 : mStyle.getWeight();
final int italic =
(mStyle == null || mStyle.getSlant() == FontStyle.FONT_SLANT_UPRIGHT) ? 0 : 1;
-
- return new Typeface(nativeCreateFromArray(ptrArray, weight, italic), fullFamilies);
+ return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
}
}
@@ -810,7 +804,7 @@ public class Typeface {
}
}
- typeface = new Typeface(nativeCreateFromTypeface(ni, style), family.mFamilies);
+ typeface = new Typeface(nativeCreateFromTypeface(ni, style));
styles.put(style, typeface);
}
return typeface;
@@ -878,8 +872,7 @@ public class Typeface {
}
typeface = new Typeface(
- nativeCreateFromTypefaceWithExactStyle(
- base.native_instance, weight, italic), base.mFamilies);
+ nativeCreateFromTypefaceWithExactStyle(base.native_instance, weight, italic));
innerCache.put(key, typeface);
}
return typeface;
@@ -889,8 +882,7 @@ public class Typeface {
public static Typeface createFromTypefaceWithVariation(@Nullable Typeface family,
@NonNull List<FontVariationAxis> axes) {
final Typeface base = family == null ? Typeface.DEFAULT : family;
- return new Typeface(nativeCreateFromTypefaceWithVariation(base.native_instance, axes),
- base.mFamilies);
+ return new Typeface(nativeCreateFromTypefaceWithVariation(base.native_instance, axes));
}
/**
@@ -996,7 +988,7 @@ public class Typeface {
ptrArray[i] = families[i].getNativePtr();
}
return new Typeface(nativeCreateFromArray(ptrArray,
- RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE), families);
+ RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
}
/**
@@ -1044,19 +1036,6 @@ public class Typeface {
}
native_instance = ni;
- mFamilies = new FontFamily[0];
- sRegistry.registerNativeAllocation(this, native_instance);
- mStyle = nativeGetStyle(ni);
- mWeight = nativeGetWeight(ni);
- }
-
- private Typeface(long ni, @NonNull FontFamily[] families) {
- if (ni == 0) {
- throw new IllegalStateException("native typeface cannot be made");
- }
-
- native_instance = ni;
- mFamilies = families;
sRegistry.registerNativeAllocation(this, native_instance);
mStyle = nativeGetStyle(ni);
mWeight = nativeGetWeight(ni);
@@ -1083,8 +1062,7 @@ public class Typeface {
final Typeface base = systemFontMap.get(alias.getToName());
final int weight = alias.getWeight();
final Typeface newFace = weight == 400 ? base :
- new Typeface(nativeCreateWeightAlias(base.native_instance, weight),
- base.mFamilies);
+ new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
systemFontMap.put(alias.getName(), newFace);
}
}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index caf610b8c236..5bd59d479876 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -713,11 +713,12 @@ public abstract class Drawable {
}
/**
- * Whether this drawable requests projection.
+ * Whether this drawable requests projection. Indicates that the
+ * {@link android.graphics.RenderNode} this Drawable will draw into should be drawn immediately
+ * after the closest ancestor RenderNode containing a projection receiver.
*
- * @hide magic!
+ * @see android.graphics.RenderNode#setProjectBackwards(boolean)
*/
- @UnsupportedAppUsage
public boolean isProjected() {
return false;
}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index d2a8f02cc6a7..4a639102192f 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -29,6 +29,7 @@
#include <SkPathOps.h>
#include <algorithm>
+#include <atomic>
#include <sstream>
#include <string>
@@ -47,8 +48,14 @@ private:
TreeInfo* mTreeInfo;
};
+static int64_t generateId() {
+ static std::atomic<int64_t> sNextId{1};
+ return sNextId++;
+}
+
RenderNode::RenderNode()
- : mDirtyPropertyFields(0)
+ : mUniqueId(generateId())
+ , mDirtyPropertyFields(0)
, mNeedsDisplayListSync(false)
, mDisplayList(nullptr)
, mStagingDisplayList(nullptr)
@@ -444,5 +451,38 @@ const SkPath* RenderNode::getClippedOutline(const SkRect& clipRect) const {
return &mClippedOutlineCache.clippedOutline;
}
+using StringBuffer = FatVector<char, 128>;
+
+template <typename... T>
+static void format(StringBuffer& buffer, const std::string_view& format, T... args) {
+ buffer.resize(buffer.capacity());
+ while (1) {
+ int needed = snprintf(buffer.data(), buffer.size(),
+ format.data(), std::forward<T>(args)...);
+ if (needed < 0) {
+ buffer[0] = '\0';
+ buffer.resize(1);
+ return;
+ }
+ if (needed < buffer.size()) {
+ buffer.resize(needed + 1);
+ return;
+ }
+ buffer.resize(buffer.size() * 2);
+ }
+}
+
+void RenderNode::markDrawStart(SkCanvas& canvas) {
+ StringBuffer buffer;
+ format(buffer, "RenderNode(id=%d, name='%s')", uniqueId(), getName());
+ canvas.drawAnnotation(SkRect::MakeWH(getWidth(), getHeight()), buffer.data(), nullptr);
+}
+
+void RenderNode::markDrawEnd(SkCanvas& canvas) {
+ StringBuffer buffer;
+ format(buffer, "/RenderNode(id=%d, name='%s')", uniqueId(), getName());
+ canvas.drawAnnotation(SkRect::MakeWH(getWidth(), getHeight()), buffer.data(), nullptr);
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index be0b46b1c45f..6060123ed759 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -213,6 +213,11 @@ public:
UsageHint usageHint() const { return mUsageHint; }
+ int64_t uniqueId() const { return mUniqueId; }
+
+ void markDrawStart(SkCanvas& canvas);
+ void markDrawEnd(SkCanvas& canvas);
+
private:
void computeOrderingImpl(RenderNodeOp* opState,
std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
@@ -233,6 +238,7 @@ private:
void incParentRefCount() { mParentCount++; }
void decParentRefCount(TreeObserver& observer, TreeInfo* info = nullptr);
+ const int64_t mUniqueId;
String8 mName;
sp<VirtualLightRefBase> mUserContext;
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index ea14d11b7b3e..d80cb6d1ab70 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -115,12 +115,26 @@ void RenderNodeDrawable::onDraw(SkCanvas* canvas) {
}
}
+class MarkDraw {
+public:
+ explicit MarkDraw(SkCanvas& canvas, RenderNode& node) : mCanvas(canvas), mNode(node) {
+ if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
+ mNode.markDrawStart(mCanvas);
+ }
+ }
+ ~MarkDraw() {
+ if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
+ mNode.markDrawEnd(mCanvas);
+ }
+ }
+private:
+ SkCanvas& mCanvas;
+ RenderNode& mNode;
+};
+
void RenderNodeDrawable::forceDraw(SkCanvas* canvas) {
RenderNode* renderNode = mRenderNode.get();
- if (CC_UNLIKELY(Properties::skpCaptureEnabled)) {
- SkRect dimensions = SkRect::MakeWH(renderNode->getWidth(), renderNode->getHeight());
- canvas->drawAnnotation(dimensions, renderNode->getName(), nullptr);
- }
+ MarkDraw _marker{*canvas, *renderNode};
// We only respect the nothingToDraw check when we are composing a layer. This
// ensures that we paint the layer even if it is not currently visible in the
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index d84ec8508ee4..9a6df75fedd9 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -263,6 +263,15 @@ bool VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe
tailPNext = &blend->pNext;
}
+ VkPhysicalDeviceSamplerYcbcrConversionFeatures* ycbcrFeature;
+ ycbcrFeature = (VkPhysicalDeviceSamplerYcbcrConversionFeatures*) malloc(
+ sizeof(VkPhysicalDeviceSamplerYcbcrConversionFeatures));
+ LOG_ALWAYS_FATAL_IF(!ycbcrFeature);
+ ycbcrFeature->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES;
+ ycbcrFeature->pNext = nullptr;
+ *tailPNext = ycbcrFeature;
+ tailPNext = &ycbcrFeature->pNext;
+
// query to get the physical device features
mGetPhysicalDeviceFeatures2(mPhysicalDevice, &features);
// this looks like it would slow things down,
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index ff2fad443bcb..ae87998a1615 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -121,18 +121,4 @@ interface ILocationManager
// used by gts tests to verify throttling whitelist
String[] getBackgroundThrottlingWhitelist();
-
- /**
- * Allow the {@link android.location.LocationManager#getNetworkProviderPackage location
- * provider} to start the UI to modify the location permission for a package.
- *
- * <p>Can only be called by the location provider.
- *
- * @param packageName The package the permission belongs to
- * @param permission The (individual) permission to switch
- *
- * @return A pending intent that starts the permission management UI or {@code null} if the
- * intent cannot be created
- */
- PendingIntent createManageLocationPermissionIntent(in String packageName, in String permission);
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index b66ceef29ceb..3bf98b352b40 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -22,7 +22,6 @@ import static android.Manifest.permission.LOCATION_HARDWARE;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import android.Manifest;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
@@ -2401,29 +2400,4 @@ public class LocationManager {
return null;
}
}
-
- /**
- * Allow the {@link android.location.LocationManager#getNetworkProviderPackage location
- * provider} to start the UI to modify the location permission for a package.
- *
- * <p>Can only be called by the location provider.
- *
- * @param packageName The package the permission belongs to
- * @param permission The (individual) location permission to switch
- *
- * @return A one-shot pending intent that starts the permission management UI or {@code null} if
- * the intent cannot be created
- *
- * @hide
- */
- @SystemApi
- public @Nullable PendingIntent createManageLocationPermissionIntent(@NonNull String packageName,
- @NonNull String permission) {
- try {
- return mService.createManageLocationPermissionIntent(packageName, permission);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- return null;
- }
- }
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index ff1bdd47f565..d10900e5d160 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -541,6 +541,7 @@ public class AudioManager {
* Adjusting the volume due to a hardware key press.
* @hide
*/
+ @SystemApi
public static final int FLAG_FROM_KEY = 1 << 12;
private static final String[] FLAG_NAMES = {
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index b047f8de515d..111dd0f0b63e 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -29,6 +29,7 @@ import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
+import android.media.MediaPlayer2.DrmInfo;
import android.media.MediaPlayer2Proto.PlayerMessage;
import android.media.MediaPlayer2Proto.Value;
import android.net.Uri;
@@ -72,7 +73,11 @@ import java.util.Map;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
@@ -300,21 +305,7 @@ public class MediaPlayer2 implements AutoCloseable
private volatile float mVolume = 1.0f;
private VideoSize mVideoSize = new VideoSize(0, 0);
- // TODO: create per-source drm fields in SourceInfo
- // Modular DRM
- private final Object mDrmLock = new Object();
- //--- guarded by |mDrmLock| start
- private UUID mDrmUUID;
- private DrmInfo mDrmInfo;
- private MediaDrm mDrmObj;
- private byte[] mDrmSessionId;
- private boolean mDrmInfoResolved;
- private boolean mActiveDrmScheme;
- private boolean mDrmConfigAllowed;
- private boolean mDrmProvisioningInProgress;
- private boolean mPrepareDrmInProgress;
- private ProvisioningThread mDrmProvisioningThread;
- //--- guarded by |mDrmLock| end
+ private ExecutorService mDrmThreadPool = Executors.newCachedThreadPool();
// Creating a dummy audio track, used for keeping session id alive
private final Object mSessionIdLock = new Object();
@@ -328,6 +319,7 @@ public class MediaPlayer2 implements AutoCloseable
private final List<Task> mPendingTasks = new LinkedList<>();
@GuardedBy("mTaskLock")
private Task mCurrentTask;
+ private final AtomicLong mTaskIdGenerator = new AtomicLong(0);
@GuardedBy("mTaskLock")
boolean mIsPreviousCommandSeekTo = false;
@@ -413,15 +405,13 @@ public class MediaPlayer2 implements AutoCloseable
mHandlerThread = null;
}
- setCurrentSourceInfo(null);
- clearNextSourceInfos();
+ clearSourceInfos();
// Modular DRM clean up
mOnDrmConfigHelper = null;
synchronized (mDrmEventCbLock) {
mDrmEventCallbackRecords.clear();
}
- resetDrmState();
native_release();
@@ -461,13 +451,8 @@ public class MediaPlayer2 implements AutoCloseable
synchronized (mDrmEventCbLock) {
mDrmEventCallbackRecords.clear();
}
- setCurrentSourceInfo(null);
- clearNextSourceInfos();
- synchronized (mTaskLock) {
- mPendingTasks.clear();
- mIsPreviousCommandSeekTo = false;
- }
+ clearSourceInfos();
stayAwake(false);
native_reset();
@@ -481,7 +466,6 @@ public class MediaPlayer2 implements AutoCloseable
mTaskHandler.removeCallbacksAndMessages(null);
}
- resetDrmState();
}
private native void native_reset();
@@ -706,13 +690,14 @@ public class MediaPlayer2 implements AutoCloseable
}
synchronized (mSrcLock) {
- setCurrentSourceInfo(new SourceInfo(dsd));
+ setCurrentSourceInfo_l(new SourceInfo(dsd));
handleDataSource(true /* isCurrent */, dsd, mCurrentSourceInfo.mId);
}
} finally {
dsd.close();
}
}
+
});
}
@@ -732,7 +717,7 @@ public class MediaPlayer2 implements AutoCloseable
void process() {
Media2Utils.checkArgument(dsd != null, "the DataSourceDesc cannot be null");
synchronized (mSrcLock) {
- clearNextSourceInfos();
+ clearNextSourceInfos_l();
mNextSourceInfos.add(new SourceInfo(dsd));
}
prepareNextDataSource();
@@ -758,7 +743,7 @@ public class MediaPlayer2 implements AutoCloseable
}
synchronized (mSrcLock) {
- clearNextSourceInfos();
+ clearNextSourceInfos_l();
for (DataSourceDesc dsd : dsds) {
if (dsd != null) {
mNextSourceInfos.add(new SourceInfo(dsd));
@@ -781,7 +766,9 @@ public class MediaPlayer2 implements AutoCloseable
return addTask(new Task(CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES, false) {
@Override
void process() {
- clearNextSourceInfos();
+ synchronized (mSrcLock) {
+ clearNextSourceInfos_l();
+ }
}
});
}
@@ -1073,7 +1060,7 @@ public class MediaPlayer2 implements AutoCloseable
SourceInfo nextSourceInfo = mNextSourceInfos.peek();
if (nextSourceInfo.mStateAsNextSource == NEXT_SOURCE_STATE_PREPARED) {
// Switch to next source only when it has been prepared.
- setCurrentSourceInfo(mNextSourceInfos.poll());
+ setCurrentSourceInfo_l(mNextSourceInfos.poll());
long srcId = mCurrentSourceInfo.mId;
try {
@@ -2173,7 +2160,7 @@ public class MediaPlayer2 implements AutoCloseable
final int what = msg.arg1;
final int extra = msg.arg2;
- final SourceInfo sourceInfo = getSourceInfoById(srcId);
+ final SourceInfo sourceInfo = getSourceInfo(srcId);
if (sourceInfo == null) {
return;
}
@@ -2227,11 +2214,11 @@ public class MediaPlayer2 implements AutoCloseable
Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
} else if (msg.obj instanceof byte[]) {
// The PlayerMessage was parsed already in postEventFromNative
- final DrmInfo drmInfo;
- synchronized (mDrmLock) {
- if (mDrmInfo != null) {
- drmInfo = mDrmInfo.makeCopy();
+ final DrmInfo drmInfo;
+ synchronized (sourceInfo) {
+ if (sourceInfo.mDrmInfo != null) {
+ drmInfo = sourceInfo.mDrmInfo.makeCopy();
} else {
drmInfo = null;
}
@@ -2303,7 +2290,7 @@ public class MediaPlayer2 implements AutoCloseable
}
});
- SourceInfo src = getSourceInfoById(srcId);
+ SourceInfo src = getSourceInfo(srcId);
if (src != null) {
src.mBufferedPercentage.set(percent);
}
@@ -2504,6 +2491,7 @@ public class MediaPlayer2 implements AutoCloseable
return;
}
+ final SourceInfo sourceInfo = mp.getSourceInfo(srcId);
switch (what) {
case MEDIA_DRM_INFO:
// We need to derive mDrmInfo before prepare() returns so processing it here
@@ -2511,7 +2499,7 @@ public class MediaPlayer2 implements AutoCloseable
// notification looper so its handleMessage might process the event after prepare()
// has returned.
Log.v(TAG, "postEventFromNative MEDIA_DRM_INFO");
- if (obj != null) {
+ if (obj != null && sourceInfo != null) {
PlayerMessage playerMsg;
try {
playerMsg = PlayerMessage.parseFrom(obj);
@@ -2520,11 +2508,12 @@ public class MediaPlayer2 implements AutoCloseable
break;
}
DrmInfo drmInfo = new DrmInfo(playerMsg);
- synchronized (mp.mDrmLock) {
- mp.mDrmInfo = drmInfo;
+ synchronized (sourceInfo) {
+ sourceInfo.mDrmInfo = drmInfo;
}
} else {
- Log.w(TAG, "MEDIA_DRM_INFO msg.obj of unexpected type " + obj);
+ Log.w(TAG, "MEDIA_DRM_INFO sourceInfo " + sourceInfo
+ + " msg.obj of unexpected type " + obj);
}
break;
@@ -2533,8 +2522,10 @@ public class MediaPlayer2 implements AutoCloseable
// mainly for prepare() use case. For prepare(), this still can run to a race
// condition b/c MediaPlayerNative releases the prepare() lock before calling notify
// so we also set mDrmInfoResolved in prepare().
- synchronized (mp.mDrmLock) {
- mp.mDrmInfoResolved = true;
+ if (sourceInfo != null) {
+ synchronized (sourceInfo) {
+ sourceInfo.mDrmInfoResolved = true;
+ }
}
break;
}
@@ -3211,9 +3202,7 @@ public class MediaPlayer2 implements AutoCloseable
*/
// This is a synchronous call.
public void setOnDrmConfigHelper(OnDrmConfigHelper listener) {
- synchronized (mDrmLock) {
- mOnDrmConfigHelper = listener;
- }
+ mOnDrmConfigHelper = listener;
}
private OnDrmConfigHelper mOnDrmConfigHelper;
@@ -3358,24 +3347,27 @@ public class MediaPlayer2 implements AutoCloseable
* @throws IllegalStateException if called before being prepared
*/
public DrmInfo getDrmInfo(@NonNull DataSourceDesc dsd) {
- // TODO: this implementation only works when dsd is the only data source
- DrmInfo drmInfo = null;
-
- // there is not much point if the app calls getDrmInfo within an OnDrmInfoListenet;
- // regardless below returns drmInfo anyway instead of raising an exception
- synchronized (mDrmLock) {
- if (!mDrmInfoResolved && mDrmInfo == null) {
- final String msg = "The Player has not been prepared yet";
- Log.v(TAG, msg);
- throw new IllegalStateException(msg);
- }
+ final SourceInfo sourceInfo = getSourceInfo(dsd);
+ if (sourceInfo != null) {
+ DrmInfo drmInfo = null;
+
+ // there is not much point if the app calls getDrmInfo within an OnDrmInfoListener;
+ // regardless below returns drmInfo anyway instead of raising an exception
+ synchronized (sourceInfo) {
+ if (!sourceInfo.mDrmInfoResolved && sourceInfo.mDrmInfo == null) {
+ final String msg = "The Player has not been prepared yet";
+ Log.v(TAG, msg);
+ throw new IllegalStateException(msg);
+ }
- if (mDrmInfo != null) {
- drmInfo = mDrmInfo.makeCopy();
- }
- } // synchronized
+ if (sourceInfo.mDrmInfo != null) {
+ drmInfo = sourceInfo.mDrmInfo.makeCopy();
+ }
+ } // synchronized
- return drmInfo;
+ return drmInfo;
+ }
+ return null;
}
/**
@@ -3411,15 +3403,28 @@ public class MediaPlayer2 implements AutoCloseable
*/
// This is an asynchronous call.
public Object prepareDrm(@NonNull DataSourceDesc dsd, @NonNull UUID uuid) {
- // TODO: this implementation only works when dsd is the only data source
return addTask(new Task(CALL_COMPLETED_PREPARE_DRM, true) {
@Override
void process() {
- int status = PREPARE_DRM_STATUS_SUCCESS;
+ final SourceInfo sourceInfo = getSourceInfo(dsd);
+ int status = PREPARE_DRM_STATUS_PREPARATION_ERROR;
boolean sendEvent = true;
+ if (sourceInfo == null) {
+ Log.e(TAG, "prepareDrm(): DataSource not found.");
+ } else if (sourceInfo.mDrmInfo == null) {
+ // only allowing if tied to a protected source;
+ // might relax for releasing offline keys
+ Log.e(TAG, "prepareDrm(): Wrong usage: The player must be prepared and "
+ + "DRM info be retrieved before this call.");
+ } else {
+ status = PREPARE_DRM_STATUS_SUCCESS;
+ }
+
try {
- doPrepareDrm(dsd, uuid);
+ if (status == PREPARE_DRM_STATUS_SUCCESS) {
+ sourceInfo.mDrmHandle.prepare(uuid);
+ }
} catch (ResourceBusyException e) {
status = PREPARE_DRM_STATUS_RESOURCE_BUSY;
} catch (UnsupportedSchemeException e) {
@@ -3428,14 +3433,14 @@ public class MediaPlayer2 implements AutoCloseable
Log.w(TAG, "prepareDrm: NotProvisionedException");
// handle provisioning internally; it'll reset mPrepareDrmInProgress
- status = handleProvisioninig(dsd, uuid);
+ status = sourceInfo.mDrmHandle.handleProvisioninig(uuid, mTaskId);
if (status == PREPARE_DRM_STATUS_SUCCESS) {
// DrmEventCallback will be fired in provisioning
sendEvent = false;
} else {
- synchronized (mDrmLock) {
- cleanDrmObj();
+ synchronized (sourceInfo.mDrmHandle) {
+ sourceInfo.mDrmHandle.cleanDrmObj();
}
switch (status) {
@@ -3478,95 +3483,6 @@ public class MediaPlayer2 implements AutoCloseable
});
}
- private void doPrepareDrm(@NonNull DataSourceDesc dsd, @NonNull UUID uuid)
- throws UnsupportedSchemeException, ResourceBusyException,
- NotProvisionedException {
- Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + mOnDrmConfigHelper);
-
- synchronized (mDrmLock) {
- // only allowing if tied to a protected source; might relax for releasing offline keys
- if (mDrmInfo == null) {
- final String msg = "prepareDrm(): Wrong usage: The player must be prepared and "
- + "DRM info be retrieved before this call.";
- Log.e(TAG, msg);
- throw new IllegalStateException(msg);
- }
-
- if (mActiveDrmScheme) {
- final String msg = "prepareDrm(): Wrong usage: There is already "
- + "an active DRM scheme with " + mDrmUUID;
- Log.e(TAG, msg);
- throw new IllegalStateException(msg);
- }
-
- if (mPrepareDrmInProgress) {
- final String msg = "prepareDrm(): Wrong usage: There is already "
- + "a pending prepareDrm call.";
- Log.e(TAG, msg);
- throw new IllegalStateException(msg);
- }
-
- if (mDrmProvisioningInProgress) {
- final String msg = "prepareDrm(): Unexpectd: Provisioning is already in progress.";
- Log.e(TAG, msg);
- throw new IllegalStateException(msg);
- }
-
- // shouldn't need this; just for safeguard
- cleanDrmObj();
-
- mPrepareDrmInProgress = true;
-
- try {
- // only creating the DRM object to allow pre-openSession configuration
- prepareDrm_createDrmStep(uuid);
- } catch (Exception e) {
- Log.w(TAG, "prepareDrm(): Exception ", e);
- mPrepareDrmInProgress = false;
- throw e;
- }
-
- mDrmConfigAllowed = true;
- } // synchronized
-
- // call the callback outside the lock
- if (mOnDrmConfigHelper != null) {
- mOnDrmConfigHelper.onDrmConfig(this, dsd);
- }
-
- synchronized (mDrmLock) {
- mDrmConfigAllowed = false;
- boolean earlyExit = false;
-
- try {
- prepareDrm_openSessionStep(uuid);
-
- mDrmUUID = uuid;
- mActiveDrmScheme = true;
- mPrepareDrmInProgress = false;
- } catch (IllegalStateException e) {
- final String msg = "prepareDrm(): Wrong usage: The player must be "
- + "in the prepared state to call prepareDrm().";
- Log.e(TAG, msg);
- earlyExit = true;
- mPrepareDrmInProgress = false;
- throw new IllegalStateException(msg);
- } catch (NotProvisionedException e) {
- Log.w(TAG, "prepareDrm: NotProvisionedException", e);
- throw e;
- } catch (Exception e) {
- Log.e(TAG, "prepareDrm: Exception " + e);
- earlyExit = true;
- mPrepareDrmInProgress = false;
- throw e;
- } finally {
- if (earlyExit) { // clean up object if didn't succeed
- cleanDrmObj();
- }
- } // finally
- } // synchronized
- }
-
/**
* Releases the DRM session for the given data source
* <p>
@@ -3581,35 +3497,10 @@ public class MediaPlayer2 implements AutoCloseable
// This is a synchronous call.
public void releaseDrm(@NonNull DataSourceDesc dsd)
throws NoDrmSchemeException {
- // TODO: this implementation only works when dsd is the only data source
- synchronized (mDrmLock) {
- Log.v(TAG, "releaseDrm:");
-
- if (!mActiveDrmScheme) {
- Log.e(TAG, "releaseDrm(): No active DRM scheme to release.");
- throw new NoDrmSchemeException(
- "releaseDrm: No active DRM scheme to release.");
- }
-
- try {
- // we don't have the player's state in this layer. The below call raises
- // exception if we're in a non-stopped/prepared state.
-
- // for cleaning native/mediaserver crypto object
- native_releaseDrm();
-
- // for cleaning client-side MediaDrm object; only called if above has succeeded
- cleanDrmObj();
-
- mActiveDrmScheme = false;
- } catch (IllegalStateException e) {
- Log.w(TAG, "releaseDrm: Exception ", e);
- throw new IllegalStateException(
- "releaseDrm: The player is not in a valid state.");
- } catch (Exception e) {
- Log.e(TAG, "releaseDrm: Exception ", e);
- }
- } // synchronized
+ final SourceInfo sourceInfo = getSourceInfo(dsd);
+ if (sourceInfo != null) {
+ sourceInfo.mDrmHandle.release();
+ }
}
private native void native_releaseDrm();
@@ -3653,51 +3544,22 @@ public class MediaPlayer2 implements AutoCloseable
*
* @throws NoDrmSchemeException if there is no active DRM session
*/
- @NonNull
public MediaDrm.KeyRequest getDrmKeyRequest(
@NonNull DataSourceDesc dsd,
@Nullable byte[] keySetId, @Nullable byte[] initData,
@Nullable String mimeType, @MediaDrmKeyType int keyType,
@Nullable Map<String, String> optionalParameters)
throws NoDrmSchemeException {
- // TODO: this implementation only works when dsd is the only data source
- Log.v(TAG, "getDrmKeyRequest: "
- + " keySetId: " + keySetId + " initData:" + initData + " mimeType: " + mimeType
- + " keyType: " + keyType + " optionalParameters: " + optionalParameters);
-
- synchronized (mDrmLock) {
- if (!mActiveDrmScheme) {
- Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
- throw new NoDrmSchemeException(
- "getDrmKeyRequest: Has to set a DRM scheme first.");
- }
-
- try {
- byte[] scope = (keyType != MediaDrm.KEY_TYPE_RELEASE)
- ? mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
- keySetId; // keySetId for KEY_TYPE_RELEASE
-
- HashMap<String, String> hmapOptionalParameters =
- (optionalParameters != null)
- ? new HashMap<String, String>(optionalParameters) :
- null;
-
- MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(scope, initData, mimeType,
- keyType, hmapOptionalParameters);
- Log.v(TAG, "getDrmKeyRequest: --> request: " + request);
-
- return request;
-
- } catch (NotProvisionedException e) {
- Log.w(TAG, "getDrmKeyRequest NotProvisionedException: "
- + "Unexpected. Shouldn't have reached here.");
- throw new IllegalStateException("getDrmKeyRequest: Unexpected provisioning error.");
- } catch (Exception e) {
- Log.w(TAG, "getDrmKeyRequest Exception " + e);
- throw e;
- }
-
- } // synchronized
+ Log.v(TAG, "getDrmKeyRequest: " +
+ " keySetId: " + keySetId + " initData:" + initData + " mimeType: " + mimeType +
+ " keyType: " + keyType + " optionalParameters: " + optionalParameters);
+
+ final SourceInfo sourceInfo = getSourceInfo(dsd);
+ if (sourceInfo != null) {
+ return sourceInfo.mDrmHandle.getDrmKeyRequest(
+ keySetId, initData, mimeType, keyType, optionalParameters);
+ }
+ return null;
}
/**
@@ -3727,40 +3589,13 @@ public class MediaPlayer2 implements AutoCloseable
@NonNull DataSourceDesc dsd,
@Nullable byte[] keySetId, @NonNull byte[] response)
throws NoDrmSchemeException, DeniedByServerException {
- // TODO: this implementation only works when dsd is the only data source
Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response);
- synchronized (mDrmLock) {
-
- if (!mActiveDrmScheme) {
- Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
- throw new NoDrmSchemeException(
- "getDrmKeyRequest: Has to set a DRM scheme first.");
- }
-
- try {
- byte[] scope = (keySetId == null)
- ? mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
- keySetId; // keySetId for KEY_TYPE_RELEASE
-
- byte[] keySetResult = mDrmObj.provideKeyResponse(scope, response);
-
- Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId + " response: " + response
- + " --> " + keySetResult);
-
-
- return keySetResult;
-
- } catch (NotProvisionedException e) {
- Log.w(TAG, "provideDrmKeyResponse NotProvisionedException: "
- + "Unexpected. Shouldn't have reached here.");
- throw new IllegalStateException("provideDrmKeyResponse: "
- + "Unexpected provisioning error.");
- } catch (Exception e) {
- Log.w(TAG, "provideDrmKeyResponse Exception " + e);
- throw e;
- }
- } // synchronized
+ final SourceInfo sourceInfo = getSourceInfo(dsd);
+ if (sourceInfo != null) {
+ return sourceInfo.mDrmHandle.provideDrmKeyResponse(keySetId, response);
+ }
+ return null;
}
/**
@@ -3779,23 +3614,12 @@ public class MediaPlayer2 implements AutoCloseable
@NonNull DataSourceDesc dsd,
@NonNull byte[] keySetId)
throws NoDrmSchemeException {
- // TODO: this implementation only works when dsd is the only data source
Log.v(TAG, "restoreDrmKeys: keySetId: " + keySetId);
- synchronized (mDrmLock) {
- if (!mActiveDrmScheme) {
- Log.w(TAG, "restoreDrmKeys NoDrmSchemeException");
- throw new NoDrmSchemeException(
- "restoreDrmKeys: Has to set a DRM scheme first.");
- }
-
- try {
- mDrmObj.restoreKeys(mDrmSessionId, keySetId);
- } catch (Exception e) {
- Log.w(TAG, "restoreKeys Exception " + e);
- throw e;
- }
- } // synchronized
+ final SourceInfo sourceInfo = getSourceInfo(dsd);
+ if (sourceInfo != null) {
+ sourceInfo.mDrmHandle.restoreDrmKeys(keySetId);
+ }
}
/**
@@ -3812,34 +3636,17 @@ public class MediaPlayer2 implements AutoCloseable
*
* @throws NoDrmSchemeException if there is no active DRM session
*/
- @NonNull
public String getDrmPropertyString(
@NonNull DataSourceDesc dsd,
@NonNull @MediaDrmStringProperty String propertyName)
throws NoDrmSchemeException {
- // TODO: this implementation only works when dsd is the only data source
Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName);
- String value;
- synchronized (mDrmLock) {
-
- if (!mActiveDrmScheme && !mDrmConfigAllowed) {
- Log.w(TAG, "getDrmPropertyString NoDrmSchemeException");
- throw new NoDrmSchemeException(
- "getDrmPropertyString: Has to prepareDrm() first.");
- }
-
- try {
- value = mDrmObj.getPropertyString(propertyName);
- } catch (Exception e) {
- Log.w(TAG, "getDrmPropertyString Exception " + e);
- throw e;
- }
- } // synchronized
-
- Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName + " --> value: " + value);
-
- return value;
+ final SourceInfo sourceInfo = getSourceInfo(dsd);
+ if (sourceInfo != null) {
+ return sourceInfo.mDrmHandle.getDrmPropertyString(propertyName);
+ }
+ return null;
}
/**
@@ -3863,21 +3670,10 @@ public class MediaPlayer2 implements AutoCloseable
// TODO: this implementation only works when dsd is the only data source
Log.v(TAG, "setDrmPropertyString: propertyName: " + propertyName + " value: " + value);
- synchronized (mDrmLock) {
-
- if (!mActiveDrmScheme && !mDrmConfigAllowed) {
- Log.w(TAG, "setDrmPropertyString NoDrmSchemeException");
- throw new NoDrmSchemeException(
- "setDrmPropertyString: Has to prepareDrm() first.");
- }
-
- try {
- mDrmObj.setPropertyString(propertyName, value);
- } catch (Exception e) {
- Log.w(TAG, "setDrmPropertyString Exception " + e);
- throw e;
- }
- } // synchronized
+ final SourceInfo sourceInfo = getSourceInfo(dsd);
+ if (sourceInfo != null) {
+ sourceInfo.mDrmHandle.setDrmPropertyString(propertyName, value);
+ }
}
/**
@@ -4029,43 +3825,6 @@ public class MediaPlayer2 implements AutoCloseable
private native void native_prepareDrm(@NonNull byte[] uuid, @NonNull byte[] drmSessionId);
- // Modular DRM helpers
-
- private void prepareDrm_createDrmStep(@NonNull UUID uuid)
- throws UnsupportedSchemeException {
- Log.v(TAG, "prepareDrm_createDrmStep: UUID: " + uuid);
-
- try {
- mDrmObj = new MediaDrm(uuid);
- Log.v(TAG, "prepareDrm_createDrmStep: Created mDrmObj=" + mDrmObj);
- } catch (Exception e) { // UnsupportedSchemeException
- Log.e(TAG, "prepareDrm_createDrmStep: MediaDrm failed with " + e);
- throw e;
- }
- }
-
- private void prepareDrm_openSessionStep(@NonNull UUID uuid)
- throws NotProvisionedException, ResourceBusyException {
- Log.v(TAG, "prepareDrm_openSessionStep: uuid: " + uuid);
-
- // TODO: don't need an open session for a future specialKeyReleaseDrm mode but we should do
- // it anyway so it raises provisioning error if needed. We'd rather handle provisioning
- // at prepareDrm/openSession rather than getDrmKeyRequest/provideDrmKeyResponse
- try {
- mDrmSessionId = mDrmObj.openSession();
- Log.v(TAG, "prepareDrm_openSessionStep: mDrmSessionId=" + mDrmSessionId);
-
- // Sending it down to native/mediaserver to create the crypto object
- // This call could simply fail due to bad player state, e.g., after play().
- native_prepareDrm(getByteArrayFromUUID(uuid), mDrmSessionId);
- Log.v(TAG, "prepareDrm_openSessionStep: native_prepareDrm/Crypto succeeded");
-
- } catch (Exception e) { //ResourceBusyException, NotProvisionedException
- Log.e(TAG, "prepareDrm_openSessionStep: open/crypto failed with " + e);
- throw e;
- }
- }
-
// Instantiated from the native side
@SuppressWarnings("unused")
private static class StreamEventCallback extends AudioTrack.StreamEventCallback {
@@ -4097,227 +3856,28 @@ public class MediaPlayer2 implements AutoCloseable
}
}
- private class ProvisioningThread extends Thread {
- public static final int TIMEOUT_MS = 60000;
-
- private final DataSourceDesc mDSD;
- private UUID mUuid;
- private String mUrlStr;
- private Object mDrmLock;
- private MediaPlayer2 mMediaPlayer;
- private int mStatus;
- public int status() {
- return mStatus;
- }
-
- public ProvisioningThread(MediaDrm.ProvisionRequest request,
- DataSourceDesc dsd,
- UUID uuid, MediaPlayer2 mediaPlayer) {
- // lock is held by the caller
- mDSD = dsd;
- mDrmLock = mediaPlayer.mDrmLock;
- mMediaPlayer = mediaPlayer;
-
- mUrlStr = request.getDefaultUrl() + "&signedRequest=" + new String(request.getData());
- mUuid = uuid;
-
- mStatus = PREPARE_DRM_STATUS_PREPARATION_ERROR;
-
- Log.v(TAG, "handleProvisioninig: Thread is initialised url: " + mUrlStr);
- }
-
- public void run() {
-
- byte[] response = null;
- boolean provisioningSucceeded = false;
- try {
- URL url = new URL(mUrlStr);
- final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- try {
- connection.setRequestMethod("POST");
- connection.setDoOutput(false);
- connection.setDoInput(true);
- connection.setConnectTimeout(TIMEOUT_MS);
- connection.setReadTimeout(TIMEOUT_MS);
-
- connection.connect();
- response = readInputStreamFully(connection.getInputStream());
-
- Log.v(TAG, "handleProvisioninig: Thread run: response "
- + response.length + " " + response);
- } catch (Exception e) {
- mStatus = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
- Log.w(TAG, "handleProvisioninig: Thread run: connect " + e + " url: " + url);
- } finally {
- connection.disconnect();
- }
- } catch (Exception e) {
- mStatus = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
- Log.w(TAG, "handleProvisioninig: Thread run: openConnection " + e);
- }
-
- if (response != null) {
- try {
- mDrmObj.provideProvisionResponse(response);
- Log.v(TAG, "handleProvisioninig: Thread run: "
- + "provideProvisionResponse SUCCEEDED!");
-
- provisioningSucceeded = true;
- } catch (Exception e) {
- mStatus = PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR;
- Log.w(TAG, "handleProvisioninig: Thread run: "
- + "provideProvisionResponse " + e);
- }
- }
-
- boolean succeeded = false;
-
- synchronized (mDrmLock) {
- // continuing with prepareDrm
- if (provisioningSucceeded) {
- succeeded = mMediaPlayer.resumePrepareDrm(mUuid);
- mStatus = (succeeded)
- ? PREPARE_DRM_STATUS_SUCCESS :
- PREPARE_DRM_STATUS_PREPARATION_ERROR;
- }
- mMediaPlayer.mDrmProvisioningInProgress = false;
- mMediaPlayer.mPrepareDrmInProgress = false;
- if (!succeeded) {
- cleanDrmObj(); // cleaning up if it hasn't gone through while in the lock
- }
- } // synchronized
-
- // calling the callback outside the lock
- sendDrmEvent(new DrmEventNotifier() {
- @Override
- public void notify(DrmEventCallback callback) {
- callback.onDrmPrepared(
- mMediaPlayer, mDSD, mStatus);
- }
- });
-
- synchronized (mTaskLock) {
- if (mCurrentTask != null
- && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE_DRM
- && mCurrentTask.mNeedToWaitForEventToComplete) {
- mCurrentTask = null;
- processPendingTask_l();
- }
- }
- }
-
- /**
- * Returns a byte[] containing the remainder of 'in', closing it when done.
- */
- private byte[] readInputStreamFully(InputStream in) throws IOException {
- try {
- return readInputStreamFullyNoClose(in);
- } finally {
- in.close();
- }
- }
-
- /**
- * Returns a byte[] containing the remainder of 'in'.
- */
- private byte[] readInputStreamFullyNoClose(InputStream in) throws IOException {
- ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int count;
- while ((count = in.read(buffer)) != -1) {
- bytes.write(buffer, 0, count);
- }
- return bytes.toByteArray();
- }
- } // ProvisioningThread
-
- private int handleProvisioninig(DataSourceDesc dsd, UUID uuid) {
- synchronized (mDrmLock) {
- if (mDrmProvisioningInProgress) {
- Log.e(TAG, "handleProvisioninig: Unexpected mDrmProvisioningInProgress");
- return PREPARE_DRM_STATUS_PREPARATION_ERROR;
- }
-
- MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
- if (provReq == null) {
- Log.e(TAG, "handleProvisioninig: getProvisionRequest returned null.");
- return PREPARE_DRM_STATUS_PREPARATION_ERROR;
- }
-
- Log.v(TAG, "handleProvisioninig provReq "
- + " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl());
-
- // networking in a background thread
- mDrmProvisioningInProgress = true;
-
- mDrmProvisioningThread = new ProvisioningThread(provReq, dsd, uuid, this);
- mDrmProvisioningThread.start();
-
- return PREPARE_DRM_STATUS_SUCCESS;
- }
- }
-
- private boolean resumePrepareDrm(UUID uuid) {
- Log.v(TAG, "resumePrepareDrm: uuid: " + uuid);
-
- // mDrmLock is guaranteed to be held
- boolean success = false;
+ /**
+ * Returns a byte[] containing the remainder of 'in', closing it when done.
+ */
+ private static byte[] readInputStreamFully(InputStream in) throws IOException {
try {
- // resuming
- prepareDrm_openSessionStep(uuid);
-
- mDrmUUID = uuid;
- mActiveDrmScheme = true;
-
- success = true;
- } catch (Exception e) {
- Log.w(TAG, "handleProvisioninig: Thread run native_prepareDrm resume failed with " + e);
- // mDrmObj clean up is done by the caller
+ return readInputStreamFullyNoClose(in);
+ } finally {
+ in.close();
}
-
- return success;
- }
-
- private void resetDrmState() {
- synchronized (mDrmLock) {
- Log.v(TAG, "resetDrmState:"
- + " mDrmInfo=" + mDrmInfo
- + " mDrmProvisioningThread=" + mDrmProvisioningThread
- + " mPrepareDrmInProgress=" + mPrepareDrmInProgress
- + " mActiveDrmScheme=" + mActiveDrmScheme);
-
- mDrmInfoResolved = false;
- mDrmInfo = null;
-
- if (mDrmProvisioningThread != null) {
- // timeout; relying on HttpUrlConnection
- try {
- mDrmProvisioningThread.join();
- } catch (InterruptedException e) {
- Log.w(TAG, "resetDrmState: ProvThread.join Exception " + e);
- }
- mDrmProvisioningThread = null;
- }
-
- mPrepareDrmInProgress = false;
- mActiveDrmScheme = false;
-
- cleanDrmObj();
- } // synchronized
}
- private void cleanDrmObj() {
- // the caller holds mDrmLock
- Log.v(TAG, "cleanDrmObj: mDrmObj=" + mDrmObj + " mDrmSessionId=" + mDrmSessionId);
-
- if (mDrmSessionId != null) {
- mDrmObj.closeSession(mDrmSessionId);
- mDrmSessionId = null;
- }
- if (mDrmObj != null) {
- mDrmObj.release();
- mDrmObj = null;
+ /**
+ * Returns a byte[] containing the remainder of 'in'.
+ */
+ private static byte[] readInputStreamFullyNoClose(InputStream in) throws IOException {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int count;
+ while ((count = in.read(buffer)) != -1) {
+ bytes.write(buffer, 0, count);
}
+ return bytes.toByteArray();
}
private static byte[] getByteArrayFromUUID(@NonNull UUID uuid) {
@@ -4333,8 +3893,6 @@ public class MediaPlayer2 implements AutoCloseable
return uuidBytes;
}
- // Modular DRM end
-
private static class TimedTextUtil {
// These keys must be in sync with the keys in TextDescription2.h
private static final int KEY_START_TIME = 7; // int
@@ -4410,6 +3968,7 @@ public class MediaPlayer2 implements AutoCloseable
}
private abstract class Task implements Runnable {
+ final long mTaskId = mTaskIdGenerator.getAndIncrement();
private final int mMediaCallType;
private final boolean mNeedToWaitForEventToComplete;
private DataSourceDesc mDSD;
@@ -4501,7 +4060,503 @@ public class MediaPlayer2 implements AutoCloseable
}
};
- private final class SourceInfo {
+ // Modular DRM
+ final class DrmHandle {
+
+ static final int PROVISION_TIMEOUT_MS = 60000;
+
+ final DataSourceDesc mDSD;
+
+ //--- guarded by |this| start
+ MediaDrm mDrmObj;
+ byte[] mDrmSessionId;
+ UUID mActiveDrmUUID;
+ boolean mDrmConfigAllowed;
+ boolean mDrmProvisioningInProgress;
+ boolean mPrepareDrmInProgress;
+ Future<?> mProvisionResult;
+ //--- guarded by |this| end
+
+ DrmHandle(DataSourceDesc dsd) {
+ mDSD = dsd;
+ }
+
+ void prepare(UUID uuid) throws UnsupportedSchemeException,
+ ResourceBusyException, NotProvisionedException {
+ final OnDrmConfigHelper onDrmConfigHelper = mOnDrmConfigHelper;
+ Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + onDrmConfigHelper);
+
+ synchronized (this) {
+ if (mActiveDrmUUID != null) {
+ final String msg = "prepareDrm(): Wrong usage: There is already "
+ + "an active DRM scheme with " + uuid;
+ Log.e(TAG, msg);
+ throw new IllegalStateException(msg);
+ }
+
+ if (mPrepareDrmInProgress) {
+ final String msg = "prepareDrm(): Wrong usage: There is already "
+ + "a pending prepareDrm call.";
+ Log.e(TAG, msg);
+ throw new IllegalStateException(msg);
+ }
+
+ if (mDrmProvisioningInProgress) {
+ final String msg = "prepareDrm(): Unexpectd: Provisioning already in progress";
+ Log.e(TAG, msg);
+ throw new IllegalStateException(msg);
+ }
+
+ // shouldn't need this; just for safeguard
+ cleanDrmObj();
+
+ mPrepareDrmInProgress = true;
+
+ try {
+ // only creating the DRM object to allow pre-openSession configuration
+ prepareDrm_createDrmStep(uuid);
+ } catch (Exception e) {
+ Log.w(TAG, "prepareDrm(): Exception ", e);
+ mPrepareDrmInProgress = false;
+ throw e;
+ }
+
+ mDrmConfigAllowed = true;
+ } // synchronized
+
+ // call the callback outside the lock
+ if (onDrmConfigHelper != null) {
+ onDrmConfigHelper.onDrmConfig(MediaPlayer2.this, mDSD);
+ }
+
+ synchronized (this) {
+ mDrmConfigAllowed = false;
+ boolean earlyExit = false;
+
+ try {
+ prepareDrm_openSessionStep(uuid);
+
+ this.mActiveDrmUUID = uuid;
+ mPrepareDrmInProgress = false;
+ } catch (IllegalStateException e) {
+ final String msg = "prepareDrm(): Wrong usage: The player must be "
+ + "in the prepared state to call prepareDrm().";
+ Log.e(TAG, msg);
+ earlyExit = true;
+ mPrepareDrmInProgress = false;
+ throw new IllegalStateException(msg);
+ } catch (NotProvisionedException e) {
+ Log.w(TAG, "prepareDrm: NotProvisionedException", e);
+ throw e;
+ } catch (Exception e) {
+ Log.e(TAG, "prepareDrm: Exception " + e);
+ earlyExit = true;
+ mPrepareDrmInProgress = false;
+ throw e;
+ } finally {
+ if (earlyExit) { // clean up object if didn't succeed
+ cleanDrmObj();
+ }
+ } // finally
+ } // synchronized
+ }
+
+ void prepareDrm_createDrmStep(UUID uuid)
+ throws UnsupportedSchemeException {
+ Log.v(TAG, "prepareDrm_createDrmStep: UUID: " + uuid);
+
+ try {
+ mDrmObj = new MediaDrm(uuid);
+ Log.v(TAG, "prepareDrm_createDrmStep: Created mDrmObj=" + mDrmObj);
+ } catch (Exception e) { // UnsupportedSchemeException
+ Log.e(TAG, "prepareDrm_createDrmStep: MediaDrm failed with " + e);
+ throw e;
+ }
+ }
+
+ void prepareDrm_openSessionStep(UUID uuid)
+ throws NotProvisionedException, ResourceBusyException {
+ Log.v(TAG, "prepareDrm_openSessionStep: uuid: " + uuid);
+
+ // TODO:
+ // don't need an open session for a future specialKeyReleaseDrm mode but we should do
+ // it anyway so it raises provisioning error if needed. We'd rather handle provisioning
+ // at prepareDrm/openSession rather than getDrmKeyRequest/provideDrmKeyResponse
+ try {
+ mDrmSessionId = mDrmObj.openSession();
+ Log.v(TAG, "prepareDrm_openSessionStep: mDrmSessionId=" + mDrmSessionId);
+
+ // Sending it down to native/mediaserver to create the crypto object
+ // This call could simply fail due to bad player state, e.g., after play().
+ MediaPlayer2.this.native_prepareDrm(getByteArrayFromUUID(uuid), mDrmSessionId);
+ Log.v(TAG, "prepareDrm_openSessionStep: native_prepareDrm/Crypto succeeded");
+
+ } catch (Exception e) { //ResourceBusyException, NotProvisionedException
+ Log.e(TAG, "prepareDrm_openSessionStep: open/crypto failed with " + e);
+ throw e;
+ }
+
+ }
+
+ int handleProvisioninig(UUID uuid, long taskId) {
+ synchronized (this) {
+ if (mDrmProvisioningInProgress) {
+ Log.e(TAG, "handleProvisioninig: Unexpected mDrmProvisioningInProgress");
+ return PREPARE_DRM_STATUS_PREPARATION_ERROR;
+ }
+
+ MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
+ if (provReq == null) {
+ Log.e(TAG, "handleProvisioninig: getProvisionRequest returned null.");
+ return PREPARE_DRM_STATUS_PREPARATION_ERROR;
+ }
+
+ Log.v(TAG, "handleProvisioninig provReq "
+ + " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl());
+
+ // networking in a background thread
+ mDrmProvisioningInProgress = true;
+
+ mProvisionResult = mDrmThreadPool.submit(newProvisioningTask(uuid, taskId));
+
+ return PREPARE_DRM_STATUS_SUCCESS;
+ }
+ }
+
+ void provision(UUID uuid, long taskId) {
+
+ MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
+ String urlStr = provReq.getDefaultUrl();
+ urlStr += "&signedRequest=" + new String(provReq.getData());
+ Log.v(TAG, "handleProvisioninig: Thread is initialised url: " + urlStr);
+
+ byte[] response = null;
+ boolean provisioningSucceeded = false;
+ int status = PREPARE_DRM_STATUS_PREPARATION_ERROR;
+ try {
+ URL url = new URL(urlStr);
+ final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ try {
+ connection.setRequestMethod("POST");
+ connection.setDoOutput(false);
+ connection.setDoInput(true);
+ connection.setConnectTimeout(PROVISION_TIMEOUT_MS);
+ connection.setReadTimeout(PROVISION_TIMEOUT_MS);
+
+ connection.connect();
+ response = readInputStreamFully(connection.getInputStream());
+
+ Log.v(TAG, "handleProvisioninig: Thread run: response " +
+ response.length + " " + response);
+ } catch (Exception e) {
+ status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
+ Log.w(TAG, "handleProvisioninig: Thread run: connect " + e + " url: " + url);
+ } finally {
+ connection.disconnect();
+ }
+ } catch (Exception e) {
+ status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
+ Log.w(TAG, "handleProvisioninig: Thread run: openConnection " + e);
+ }
+
+ if (response != null) {
+ try {
+ mDrmObj.provideProvisionResponse(response);
+ Log.v(TAG, "handleProvisioninig: Thread run: " +
+ "provideProvisionResponse SUCCEEDED!");
+
+ provisioningSucceeded = true;
+ } catch (Exception e) {
+ status = PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR;
+ Log.w(TAG, "handleProvisioninig: Thread run: " +
+ "provideProvisionResponse " + e);
+ }
+ }
+
+ boolean succeeded = false;
+
+ synchronized (this) {
+ // continuing with prepareDrm
+ if (provisioningSucceeded) {
+ succeeded = resumePrepare(uuid);
+ status = (succeeded) ?
+ PREPARE_DRM_STATUS_SUCCESS :
+ PREPARE_DRM_STATUS_PREPARATION_ERROR;
+ }
+ mDrmProvisioningInProgress = false;
+ mPrepareDrmInProgress = false;
+ if (!succeeded) {
+ cleanDrmObj(); // cleaning up if it hasn't gone through while in the lock
+ }
+ } // synchronized
+
+ // calling the callback outside the lock
+ final int finalStatus = status;
+ sendDrmEvent(new DrmEventNotifier() {
+ @Override
+ public void notify(DrmEventCallback callback) {
+ callback.onDrmPrepared(
+ MediaPlayer2.this, mDSD, finalStatus);
+ }
+ });
+
+ synchronized (mTaskLock) {
+ if (mCurrentTask != null
+ && mCurrentTask.mTaskId == taskId
+ && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE_DRM
+ && mCurrentTask.mNeedToWaitForEventToComplete) {
+ mCurrentTask = null;
+ processPendingTask_l();
+ }
+ }
+ }
+
+ Runnable newProvisioningTask(UUID uuid, long taskId) {
+ return new Runnable() {
+ @Override
+ public void run() {
+ provision(uuid, taskId);
+ }
+ };
+ }
+
+ boolean resumePrepare(UUID uuid) {
+ Log.v(TAG, "resumePrepareDrm: uuid: " + uuid);
+
+ // mDrmLock is guaranteed to be held
+ boolean success = false;
+ try {
+ // resuming
+ prepareDrm_openSessionStep(uuid);
+
+ this.mActiveDrmUUID = uuid;
+
+ success = true;
+ } catch (Exception e) {
+ Log.w(TAG, "handleProvisioninig: Thread run native_prepareDrm resume failed:" + e);
+ // mDrmObj clean up is done by the caller
+ }
+
+ return success;
+ }
+
+ void cleanDrmObj() {
+ // the caller holds mDrmLock
+ Log.v(TAG, "cleanDrmObj: mDrmObj=" + mDrmObj + " mDrmSessionId=" + mDrmSessionId);
+
+ if (mDrmSessionId != null) {
+ mDrmObj.closeSession(mDrmSessionId);
+ mDrmSessionId = null;
+ }
+ if (mDrmObj != null) {
+ mDrmObj.close();
+ mDrmObj = null;
+ }
+ }
+
+ void release() throws NoDrmSchemeException {
+ synchronized (this) {
+ Log.v(TAG, "releaseDrm:");
+
+ if (mActiveDrmUUID == null) {
+ Log.e(TAG, "releaseDrm(): No active DRM scheme to release.");
+ throw new NoDrmSchemeException(
+ "releaseDrm: No active DRM scheme to release.");
+ }
+
+ try {
+ // we don't have the player's state in this layer. The below call raises
+ // exception if we're in a non-stopped/prepared state.
+
+ // for cleaning native/mediaserver crypto object
+ native_releaseDrm();
+
+ // for cleaning client-side MediaDrm object; only called if above has succeeded
+ cleanDrmObj();
+
+ this.mActiveDrmUUID = null;
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "releaseDrm: Exception ", e);
+ throw new IllegalStateException(
+ "releaseDrm: The player is not in a valid state.");
+ } catch (Exception e) {
+ Log.e(TAG, "releaseDrm: Exception ", e);
+ }
+ } // synchronized
+ }
+
+ void cleanup() {
+ synchronized (this) {
+ Log.v(TAG, "cleanupDrm: " +
+ " mProvisioningTask=" + mProvisionResult +
+ " mPrepareDrmInProgress=" + mPrepareDrmInProgress +
+ " mActiveDrmScheme=" + mActiveDrmUUID);
+
+ if (mProvisionResult != null) {
+ // timeout; relying on HttpUrlConnection
+ try {
+ mProvisionResult.get();
+ }
+ catch (InterruptedException | ExecutionException e) {
+ Log.w(TAG, "resetDrmState: ProvThread.join Exception " + e);
+ }
+ }
+
+ // set to false to avoid duplicate release calls
+ this.mActiveDrmUUID = null;
+
+ cleanDrmObj();
+ } // synchronized
+ }
+
+ Runnable newCleanupTask() {
+ return new Runnable() {
+ @Override
+ public void run() {
+ cleanup();
+ }
+ };
+ }
+
+ MediaDrm.KeyRequest getDrmKeyRequest(
+ byte[] keySetId, byte[] initData,
+ String mimeType, int keyType,
+ Map<String, String> optionalParameters)
+ throws NoDrmSchemeException {
+ synchronized (this) {
+ if (mActiveDrmUUID == null) {
+ Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
+ throw new NoDrmSchemeException(
+ "getDrmKeyRequest: Has to set a DRM scheme first.");
+ }
+
+ try {
+ byte[] scope = (keyType != MediaDrm.KEY_TYPE_RELEASE) ?
+ mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
+ keySetId; // keySetId for KEY_TYPE_RELEASE
+
+ HashMap<String, String> hmapOptionalParameters =
+ (optionalParameters != null)
+ ? new HashMap<String, String>(optionalParameters)
+ : null;
+
+ MediaDrm.KeyRequest request = mDrmObj.getKeyRequest(
+ scope, initData, mimeType, keyType, hmapOptionalParameters);
+ Log.v(TAG, "getDrmKeyRequest: --> request: " + request);
+
+ return request;
+
+ } catch (NotProvisionedException e) {
+ Log.w(TAG, "getDrmKeyRequest NotProvisionedException: " +
+ "Unexpected. Shouldn't have reached here.");
+ throw new IllegalStateException("getDrmKeyRequest: provisioning error.");
+ } catch (Exception e) {
+ Log.w(TAG, "getDrmKeyRequest Exception " + e);
+ throw e;
+ }
+
+ }
+ }
+
+ byte[] provideDrmKeyResponse(byte[] keySetId, byte[] response)
+ throws NoDrmSchemeException, DeniedByServerException {
+ synchronized (this) {
+
+ if (mActiveDrmUUID == null) {
+ Log.e(TAG, "getDrmKeyRequest NoDrmSchemeException");
+ throw new NoDrmSchemeException(
+ "getDrmKeyRequest: Has to set a DRM scheme first.");
+ }
+
+ try {
+ byte[] scope = (keySetId == null) ?
+ mDrmSessionId : // sessionId for KEY_TYPE_STREAMING/OFFLINE
+ keySetId; // keySetId for KEY_TYPE_RELEASE
+
+ byte[] keySetResult = mDrmObj.provideKeyResponse(scope, response);
+
+ Log.v(TAG, "provideDrmKeyResponse: keySetId: " + keySetId
+ + " response: " + response + " --> " + keySetResult);
+
+
+ return keySetResult;
+
+ } catch (NotProvisionedException e) {
+ Log.w(TAG, "provideDrmKeyResponse NotProvisionedException: " +
+ "Unexpected. Shouldn't have reached here.");
+ throw new IllegalStateException("provideDrmKeyResponse: " +
+ "Unexpected provisioning error.");
+ } catch (Exception e) {
+ Log.w(TAG, "provideDrmKeyResponse Exception " + e);
+ throw e;
+ }
+ }
+ }
+
+ void restoreDrmKeys(byte[] keySetId)
+ throws NoDrmSchemeException {
+ synchronized (this) {
+ if (mActiveDrmUUID == null) {
+ Log.w(TAG, "restoreDrmKeys NoDrmSchemeException");
+ throw new NoDrmSchemeException(
+ "restoreDrmKeys: Has to set a DRM scheme first.");
+ }
+
+ try {
+ mDrmObj.restoreKeys(mDrmSessionId, keySetId);
+ } catch (Exception e) {
+ Log.w(TAG, "restoreKeys Exception " + e);
+ throw e;
+ }
+ }
+ }
+
+ String getDrmPropertyString(String propertyName)
+ throws NoDrmSchemeException {
+ String v;
+ synchronized (this) {
+
+ if (mActiveDrmUUID == null && !mDrmConfigAllowed) {
+ Log.w(TAG, "getDrmPropertyString NoDrmSchemeException");
+ throw new NoDrmSchemeException(
+ "getDrmPropertyString: Has to prepareDrm() first.");
+ }
+
+ try {
+ v = mDrmObj.getPropertyString(propertyName);
+ } catch (Exception e) {
+ Log.w(TAG, "getDrmPropertyString Exception " + e);
+ throw e;
+ }
+ } // synchronized
+
+ Log.v(TAG, "getDrmPropertyString: propertyName: " + propertyName + " --> value: " + v);
+
+ return v;
+ }
+
+ void setDrmPropertyString(String propertyName, String value)
+ throws NoDrmSchemeException {
+ synchronized (this) {
+
+ if ( mActiveDrmUUID == null && !mDrmConfigAllowed ) {
+ Log.w(TAG, "setDrmPropertyString NoDrmSchemeException");
+ throw new NoDrmSchemeException(
+ "setDrmPropertyString: Has to prepareDrm() first.");
+ }
+
+ try {
+ mDrmObj.setPropertyString(propertyName, value);
+ } catch ( Exception e ) {
+ Log.w(TAG, "setDrmPropertyString Exception " + e);
+ throw e;
+ }
+ }
+ }
+
+ }
+
+ final class SourceInfo {
final DataSourceDesc mDSD;
final long mId = mSrcIdGenerator.getAndIncrement();
AtomicInteger mBufferedPercentage = new AtomicInteger(0);
@@ -4513,8 +4568,14 @@ public class MediaPlayer2 implements AutoCloseable
int mStateAsNextSource = NEXT_SOURCE_STATE_INIT;
boolean mPlayPendingAsNextSource = false;
+ // Modular DRM
+ final DrmHandle mDrmHandle;
+ DrmInfo mDrmInfo;
+ boolean mDrmInfoResolved;
+
SourceInfo(DataSourceDesc dsd) {
this.mDSD = dsd;
+ mDrmHandle = new DrmHandle(dsd);
}
void close() {
@@ -4535,7 +4596,7 @@ public class MediaPlayer2 implements AutoCloseable
}
- private SourceInfo getSourceInfoById(long srcId) {
+ private SourceInfo getSourceInfo(long srcId) {
synchronized (mSrcLock) {
if (isCurrentSource(srcId)) {
return mCurrentSourceInfo;
@@ -4547,34 +4608,65 @@ public class MediaPlayer2 implements AutoCloseable
return null;
}
+ private SourceInfo getSourceInfo(DataSourceDesc dsd) {
+ synchronized (mSrcLock) {
+ if (isCurrentSource(dsd)) {
+ return mCurrentSourceInfo;
+ }
+ if (isNextSource(dsd)) {
+ return mNextSourceInfos.peek();
+ }
+ }
+ return null;
+ }
+
private boolean isCurrentSource(long srcId) {
synchronized (mSrcLock) {
return mCurrentSourceInfo != null && mCurrentSourceInfo.mId == srcId;
}
}
+ private boolean isCurrentSource(DataSourceDesc dsd) {
+ synchronized (mSrcLock) {
+ return mCurrentSourceInfo != null && mCurrentSourceInfo.mDSD == dsd;
+ }
+ }
+
private boolean isNextSource(long srcId) {
SourceInfo nextSourceInfo = mNextSourceInfos.peek();
return nextSourceInfo != null && nextSourceInfo.mId == srcId;
}
- private void setCurrentSourceInfo(SourceInfo newSourceInfo) {
- synchronized (mSrcLock) {
- if (mCurrentSourceInfo != null) {
- mCurrentSourceInfo.close();
- }
- mCurrentSourceInfo = newSourceInfo;
+ private boolean isNextSource(DataSourceDesc dsd) {
+ SourceInfo nextSourceInfo = mNextSourceInfos.peek();
+ return nextSourceInfo != null && nextSourceInfo.mDSD == dsd;
+ }
+
+ @GuardedBy("mSrcLock")
+ private void setCurrentSourceInfo_l(SourceInfo sourceInfo) {
+ cleanupSourceInfo(mCurrentSourceInfo);
+ mCurrentSourceInfo = sourceInfo;
+ }
+
+ @GuardedBy("mSrcLock")
+ private void clearNextSourceInfos_l() {
+ while (!mNextSourceInfos.isEmpty()) {
+ cleanupSourceInfo(mNextSourceInfos.poll());
+ }
+ }
+
+ private void cleanupSourceInfo(SourceInfo sourceInfo) {
+ if (sourceInfo != null) {
+ sourceInfo.close();
+ Runnable task = sourceInfo.mDrmHandle.newCleanupTask();
+ mDrmThreadPool.submit(task);
}
}
- private void clearNextSourceInfos() {
+ private void clearSourceInfos() {
synchronized (mSrcLock) {
- for (SourceInfo sourceInfo : mNextSourceInfos) {
- if (sourceInfo != null) {
- sourceInfo.close();
- }
- }
- mNextSourceInfos.clear();
+ setCurrentSourceInfo_l(null);
+ clearNextSourceInfos_l();
}
}
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index b6e3276a4e43..5e9eed737256 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -20,7 +20,6 @@ import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.graphics.Bitmap;
import android.media.session.MediaController;
import android.media.session.MediaSession;
@@ -36,7 +35,6 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
-import java.lang.ref.WeakReference;
import java.util.List;
/**
@@ -250,7 +248,7 @@ import java.util.List;
* @throws IllegalArgumentException
*/
public boolean sendMediaKeyEvent(KeyEvent keyEvent) throws IllegalArgumentException {
- if (!KeyEvent.isMediaKey(keyEvent.getKeyCode())) {
+ if (!KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
throw new IllegalArgumentException("not a media key event");
}
synchronized (mInfoLock) {
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 436897fbf8b0..874f21ea8c28 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -18,6 +18,7 @@ package android.media;
import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -1029,7 +1030,7 @@ public class RingtoneManager {
* @throws FileNotFoundException if the provided URI could not be opened.
* @see #getDefaultUri
*/
- public static AssetFileDescriptor openDefaultRingtoneUri(
+ public static @Nullable AssetFileDescriptor openDefaultRingtoneUri(
@NonNull Context context, @NonNull Uri uri) throws FileNotFoundException {
// Try cached ringtone first since the actual provider may not be
// encryption aware, or it may be stored on CE media storage
diff --git a/media/java/android/media/midi/MidiOutputPort.java b/media/java/android/media/midi/MidiOutputPort.java
index 511f6cd51917..5411e669f14d 100644
--- a/media/java/android/media/midi/MidiOutputPort.java
+++ b/media/java/android/media/midi/MidiOutputPort.java
@@ -59,6 +59,8 @@ public final class MidiOutputPort extends MidiSender implements Closeable {
// read next event
int count = mInputStream.read(buffer);
if (count < 0) {
+ // This is the exit condition as read() returning <0 indicates
+ // that the pipe has been closed.
break;
// FIXME - inform receivers here?
}
@@ -81,10 +83,15 @@ public final class MidiOutputPort extends MidiSender implements Closeable {
Log.e(TAG, "Unknown packet type " + packetType);
break;
}
- }
+ } // while (true)
} catch (IOException e) {
// FIXME report I/O failure?
- Log.e(TAG, "read failed", e);
+ // TODO: The comment above about the exit condition is not currently working
+ // as intended. The read from the closed pipe is throwing an error rather than
+ // returning <0, so this becomes (probably) not an error, but the exit case.
+ // This warrants further investigation;
+ // Silence the (probably) spurious error message.
+ // Log.e(TAG, "read failed", e);
} finally {
IoUtils.closeQuietly(mInputStream);
}
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index c4b82c3141d3..b457357600fe 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -149,7 +149,7 @@ public final class MediaController {
if (keyEvent == null) {
throw new IllegalArgumentException("KeyEvent may not be null");
}
- if (!KeyEvent.isMediaKey(keyEvent.getKeyCode())) {
+ if (!KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
return false;
}
try {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index d9017b4fb14c..ff6977914ac3 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -59,9 +59,7 @@ import com.android.internal.os.SomeArgs;
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
/**
* The TvInputService class represents a TV input or source such as HDMI or built-in tuner which
@@ -1400,7 +1398,7 @@ public abstract class TvInputService extends Service {
// ViewRootImpl always consumes the keys. In this case, the application loses
// a chance to handle media keys. Therefore, media keys are not dispatched to
// ViewRootImpl.
- skipDispatchToOverlayView = KeyEvent.isMediaKey(keyEvent.getKeyCode())
+ skipDispatchToOverlayView = KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())
|| keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK;
} else if (event instanceof MotionEvent) {
MotionEvent motionEvent = (MotionEvent) event;
diff --git a/native/webview/plat_support/draw_gl.h b/native/webview/plat_support/draw_gl.h
index c8434b61eba5..de13ed0dec6f 100644
--- a/native/webview/plat_support/draw_gl.h
+++ b/native/webview/plat_support/draw_gl.h
@@ -43,9 +43,9 @@ struct AwDrawGLInfo {
// Input: tells the draw function what action to perform.
enum Mode {
kModeDraw = 0,
- kModeProcess,
- kModeProcessNoContext,
- kModeSync,
+ kModeProcess = 1,
+ kModeProcessNoContext = 2,
+ kModeSync = 3,
} mode;
// Input: current clip rect in surface coordinates. Reflects the current state
@@ -93,9 +93,9 @@ typedef void (AwDrawGLFunction)(long view_context,
AwDrawGLInfo* draw_info,
void* spare);
enum AwMapMode {
- MAP_READ_ONLY,
- MAP_WRITE_ONLY,
- MAP_READ_WRITE,
+ MAP_READ_ONLY = 0,
+ MAP_WRITE_ONLY = 1,
+ MAP_READ_WRITE = 2,
};
// Called to create a GraphicBuffer
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java
new file mode 100644
index 000000000000..5bf30ca10694
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/AssitantButton.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car;
+
+import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.util.Log;
+
+import com.android.internal.app.AssistUtils;
+import com.android.internal.app.IVoiceInteractionSessionShowCallback;
+
+/**
+ * AssitantButton is a ui component that will trigger the Voice Interaction Service.
+ */
+public class AssitantButton extends CarFacetButton {
+
+ private static final String TAG = "CarFacetButton";
+ private IVoiceInteractionSessionShowCallback mShowCallback =
+ new IVoiceInteractionSessionShowCallback.Stub() {
+ @Override
+ public void onFailed() {
+ Log.w(TAG, "Failed to show VoiceInteractionSession");
+ }
+
+ @Override
+ public void onShown() {
+ Log.d(TAG, "IVoiceInteractionSessionShowCallback onShown()");
+ }
+ };
+
+ private static final String EXTRA_CAR_PUSH_TO_TALK =
+ "com.android.car.input.EXTRA_CAR_PUSH_TO_TALK";
+ private final AssistUtils mAssistUtils;
+
+ public AssitantButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mAssistUtils = new AssistUtils(context);
+ setOnClickListener(v -> {
+ showAssistant();
+ });
+ }
+
+ private void showAssistant() {
+ final Bundle args = new Bundle();
+ args.putBoolean(EXTRA_CAR_PUSH_TO_TALK, true);
+ mAssistUtils.showSessionForActiveService(args,
+ SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, /*activityToken=*/ null);
+ }
+
+ @Override
+ protected void setupIntents(TypedArray typedArray){
+ // left blank because for the assistant button Intent will not be passed from the layout.
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
new file mode 100644
index 000000000000..cea4ab0e4992
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.os.UserHandle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.keyguard.AlphaOptimizedImageButton;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+
+/**
+ * CarFacetButton is a ui component designed to be used as a shortcut for an app of a defined
+ * category. It can also render a indicator impling that there are more options of apps to launch
+ * using this component. This is done with a "More icon" currently an arrow as defined in the layout
+ * file. The class is to serve as an example.
+ * Usage example: A button that allows a user to select a music app and indicate that there are
+ * other music apps installed.
+ */
+public class CarFacetButton extends LinearLayout {
+ private static final String FACET_FILTER_DELIMITER = ";";
+ /**
+ * Extra information to be sent to a helper to make the decision of what app to launch when
+ * clicked.
+ */
+ private static final String EXTRA_FACET_CATEGORIES = "categories";
+ private static final String EXTRA_FACET_PACKAGES = "packages";
+ private static final String EXTRA_FACET_ID = "filter_id";
+ private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker";
+ private static final String TAG = "CarFacetButton";
+
+ private Context mContext;
+ private AlphaOptimizedImageButton mIcon;
+ private AlphaOptimizedImageButton mMoreIcon;
+ private boolean mSelected = false;
+ private String[] mComponentNames;
+ /** App categories that are to be used with this widget */
+ private String[] mFacetCategories;
+ /** App packages that are allowed to be used with this widget */
+ private String[] mFacetPackages;
+ private int mIconResourceId;
+ /**
+ * If defined in the xml this will be the icon that's rendered when the button is marked as
+ * selected
+ */
+ private int mSelectedIconResourceId;
+ private boolean mUseMoreIcon = true;
+ private float mSelectedAlpha = 1f;
+ private float mUnselectedAlpha = 1f;
+
+ public CarFacetButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+ View.inflate(context, R.layout.car_facet_button, this);
+ // extract custom attributes
+ TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton);
+ setupIntents(typedArray);
+ setupIcons(typedArray);
+ CarFacetButtonController carFacetButtonController = Dependency.get(
+ CarFacetButtonController.class);
+ carFacetButtonController.addFacetButton(this);
+ }
+
+ /**
+ * Reads the custom attributes to setup click handlers for this component.
+ */
+ protected void setupIntents(TypedArray typedArray) {
+ String intentString = typedArray.getString(R.styleable.CarFacetButton_intent);
+ String longPressIntentString = typedArray.getString(R.styleable.CarFacetButton_longIntent);
+ String categoryString = typedArray.getString(R.styleable.CarFacetButton_categories);
+ String packageString = typedArray.getString(R.styleable.CarFacetButton_packages);
+ String componentNameString =
+ typedArray.getString(R.styleable.CarFacetButton_componentNames);
+ try {
+ final Intent intent = Intent.parseUri(intentString, Intent.URI_INTENT_SCHEME);
+ intent.putExtra(EXTRA_FACET_ID, Integer.toString(getId()));
+
+ if (packageString != null) {
+ mFacetPackages = packageString.split(FACET_FILTER_DELIMITER);
+ intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages);
+ }
+ if (categoryString != null) {
+ mFacetCategories = categoryString.split(FACET_FILTER_DELIMITER);
+ intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories);
+ }
+ if (componentNameString != null) {
+ mComponentNames = componentNameString.split(FACET_FILTER_DELIMITER);
+ }
+
+ setOnClickListener(v -> {
+ intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, mSelected);
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+ });
+
+ if (longPressIntentString != null) {
+ final Intent longPressIntent = Intent.parseUri(longPressIntentString,
+ Intent.URI_INTENT_SCHEME);
+ setOnLongClickListener(v -> {
+ mContext.startActivityAsUser(longPressIntent, UserHandle.CURRENT);
+ return true;
+ });
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to attach intent", e);
+ }
+ }
+
+ private void setupIcons(TypedArray styledAttributes) {
+ mSelectedAlpha = styledAttributes.getFloat(
+ R.styleable.CarFacetButton_selectedAlpha, mSelectedAlpha);
+ mUnselectedAlpha = styledAttributes.getFloat(
+ R.styleable.CarFacetButton_unselectedAlpha, mUnselectedAlpha);
+ mIcon = findViewById(R.id.car_nav_button_icon);
+ mIcon.setScaleType(ImageView.ScaleType.CENTER);
+ mIcon.setClickable(false);
+ mIcon.setAlpha(mUnselectedAlpha);
+ mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
+ mIcon.setImageResource(mIconResourceId);
+ mSelectedIconResourceId = styledAttributes.getResourceId(
+ R.styleable.CarFacetButton_selectedIcon, mIconResourceId);
+
+ mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
+ mMoreIcon.setClickable(false);
+ mMoreIcon.setAlpha(mSelectedAlpha);
+ mMoreIcon.setVisibility(GONE);
+ mUseMoreIcon = styledAttributes.getBoolean(R.styleable.CarFacetButton_useMoreIcon, true);
+ }
+
+ /**
+ * @return The app categories the component represents
+ */
+ public String[] getCategories() {
+ if (mFacetCategories == null) {
+ return new String[0];
+ }
+ return mFacetCategories;
+ }
+
+ /**
+ * @return The valid packages that should be considered.
+ */
+ public String[] getFacetPackages() {
+ if (mFacetPackages == null) {
+ return new String[0];
+ }
+ return mFacetPackages;
+ }
+
+ /**
+ * @return The list of component names.
+ */
+ public String[] getComponentName() {
+ if (mComponentNames == null) {
+ return new String[0];
+ }
+ return mComponentNames;
+ }
+
+ /**
+ * Updates the alpha of the icons to "selected" and shows the "More icon"
+ *
+ * @param selected true if the view must be selected, false otherwise
+ */
+ public void setSelected(boolean selected) {
+ super.setSelected(selected);
+ setSelected(selected, selected);
+ }
+
+ /**
+ * Updates the visual state to let the user know if it's been selected.
+ *
+ * @param selected true if should update the alpha of the icon to selected, false otherwise
+ * @param showMoreIcon true if the "more icon" should be shown, false otherwise. Note this
+ * is ignored if the attribute useMoreIcon is set to false
+ */
+ public void setSelected(boolean selected, boolean showMoreIcon) {
+ mSelected = selected;
+ mIcon.setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha);
+ mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId);
+ if (mUseMoreIcon) {
+ mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
+ }
+ }
+}
diff --git a/packages/PackageInstaller/Android.bp b/packages/PackageInstaller/Android.bp
deleted file mode 100644
index bc06cab7aef5..000000000000
--- a/packages/PackageInstaller/Android.bp
+++ /dev/null
@@ -1,14 +0,0 @@
-android_app {
- name: "PackageInstaller",
-
- srcs: ["src/**/*.java"],
-
- static_libs: [
- "androidx.leanback_leanback",
- "xz-java",
- ],
-
- certificate: "platform",
- privileged: true,
- platform_apis: true,
-} \ No newline at end of file
diff --git a/packages/PackageInstaller/Android.mk b/packages/PackageInstaller/Android.mk
new file mode 100644
index 000000000000..ab5483c8afb8
--- /dev/null
+++ b/packages/PackageInstaller/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PackageInstaller
+
+LOCAL_CERTIFICATE := platform
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
+LOCAL_STATIC_JAVA_LIBRARIES := xz-java
+LOCAL_STATIC_ANDROID_LIBRARIES := androidx.leanback_leanback
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 4801f62bae67..eb9ec82c9519 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.packageinstaller">
+ <original-package android:name="com.android.packageinstaller" />
+
<uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.DELETE_PACKAGES" />
diff --git a/packages/SettingsLib/ActionButtonsPreference/Android.bp b/packages/SettingsLib/ActionButtonsPreference/Android.bp
new file mode 100644
index 000000000000..e518e0b97c4b
--- /dev/null
+++ b/packages/SettingsLib/ActionButtonsPreference/Android.bp
@@ -0,0 +1,13 @@
+android_library {
+ name: "ActionButtonsPreference",
+
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+
+ static_libs: [
+ "androidx.preference_preference",
+ ],
+
+ sdk_version: "system_current",
+ min_sdk_version: "21",
+}
diff --git a/packages/SettingsLib/ActionButtonsPreference/AndroidManifest.xml b/packages/SettingsLib/ActionButtonsPreference/AndroidManifest.xml
new file mode 100644
index 000000000000..4b9f1ab8d6cc
--- /dev/null
+++ b/packages/SettingsLib/ActionButtonsPreference/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.settingslib.widget">
+
+ <uses-sdk android:minSdkVersion="21" />
+
+</manifest>
diff --git a/packages/SettingsLib/ActionButtonsPreference/res/layout/settings_action_buttons.xml b/packages/SettingsLib/ActionButtonsPreference/res/layout/settings_action_buttons.xml
new file mode 100644
index 000000000000..4f47113bbafa
--- /dev/null
+++ b/packages/SettingsLib/ActionButtonsPreference/res/layout/settings_action_buttons.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="8dp"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/button1"
+ style="@style/SettingsActionButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+
+ <Button
+ android:id="@+id/button2"
+ style="@style/SettingsActionButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+
+ <Button
+ android:id="@+id/button3"
+ style="@style/SettingsActionButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+
+ <Button
+ android:id="@+id/button4"
+ style="@style/SettingsActionButton"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"/>
+</LinearLayout> \ No newline at end of file
diff --git a/packages/SettingsLib/ActionButtonsPreference/res/values/styles.xml b/packages/SettingsLib/ActionButtonsPreference/res/values/styles.xml
new file mode 100644
index 000000000000..efa508dcde62
--- /dev/null
+++ b/packages/SettingsLib/ActionButtonsPreference/res/values/styles.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <style name="SettingsActionButton" parent="android:Widget.DeviceDefault.Button.Borderless.Colored">
+ <item name="android:drawablePadding">4dp</item>
+ <item name="android:drawableTint">@*android:color/btn_colored_borderless_text_material</item>
+ <item name="android:layout_marginEnd">8dp</item>
+ <item name="android:paddingTop">20dp</item>
+ <item name="android:paddingBottom">20dp</item>
+ </style>
+</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/ActionButtonsPreference/src/com/android/settingslib/widget/ActionButtonsPreference.java b/packages/SettingsLib/ActionButtonsPreference/src/com/android/settingslib/widget/ActionButtonsPreference.java
new file mode 100644
index 000000000000..8b46cc608fd1
--- /dev/null
+++ b/packages/SettingsLib/ActionButtonsPreference/src/com/android/settingslib/widget/ActionButtonsPreference.java
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+
+import androidx.annotation.DrawableRes;
+import androidx.annotation.StringRes;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+/**
+ * This preference provides a four buttons layout with Settings style.
+ * It looks like below
+ *
+ * --------------------------------------------------
+ * button1 | button2 | button3 | button4 |
+ * --------------------------------------------------
+ *
+ * User can set title / icon / click listener for each button.
+ *
+ * By default, four buttons are visible.
+ * However, there are two cases which button should be invisible(View.GONE).
+ *
+ * 1. User sets invisible for button. ex: ActionButtonPreference.setButton1Visible(false)
+ * 2. User doesn't set any title or icon for button.
+ */
+public class ActionButtonsPreference extends Preference {
+
+ private static final String TAG = "ActionButtonPreference";
+ private final ButtonInfo mButton1Info = new ButtonInfo();
+ private final ButtonInfo mButton2Info = new ButtonInfo();
+ private final ButtonInfo mButton3Info = new ButtonInfo();
+ private final ButtonInfo mButton4Info = new ButtonInfo();
+
+ public ActionButtonsPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init();
+ }
+
+ public ActionButtonsPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init();
+ }
+
+ public ActionButtonsPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public ActionButtonsPreference(Context context) {
+ super(context);
+ init();
+ }
+
+ private void init() {
+ setLayoutResource(R.layout.settings_action_buttons);
+ setSelectable(false);
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ holder.setDividerAllowedAbove(true);
+ holder.setDividerAllowedBelow(true);
+
+ mButton1Info.mButton = (Button) holder.findViewById(R.id.button1);
+ mButton2Info.mButton = (Button) holder.findViewById(R.id.button2);
+ mButton3Info.mButton = (Button) holder.findViewById(R.id.button3);
+ mButton4Info.mButton = (Button) holder.findViewById(R.id.button4);
+
+ mButton1Info.setUpButton();
+ mButton2Info.setUpButton();
+ mButton3Info.setUpButton();
+ mButton4Info.setUpButton();
+ }
+
+ /**
+ * Set the visibility state of button1.
+ */
+ public ActionButtonsPreference setButton1Visible(boolean isVisible) {
+ if (isVisible != mButton1Info.mIsVisible) {
+ mButton1Info.mIsVisible = isVisible;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the text to be displayed in button1.
+ */
+ public ActionButtonsPreference setButton1Text(@StringRes int textResId) {
+ final String newText = getContext().getString(textResId);
+ if (!TextUtils.equals(newText, mButton1Info.mText)) {
+ mButton1Info.mText = newText;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the drawable to be displayed above of text in button1.
+ */
+ public ActionButtonsPreference setButton1Icon(@DrawableRes int iconResId) {
+ if (iconResId == 0) {
+ return this;
+ }
+
+ final Drawable icon;
+ try {
+ icon = getContext().getDrawable(iconResId);
+ mButton1Info.mIcon = icon;
+ notifyChanged();
+ } catch (Resources.NotFoundException exception) {
+ Log.e(TAG, "Resource does not exist: " + iconResId);
+ }
+ return this;
+ }
+
+ /**
+ * Set the enabled state of button1.
+ */
+ public ActionButtonsPreference setButton1Enabled(boolean isEnabled) {
+ if (isEnabled != mButton1Info.mIsEnabled) {
+ mButton1Info.mIsEnabled = isEnabled;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Register a callback to be invoked when button1 is clicked.
+ */
+ public ActionButtonsPreference setButton1OnClickListener(
+ View.OnClickListener listener) {
+ if (listener != mButton1Info.mListener) {
+ mButton1Info.mListener = listener;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Set the visibility state of button2.
+ */
+ public ActionButtonsPreference setButton2Visible(boolean isVisible) {
+ if (isVisible != mButton2Info.mIsVisible) {
+ mButton2Info.mIsVisible = isVisible;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the text to be displayed in button2.
+ */
+ public ActionButtonsPreference setButton2Text(@StringRes int textResId) {
+ final String newText = getContext().getString(textResId);
+ if (!TextUtils.equals(newText, mButton2Info.mText)) {
+ mButton2Info.mText = newText;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the drawable to be displayed above of text in button2.
+ */
+ public ActionButtonsPreference setButton2Icon(@DrawableRes int iconResId) {
+ if (iconResId == 0) {
+ return this;
+ }
+
+ final Drawable icon;
+ try {
+ icon = getContext().getDrawable(iconResId);
+ mButton2Info.mIcon = icon;
+ notifyChanged();
+ } catch (Resources.NotFoundException exception) {
+ Log.e(TAG, "Resource does not exist: " + iconResId);
+ }
+ return this;
+ }
+
+ /**
+ * Set the enabled state of button2.
+ */
+ public ActionButtonsPreference setButton2Enabled(boolean isEnabled) {
+ if (isEnabled != mButton2Info.mIsEnabled) {
+ mButton2Info.mIsEnabled = isEnabled;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Register a callback to be invoked when button2 is clicked.
+ */
+ public ActionButtonsPreference setButton2OnClickListener(
+ View.OnClickListener listener) {
+ if (listener != mButton2Info.mListener) {
+ mButton2Info.mListener = listener;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Set the visibility state of button3.
+ */
+ public ActionButtonsPreference setButton3Visible(boolean isVisible) {
+ if (isVisible != mButton3Info.mIsVisible) {
+ mButton3Info.mIsVisible = isVisible;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the text to be displayed in button3.
+ */
+ public ActionButtonsPreference setButton3Text(@StringRes int textResId) {
+ final String newText = getContext().getString(textResId);
+ if (!TextUtils.equals(newText, mButton3Info.mText)) {
+ mButton3Info.mText = newText;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the drawable to be displayed above of text in button3.
+ */
+ public ActionButtonsPreference setButton3Icon(@DrawableRes int iconResId) {
+ if (iconResId == 0) {
+ return this;
+ }
+
+ final Drawable icon;
+ try {
+ icon = getContext().getDrawable(iconResId);
+ mButton3Info.mIcon = icon;
+ notifyChanged();
+ } catch (Resources.NotFoundException exception) {
+ Log.e(TAG, "Resource does not exist: " + iconResId);
+ }
+ return this;
+ }
+
+ /**
+ * Set the enabled state of button3.
+ */
+ public ActionButtonsPreference setButton3Enabled(boolean isEnabled) {
+ if (isEnabled != mButton3Info.mIsEnabled) {
+ mButton3Info.mIsEnabled = isEnabled;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Register a callback to be invoked when button3 is clicked.
+ */
+ public ActionButtonsPreference setButton3OnClickListener(
+ View.OnClickListener listener) {
+ if (listener != mButton3Info.mListener) {
+ mButton3Info.mListener = listener;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Set the visibility state of button4.
+ */
+ public ActionButtonsPreference setButton4Visible(boolean isVisible) {
+ if (isVisible != mButton4Info.mIsVisible) {
+ mButton4Info.mIsVisible = isVisible;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the text to be displayed in button4.
+ */
+ public ActionButtonsPreference setButton4Text(@StringRes int textResId) {
+ final String newText = getContext().getString(textResId);
+ if (!TextUtils.equals(newText, mButton4Info.mText)) {
+ mButton4Info.mText = newText;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Sets the drawable to be displayed above of text in button4.
+ */
+ public ActionButtonsPreference setButton4Icon(@DrawableRes int iconResId) {
+ if (iconResId == 0) {
+ return this;
+ }
+
+ final Drawable icon;
+ try {
+ icon = getContext().getDrawable(iconResId);
+ mButton4Info.mIcon = icon;
+ notifyChanged();
+ } catch (Resources.NotFoundException exception) {
+ Log.e(TAG, "Resource does not exist: " + iconResId);
+ }
+ return this;
+ }
+
+ /**
+ * Set the enabled state of button4.
+ */
+ public ActionButtonsPreference setButton4Enabled(boolean isEnabled) {
+ if (isEnabled != mButton4Info.mIsEnabled) {
+ mButton4Info.mIsEnabled = isEnabled;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ /**
+ * Register a callback to be invoked when button4 is clicked.
+ */
+ public ActionButtonsPreference setButton4OnClickListener(
+ View.OnClickListener listener) {
+ if (listener != mButton4Info.mListener) {
+ mButton4Info.mListener = listener;
+ notifyChanged();
+ }
+ return this;
+ }
+
+ static class ButtonInfo {
+ private Button mButton;
+ private CharSequence mText;
+ private Drawable mIcon;
+ private View.OnClickListener mListener;
+ private boolean mIsEnabled = true;
+ private boolean mIsVisible = true;
+
+ void setUpButton() {
+ mButton.setText(mText);
+ mButton.setOnClickListener(mListener);
+ mButton.setEnabled(mIsEnabled);
+ mButton.setCompoundDrawablesWithIntrinsicBounds(
+ null /* left */, mIcon /* top */, null /* right */, null /* bottom */);
+
+ if (shouldBeVisible()) {
+ mButton.setVisibility(View.VISIBLE);
+ } else {
+ mButton.setVisibility(View.GONE);
+ }
+ }
+
+ /**
+ * By default, four buttons are visible.
+ * However, there are two cases which button should be invisible.
+ *
+ * 1. User set invisible for this button. ex: mIsVisible = false.
+ * 2. User didn't set any title or icon.
+ */
+ private boolean shouldBeVisible() {
+ return mIsVisible && (!TextUtils.isEmpty(mText) || mIcon != null);
+ }
+ }
+}
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index 444e72459510..cc17b25d9a40 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -17,6 +17,7 @@ android_library {
"SettingsLibSearchWidget",
"SettingsLibSettingsSpinner",
"SettingsLayoutPreference",
+ "ActionButtonsPreference",
],
// ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES
diff --git a/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml b/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml
index 06782633a4de..01d9c00d94dd 100644
--- a/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml
+++ b/packages/SettingsLib/SettingsLayoutPreference/res/layout/settings_entity_header.xml
@@ -35,7 +35,7 @@
android:id="@+id/entity_header_icon"
android:layout_width="48dp"
android:layout_height="48dp"
- android:scaleType="fitXY"
+ android:scaleType="fitCenter"
android:antialias="true"/>
<TextView
@@ -72,7 +72,6 @@
</LinearLayout>
<LinearLayout
- android:id="@+id/entity_header_links"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerVertical="true"
@@ -85,6 +84,7 @@
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="0dp"
+ android:visibility="gone"
android:minWidth="24dp"
android:src="@null"
android:tint="?android:attr/colorAccent"/>
@@ -95,6 +95,7 @@
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_height="0dp"
+ android:visibility="gone"
android:minWidth="24dp"
android:src="@null"
android:tint="?android:attr/colorAccent"/>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index a97e05442b6d..9270d13002d7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -208,6 +208,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
mHiSyncId = id;
}
+ public boolean isHearingAidDevice() {
+ return mHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID;
+ }
+
void onBondingDockConnect() {
// Attempt to connect if UUIDs are available. Otherwise,
// we will connect when the ACTION_UUID intent arrives.
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index d15a3ef2946d..cfa067f13680 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -32,12 +32,13 @@ include frameworks/base/packages/SettingsLib/common.mk
include $(BUILD_PACKAGE)
-#############################################
-# SettingsLib Robolectric test target. #
-#############################################
+############################################################
+# SettingsLib Robolectric test target. #
+############################################################
include $(CLEAR_VARS)
LOCAL_MODULE := SettingsLibRoboTests
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -53,6 +54,9 @@ LOCAL_INSTRUMENTATION_FOR := SettingsLibShell
LOCAL_MODULE_TAGS := optional
+# Generate test_config.properties
+include external/robolectric-shadows/gen_test_config.mk
+
include $(BUILD_STATIC_JAVA_LIBRARY)
#############################################################
diff --git a/packages/SettingsLib/tests/robotests/config/robolectric.properties b/packages/SettingsLib/tests/robotests/config/robolectric.properties
index 6b5b8e59472b..fab7251d020b 100644
--- a/packages/SettingsLib/tests/robotests/config/robolectric.properties
+++ b/packages/SettingsLib/tests/robotests/config/robolectric.properties
@@ -1,5 +1 @@
-manifest=frameworks/base/packages/SettingsLib/tests/robotests/AndroidManifest.xml
sdk=NEWEST_SDK
-
-shadows=\
- com.android.settingslib.testutils.shadow.ShadowXmlUtils \ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java
index 9ba996752f49..3a4e2e403ee0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceComaptTest.java
@@ -30,10 +30,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class CustomEditTextPreferenceComaptTest {
@Mock
@@ -70,7 +71,7 @@ public class CustomEditTextPreferenceComaptTest {
}
private static class TestPreference extends CustomEditTextPreferenceCompat {
- public TestPreference(Context context) {
+ private TestPreference(Context context) {
super(context);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceTest.java
index 9d7f59a78fa5..e94a06ce7f6d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/CustomEditTextPreferenceTest.java
@@ -30,10 +30,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class CustomEditTextPreferenceTest {
@Mock
@@ -70,7 +71,7 @@ public class CustomEditTextPreferenceTest {
}
private static class TestPreference extends CustomEditTextPreference {
- public TestPreference(Context context) {
+ private TestPreference(Context context) {
super(context);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/DeviceInfoUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/DeviceInfoUtilsTest.java
index 19a916cf85da..4e8af7350f8a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/DeviceInfoUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/DeviceInfoUtilsTest.java
@@ -24,9 +24,10 @@ import android.system.StructUtsname;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class DeviceInfoUtilsTest {
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
index 36b70dfe2297..4d76331d8da7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/HelpUtilsTest.java
@@ -18,12 +18,13 @@ package com.android.settingslib;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.R;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -36,20 +37,19 @@ import android.content.res.TypedArray;
import android.provider.Settings;
import android.view.MenuItem;
-import android.R;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
/**
* Tests for {@link HelpUtils}.
*/
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class HelpUtilsTest {
private static final String TEST_HELP_URL = "intent:#Intent;action=com.android.test;end";
private static final String PACKAGE_NAME_KEY = "package-name-key";
@@ -83,8 +83,6 @@ public class HelpUtilsTest {
when(mContext.getResources().getString(R.string.config_feedbackIntentNameKey))
.thenReturn(FEEDBACK_INTENT_NAME_KEY);
when(mActivity.getPackageManager()).thenReturn(mPackageManager);
-
-
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
index 88ac8ce5fae5..2b5a4e069001 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedLockUtilsTest.java
@@ -25,8 +25,8 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
@@ -44,11 +44,12 @@ import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import java.util.Collections;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class RestrictedLockUtilsTest {
@Mock
@@ -178,8 +179,7 @@ public class RestrictedLockUtilsTest {
public void checkIfKeyguardFeaturesAreDisabled_doesMatchAllowedFeature_unifiedManagedProfile() {
UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
- when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
- userInfo, profileInfo}));
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(userInfo, profileInfo));
when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
.thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
@@ -207,8 +207,7 @@ public class RestrictedLockUtilsTest {
public void checkIfKeyguardFeaturesAreDisabled_notMatchOtherFeatures_unifiedManagedProfile() {
UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
- when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
- userInfo, profileInfo}));
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(userInfo, profileInfo));
when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
.thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
@@ -231,8 +230,7 @@ public class RestrictedLockUtilsTest {
public void checkIfKeyguardFeaturesAreDisabled_onlyMatchesProfile_separateManagedProfile() {
UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
- when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
- userInfo, profileInfo}));
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(userInfo, profileInfo));
when(mDevicePolicyManager.getKeyguardDisabledFeatures(mAdmin1, mUserId))
.thenReturn(KEYGUARD_DISABLE_FEATURES_NONE);
@@ -268,8 +266,7 @@ public class RestrictedLockUtilsTest {
public void checkIfKeyguardFeaturesAreDisabled_onlyMatchesParent_profileParentPolicy() {
UserInfo userInfo = setUpUser(mUserId, new ComponentName[] {mAdmin1});
UserInfo profileInfo = setUpManagedProfile(mProfileId, new ComponentName[] {mAdmin2});
- when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(new UserInfo[] {
- userInfo, profileInfo}));
+ when(mUserManager.getProfiles(mUserId)).thenReturn(Arrays.asList(userInfo, profileInfo));
when(mProxy.getParentProfileInstance(any(DevicePolicyManager.class), any())
.getKeyguardDisabledFeatures(mAdmin2, mProfileId))
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
index 79d682d67a4a..1b10c736f266 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/RestrictedPreferenceHelperTest.java
@@ -16,7 +16,6 @@
package com.android.settingslib;
-
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -35,8 +34,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class RestrictedPreferenceHelperTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
deleted file mode 100644
index 8757eed8b746..000000000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/SettingsLibRobolectricTestRunner.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.settingslib;
-
-import android.annotation.NonNull;
-
-import org.junit.runners.model.InitializationError;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-import org.robolectric.manifest.AndroidManifest;
-import org.robolectric.res.Fs;
-import org.robolectric.res.ResourcePath;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.List;
-
-public class SettingsLibRobolectricTestRunner extends RobolectricTestRunner {
-
- public SettingsLibRobolectricTestRunner(Class<?> testClass) throws InitializationError {
- super(testClass);
- }
-
- /**
- * We are going to create our own custom manifest so we can add multiple resource paths to it.
- */
- @Override
- protected AndroidManifest getAppManifest(Config config) {
- try {
- // Using the manifest file's relative path, we can figure out the application directory.
- final URL appRoot =
- new URL("file:frameworks/base/packages/SettingsLib/tests/robotests");
- final URL manifestPath = new URL(appRoot, "AndroidManifest.xml");
- final URL resDir = new URL(appRoot, "res");
- final URL assetsDir = new URL(appRoot, "assets");
-
- return new AndroidManifest(Fs.fromURL(manifestPath), Fs.fromURL(resDir),
- Fs.fromURL(assetsDir), "com.android.settingslib") {
- @Override
- public List<ResourcePath> getIncludedResourcePaths() {
- final List<ResourcePath> paths = super.getIncludedResourcePaths();
- paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/AppPreference/res"));
- paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/HelpUtils/res"));
- paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/RestrictedLockUtils/res"));
- paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/"
- + "SettingsLayoutPreference/res"));
- paths.add(resourcePath("file:frameworks/base/packages/SettingsLib/res"));
- paths.add(resourcePath("file:frameworks/base/core/res/res"));
- paths.add(resourcePath("file:out/soong/.intermediates/prebuilts/sdk/current/androidx/androidx.appcompat_appcompat-nodeps/android_common/aar/res/"));
- return paths;
- }
- };
- } catch (MalformedURLException e) {
- throw new RuntimeException("SettingsLibRobolectricTestRunner failure", e);
- }
- }
-
- private static ResourcePath resourcePath(@NonNull String spec) {
- try {
- return new ResourcePath(null, Fs.fromURL(new URL(spec)), null);
- } catch (MalformedURLException e) {
- throw new RuntimeException("SettingsLibRobolectricTestRunner failure", e);
- }
- }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java
index e70baa197123..0ca779162ef2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TetherUtilTest.java
@@ -32,12 +32,13 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.List;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class TetherUtilTest {
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
index c0b69f2260eb..3f0ba13ce50a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/TwoTargetPreferenceTest.java
@@ -36,9 +36,10 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class TwoTargetPreferenceTest {
private PreferenceViewHolder mViewHolder;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index 08a75ab3cfd5..594d767675c8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -49,6 +49,7 @@ import org.mockito.ArgumentMatcher;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
@@ -58,10 +59,8 @@ import org.robolectric.shadows.ShadowSettings;
import java.util.HashMap;
import java.util.Map;
-@RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(shadows = {
- UtilsTest.ShadowSecure.class,
- UtilsTest.ShadowLocationManager.class})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {UtilsTest.ShadowSecure.class, UtilsTest.ShadowLocationManager.class})
public class UtilsTest {
private static final double[] TEST_PERCENTAGES = {0, 0.4, 0.5, 0.6, 49, 49.3, 49.8, 50, 100};
private static final String PERCENTAGE_0 = "0%";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/accessibility/AccessibilityUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/accessibility/AccessibilityUtilsTest.java
index 152d024d0155..44fdaec49f73 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/accessibility/AccessibilityUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/accessibility/AccessibilityUtilsTest.java
@@ -23,14 +23,13 @@ import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class AccessibilityUtilsTest {
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
index b307b4730fa1..ccec175aefad 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ApplicationsStateRoboTest.java
@@ -41,7 +41,6 @@ import android.os.Handler;
import android.os.UserHandle;
import android.util.IconDrawableFactory;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.Callbacks;
import com.android.settingslib.applications.ApplicationsState.Session;
@@ -55,6 +54,7 @@ import org.mockito.ArgumentMatchers;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
@@ -67,7 +67,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowUserManager.class,
ApplicationsStateRoboTest.ShadowIconDrawableFactory.class,
ApplicationsStateRoboTest.ShadowPackageManager.class})
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java
index a92a2dd8c11a..50fad70f0a0e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/DefaultAppInfoTest.java
@@ -18,8 +18,8 @@ package com.android.settingslib.applications;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -32,16 +32,15 @@ import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class DefaultAppInfoTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
index d8c459c07b75..f7fd25b9fb7d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/applications/ServiceListingTest.java
@@ -26,14 +26,13 @@ import static org.mockito.Mockito.verify;
import android.content.ComponentName;
import android.provider.Settings;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class ServiceListingTest {
private static final String TEST_SETTING = "testSetting";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
index 29831a89027a..c555cbec4bab 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -17,8 +17,8 @@ package com.android.settingslib.bluetooth;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -32,7 +32,6 @@ import android.content.Context;
import android.content.res.Resources;
import com.android.settingslib.R;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
@@ -40,26 +39,27 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class A2dpProfileTest {
@Mock
- Context mContext;
+ private Context mContext;
@Mock
- CachedBluetoothDeviceManager mDeviceManager;
+ private CachedBluetoothDeviceManager mDeviceManager;
@Mock
- LocalBluetoothProfileManager mProfileManager;
+ private LocalBluetoothProfileManager mProfileManager;
@Mock
- BluetoothDevice mDevice;
+ private BluetoothDevice mDevice;
@Mock
- BluetoothA2dp mBluetoothA2dp;
- BluetoothProfile.ServiceListener mServiceListener;
+ private BluetoothA2dp mBluetoothA2dp;
+ private BluetoothProfile.ServiceListener mServiceListener;
- A2dpProfile mProfile;
+ private A2dpProfile mProfile;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
@Before
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java
index 274fff83ea8a..976445eb8c04 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java
@@ -18,18 +18,14 @@ package com.android.settingslib.bluetooth;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.bluetooth.BluetoothA2dpSink;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothA2dpSink;
import android.bluetooth.BluetoothProfile;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
@@ -37,11 +33,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class A2dpSinkProfileTest {
@@ -52,8 +49,6 @@ public class A2dpSinkProfileTest {
@Mock
private BluetoothA2dpSink mService;
@Mock
- private CachedBluetoothDevice mCachedBluetoothDevice;
- @Mock
private BluetoothDevice mBluetoothDevice;
private BluetoothProfile.ServiceListener mServiceListener;
private A2dpSinkProfile mProfile;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
index c147d5e306c2..27b8dfc28448 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
@@ -29,20 +29,18 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.os.Handler;
import android.os.UserHandle;
import android.telephony.TelephonyManager;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class BluetoothEventManagerTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index 07310bd5746c..0eb6de9584eb 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -21,14 +21,14 @@ import android.bluetooth.BluetoothDevice;
import android.graphics.drawable.Drawable;
import com.android.settingslib.R;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class BluetoothUtilsTest {
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index 9c7549147217..47b12103e772 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -28,18 +28,17 @@ import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.Collection;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class CachedBluetoothDeviceManagerTest {
private final static String DEVICE_NAME_1 = "TestName_1";
private final static String DEVICE_NAME_2 = "TestName_2";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 5ceede1ccf72..4e5d38ab5799 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -31,16 +31,15 @@ import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.media.AudioManager;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class CachedBluetoothDeviceTest {
private final static String DEVICE_NAME = "TestName";
private final static String DEVICE_ALIAS = "TestAlias";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
index c0a1f0cda3ee..9adef8287355 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
@@ -11,7 +11,6 @@ import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
@@ -19,11 +18,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class HeadsetProfileTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
index cb1b12d04f83..2b5466c4161f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
@@ -29,16 +29,15 @@ import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class HearingAidDeviceManagerTest {
private final static long HISYNCID1 = 10;
private final static long HISYNCID2 = 11;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java
index 187be0bf647b..69c020dd5c08 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java
@@ -18,18 +18,14 @@ package com.android.settingslib.bluetooth;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothProfile;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
@@ -37,11 +33,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class HfpClientProfileTest {
@@ -52,8 +49,6 @@ public class HfpClientProfileTest {
@Mock
private BluetoothHeadsetClient mService;
@Mock
- private CachedBluetoothDevice mCachedBluetoothDevice;
- @Mock
private BluetoothDevice mBluetoothDevice;
private BluetoothProfile.ServiceListener mServiceListener;
private HfpClientProfile mProfile;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java
index c91ee22d8587..f38af70c7498 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HidDeviceProfileTest.java
@@ -18,18 +18,14 @@ package com.android.settingslib.bluetooth;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHidDevice;
import android.bluetooth.BluetoothProfile;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
@@ -37,11 +33,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class HidDeviceProfileTest {
@@ -52,8 +49,6 @@ public class HidDeviceProfileTest {
@Mock
private BluetoothHidDevice mService;
@Mock
- private CachedBluetoothDevice mCachedBluetoothDevice;
- @Mock
private BluetoothDevice mBluetoothDevice;
private BluetoothProfile.ServiceListener mServiceListener;
private HidDeviceProfile mProfile;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index a3c3a54c38f0..5d5872ea2354 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -37,7 +37,6 @@ import android.content.Context;
import android.content.Intent;
import android.os.ParcelUuid;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
@@ -45,6 +44,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
@@ -52,7 +52,7 @@ import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.List;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class LocalBluetoothProfileManagerTest {
private final static long HISYNCID = 10;
@@ -270,13 +270,13 @@ public class LocalBluetoothProfileManagerTest {
verify(mCachedBluetoothDevice).refresh();
}
- private List<Integer> generateList(int[] profile) {
- if (profile == null) {
+ private List<Integer> generateList(int[] profiles) {
+ if (profiles == null) {
return null;
}
- final List<Integer> profileList = new ArrayList<>(profile.length);
- for(int i = 0; i < profile.length; i++) {
- profileList.add(profile[i]);
+ final List<Integer> profileList = new ArrayList<>(profiles.length);
+ for (int profile : profiles) {
+ profileList.add(profile);
}
return profileList;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java
index c4c48a8bce8c..6f667094a5aa 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/MapClientProfileTest.java
@@ -18,18 +18,14 @@ package com.android.settingslib.bluetooth;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothMapClient;
import android.bluetooth.BluetoothProfile;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
@@ -37,11 +33,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class MapClientProfileTest {
@@ -52,8 +49,6 @@ public class MapClientProfileTest {
@Mock
private BluetoothMapClient mService;
@Mock
- private CachedBluetoothDevice mCachedBluetoothDevice;
- @Mock
private BluetoothDevice mBluetoothDevice;
private BluetoothProfile.ServiceListener mServiceListener;
private MapClientProfile mProfile;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PbapClientProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PbapClientProfileTest.java
index e4a444c836ab..b21ec9c3e52a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PbapClientProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/PbapClientProfileTest.java
@@ -18,18 +18,14 @@ package com.android.settingslib.bluetooth;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothPbapClient;
import android.bluetooth.BluetoothProfile;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
@@ -37,12 +33,13 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
-@RunWith(SettingsLibRobolectricTestRunner.class)
-@Config(shadows = {ShadowBluetoothAdapter.class})
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowBluetoothAdapter.class)
public class PbapClientProfileTest {
@Mock
@@ -52,8 +49,6 @@ public class PbapClientProfileTest {
@Mock
private BluetoothPbapClient mService;
@Mock
- private CachedBluetoothDevice mCachedBluetoothDevice;
- @Mock
private BluetoothDevice mBluetoothDevice;
private BluetoothProfile.ServiceListener mServiceListener;
private PbapClientProfile mProfile;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java
index 9bb53ee6a343..ec880345f6f0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/SapProfileTest.java
@@ -18,18 +18,14 @@ package com.android.settingslib.bluetooth;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothSap;
import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothSap;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import org.junit.Before;
@@ -37,11 +33,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowBluetoothAdapter.class})
public class SapProfileTest {
@@ -52,8 +49,6 @@ public class SapProfileTest {
@Mock
private BluetoothSap mService;
@Mock
- private CachedBluetoothDevice mCachedBluetoothDevice;
- @Mock
private BluetoothDevice mBluetoothDevice;
private BluetoothProfile.ServiceListener mServiceListener;
private SapProfile mProfile;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java
index 4d7553cd85da..28de1914838f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/AbstractPreferenceControllerTest.java
@@ -24,16 +24,15 @@ import android.content.Context;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class AbstractPreferenceControllerTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
index 4ec6fb2efab1..8a0ae9190a8c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
@@ -27,7 +27,6 @@ import android.content.Context;
import android.content.Intent;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
@@ -35,13 +34,14 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
import java.util.ArrayList;
import java.util.List;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class MetricsFeatureProviderTest {
@Mock
private LogWriter mLogWriter;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
index 6285fcdb10b3..8f51dece64e5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -17,8 +17,8 @@ package com.android.settingslib.core.instrumentation;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -26,16 +26,15 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.SharedPreferences;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class SharedPreferenceLoggerTest {
private static final String TEST_TAG = "tag";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
index b251c09ff33e..097db176a99a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
@@ -17,10 +17,10 @@ package com.android.settingslib.core.instrumentation;
import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -35,7 +35,6 @@ import android.os.Bundle;
import androidx.fragment.app.FragmentActivity;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
@@ -43,10 +42,10 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.android.controller.ActivityController;
-
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class VisibilityLoggerMixinTest {
@Mock
@@ -139,7 +138,7 @@ public class VisibilityLoggerMixinTest {
private final class TestInstrumentable implements Instrumentable {
- public static final int TEST_METRIC = 12345;
+ private static final int TEST_METRIC = 12345;
@Override
public int getMetricsCategory() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
index 887c1d57c870..29e37e4938a8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/lifecycle/LifecycleTest.java
@@ -28,7 +28,6 @@ import android.widget.LinearLayout;
import androidx.lifecycle.LifecycleOwner;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.events.OnAttach;
import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu;
import com.android.settingslib.core.lifecycle.events.OnDestroy;
@@ -43,10 +42,11 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.shadows.androidx.fragment.FragmentController;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class LifecycleTest {
private LifecycleOwner mLifecycleOwner;
@@ -56,7 +56,7 @@ public class LifecycleTest {
final TestObserver mFragObserver;
- public TestDialogFragment() {
+ private TestDialogFragment() {
mFragObserver = new TestObserver();
mLifecycle.addObserver(mFragObserver);
}
@@ -236,11 +236,11 @@ public class LifecycleTest {
}
private static class OptionItemAccepter implements LifecycleObserver, OnOptionsItemSelected {
- public boolean wasCalled = false;
+ private boolean mWasCalled = false;
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
- wasCalled = true;
+ mWasCalled = true;
return false;
}
}
@@ -258,14 +258,14 @@ public class LifecycleTest {
fragment.onPrepareOptionsMenu(null);
fragment.onOptionsItemSelected(null);
- assertThat(accepter.wasCalled).isFalse();
+ assertThat(accepter.mWasCalled).isFalse();
}
private class OnStartObserver implements LifecycleObserver, OnStart {
private final Lifecycle mLifecycle;
- public OnStartObserver(Lifecycle lifecycle) {
+ private OnStartObserver(Lifecycle lifecycle) {
mLifecycle = lifecycle;
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DeveloperOptionsPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DeveloperOptionsPreferenceControllerTest.java
index 9dd93b3af390..6191a00b377c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DeveloperOptionsPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DeveloperOptionsPreferenceControllerTest.java
@@ -22,16 +22,15 @@ import static org.mockito.Mockito.verify;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class DeveloperOptionsPreferenceControllerTest {
private static final String TEST_KEY = "Test_pref_key";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java
index a0fa6b599b45..3475ff7d96f8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/DevelopmentSettingsEnablerTest.java
@@ -18,23 +18,19 @@ package com.android.settingslib.development;
import static com.google.common.truth.Truth.assertThat;
-import android.os.UserManager;
import android.content.Context;
+import android.os.UserManager;
import android.provider.Settings;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
-import org.robolectric.shadows.ShadowUserManager;
-import org.robolectric.shadow.api.Shadow;
-
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowUserManager;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class DevelopmentSettingsEnablerTest {
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
index d7b23b0ef636..e84a25c0ba4e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/EnableAdbPreferenceControllerTest.java
@@ -32,17 +32,16 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class EnableAdbPreferenceControllerTest {
@Mock(answer = RETURNS_DEEP_STUBS)
private PreferenceScreen mScreen;
@@ -150,7 +149,7 @@ public class EnableAdbPreferenceControllerTest {
}
class ConcreteEnableAdbPreferenceController extends AbstractEnableAdbPreferenceController {
- public ConcreteEnableAdbPreferenceController(Context context) {
+ private ConcreteEnableAdbPreferenceController(Context context) {
super(context);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java
index 2f78899ff92d..146be23f1683 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogdSizePreferenceControllerTest.java
@@ -45,16 +45,16 @@ import androidx.preference.ListPreference;
import androidx.preference.PreferenceScreen;
import com.android.settingslib.R;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class LogdSizePreferenceControllerTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
index ed128e098c6f..d5afb4b08a93 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/LogpersistPreferenceControllerTest.java
@@ -29,7 +29,6 @@ import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -37,9 +36,10 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class LogpersistPreferenceControllerTest {
private LifecycleOwner mLifecycleOwner;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropPokerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropPokerTest.java
index 40db478f2dc7..d1212fcad864 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropPokerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/development/SystemPropPokerTest.java
@@ -27,16 +27,15 @@ import static org.mockito.Mockito.verify;
import android.os.IBinder;
import android.os.Parcel;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import org.robolectric.RobolectricTestRunner;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class SystemPropPokerTest {
@Spy
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java
index 234b4d5ac604..16de5f804b68 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/BluetoothAddressPreferenceControllerTest.java
@@ -26,7 +26,6 @@ import android.content.Context;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -34,11 +33,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class BluetoothAddressPreferenceControllerTest {
@Mock
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java
index aee956cf5518..4444e6369b67 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ConnectivityPreferenceControllerTest.java
@@ -30,7 +30,6 @@ import android.content.Context;
import android.content.IntentFilter;
import android.os.Handler;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -39,8 +38,9 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class ConnectivityPreferenceControllerTest {
@Mock
private Context mContext;
@@ -91,8 +91,7 @@ public class ConnectivityPreferenceControllerTest {
private static class ConcreteConnectivityPreferenceController
extends AbstractConnectivityPreferenceController {
-
- public ConcreteConnectivityPreferenceController(Context context,
+ private ConcreteConnectivityPreferenceController(Context context,
Lifecycle lifecycle) {
super(context, lifecycle);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java
index 2b490ee63856..bd223bd778bb 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/ImsStatusPreferenceControllerTest.java
@@ -25,12 +25,10 @@ import static org.mockito.Mockito.mock;
import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -38,11 +36,10 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowSubscriptionManager;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class ImsStatusPreferenceControllerTest {
@Mock
private Context mContext;
@@ -61,8 +58,9 @@ public class ImsStatusPreferenceControllerTest {
}
@Test
- @Config(shadows = ShadowSubscriptionManager.class)
public void testIsAvailable() {
+ ShadowSubscriptionManager.setDefaultDataSubscriptionId(1234);
+
CarrierConfigManager carrierConfigManager = mock(CarrierConfigManager.class);
doReturn(carrierConfigManager).when(mContext).getSystemService(CarrierConfigManager.class);
@@ -92,18 +90,10 @@ public class ImsStatusPreferenceControllerTest {
.that(imsStatusPreferenceController.isAvailable()).isFalse();
}
- @Implements(SubscriptionManager.class)
- public static class ShadowSubscriptionManager {
- @Implementation
- public static int getDefaultDataSubscriptionId() {
- return 1234;
- }
- }
-
private static class ConcreteImsStatusPreferenceController
extends AbstractImsStatusPreferenceController {
- public ConcreteImsStatusPreferenceController(Context context,
+ private ConcreteImsStatusPreferenceController(Context context,
Lifecycle lifecycle) {
super(context, lifecycle);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java
index 1d957c3b5e5b..76a26d917969 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/IpAddressPreferenceControllerTest.java
@@ -27,7 +27,6 @@ import android.net.wifi.WifiManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -35,11 +34,12 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import java.util.List;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class IpAddressPreferenceControllerTest {
@Mock
private Context mContext;
@@ -75,8 +75,7 @@ public class IpAddressPreferenceControllerTest {
private static class ConcreteIpAddressPreferenceController extends
AbstractIpAddressPreferenceController {
- public ConcreteIpAddressPreferenceController(Context context,
- Lifecycle lifecycle) {
+ private ConcreteIpAddressPreferenceController(Context context, Lifecycle lifecycle) {
super(context, lifecycle);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java
index dc77400e2547..5b71bdd3d760 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SerialNumberPreferenceControllerTest.java
@@ -25,16 +25,15 @@ import android.content.Context;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class SerialNumberPreferenceControllerTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
index eb77cb6271e9..5252c6c82754 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/SimStatusImeiInfoPreferenceControllerTest.java
@@ -24,17 +24,16 @@ import android.net.ConnectivityManager;
import android.os.UserManager;
import android.util.SparseBooleanArray;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {SimStatusImeiInfoPreferenceControllerTest.ShadowUserManager.class,
SimStatusImeiInfoPreferenceControllerTest.ShadowConnectivityManager.class})
public class SimStatusImeiInfoPreferenceControllerTest {
@@ -106,7 +105,7 @@ public class SimStatusImeiInfoPreferenceControllerTest {
private final SparseBooleanArray mSupportedNetworkTypes = new SparseBooleanArray();
- public void setNetworkSupported(int networkType, boolean supported) {
+ private void setNetworkSupported(int networkType, boolean supported) {
mSupportedNetworkTypes.put(networkType, supported);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
index 2e0348daaa51..f09879b95221 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/UptimePreferenceControllerTest.java
@@ -28,7 +28,6 @@ import android.text.format.DateUtils;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -36,9 +35,10 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.shadows.ShadowLooper;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class UptimePreferenceControllerTest {
@Mock
private Context mContext;
@@ -92,7 +92,7 @@ public class UptimePreferenceControllerTest {
private static class ConcreteUptimePreferenceController
extends AbstractUptimePreferenceController {
- public ConcreteUptimePreferenceController(Context context,
+ private ConcreteUptimePreferenceController(Context context,
Lifecycle lifecycle) {
super(context, lifecycle);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java
index 359ea7791922..74e5bf5a8034 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/deviceinfo/WifiMacAddressPreferenceControllerTest.java
@@ -33,7 +33,6 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settingslib.R;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -41,13 +40,14 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.Arrays;
import java.util.List;
@SuppressLint("HardwareIds")
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class WifiMacAddressPreferenceControllerTest {
@Mock
private Lifecycle mLifecycle;
@@ -197,7 +197,7 @@ public class WifiMacAddressPreferenceControllerTest {
private static class ConcreteWifiMacAddressPreferenceController
extends AbstractWifiMacAddressPreferenceController {
- public ConcreteWifiMacAddressPreferenceController(Context context,
+ private ConcreteWifiMacAddressPreferenceController(Context context,
Lifecycle lifecycle) {
super(context, lifecycle);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java
index ca621ca66829..c0924d9a8b35 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/display/BrightnessUtilsTest.java
@@ -20,12 +20,11 @@ import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX;
import static com.google.common.truth.Truth.assertThat;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class BrightnessUtilsTest {
private static final int MIN = 1;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
index 59a3dd61475c..605c861fa07f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/CategoryKeyTest.java
@@ -20,14 +20,13 @@ import static com.google.common.truth.Truth.assertThat;
import android.util.ArraySet;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import java.util.Set;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class CategoryKeyTest {
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
index 40e7386cf5af..b77670bd01e5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileTest.java
@@ -13,15 +13,14 @@ import android.content.pm.ActivityInfo;
import android.os.Bundle;
import com.android.settingslib.R;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class TileTest {
private ActivityInfo mActivityInfo;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 362ae4c84cbf..bbb4249317f7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -54,7 +54,6 @@ import android.util.ArrayMap;
import android.util.Pair;
import com.android.settingslib.R;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
@@ -62,12 +61,13 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class TileUtilsTest {
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
index d0b6dab43281..2988905b44a6 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/BatterySaverUtilsTest.java
@@ -33,28 +33,26 @@ import android.os.PowerManager;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
-
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class BatterySaverUtilsTest {
- final int BATTERY_SAVER_THRESHOLD_1 = 15;
- final int BATTERY_SAVER_THRESHOLD_2 = 20;
+ private static final int BATTERY_SAVER_THRESHOLD_1 = 15;
+ private static final int BATTERY_SAVER_THRESHOLD_2 = 20;
@Mock
- Context mMockContext;
+ private Context mMockContext;
@Mock
- ContentResolver mMockResolver;
+ private ContentResolver mMockResolver;
@Mock
- PowerManager mMockPowerManager;
+ private PowerManager mMockPowerManager;
@Before
public void setUp() throws Exception {
@@ -66,11 +64,11 @@ public class BatterySaverUtilsTest {
}
@Test
- public void testSetPowerSaveMode_enable_firstCall_needWarning() throws Exception {
+ public void testSetPowerSaveMode_enable_firstCall_needWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
- assertEquals(false, BatterySaverUtils.setPowerSaveMode(mMockContext, true, true));
+ assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isFalse();
verify(mMockContext, times(1)).sendBroadcast(any(Intent.class));
verify(mMockPowerManager, times(0)).setPowerSaveMode(anyBoolean());
@@ -83,11 +81,11 @@ public class BatterySaverUtilsTest {
}
@Test
- public void testSetPowerSaveMode_enable_secondCall_needWarning() throws Exception {
+ public void testSetPowerSaveMode_enable_secondCall_needWarning() {
Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
- assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, true, true));
+ assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(true));
@@ -97,11 +95,11 @@ public class BatterySaverUtilsTest {
}
@Test
- public void testSetPowerSaveMode_enable_thridCall_needWarning() throws Exception {
+ public void testSetPowerSaveMode_enable_thridCall_needWarning() {
Secure.putInt(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, 1); // Already acked.
Secure.putInt(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, 1);
- assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, true, true));
+ assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, true)).isTrue();
verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(true));
@@ -111,11 +109,11 @@ public class BatterySaverUtilsTest {
}
@Test
- public void testSetPowerSaveMode_enable_firstCall_noWarning() throws Exception {
+ public void testSetPowerSaveMode_enable_firstCall_noWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
- assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, true, false));
+ assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, true, false)).isTrue();
verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(true));
@@ -125,12 +123,12 @@ public class BatterySaverUtilsTest {
}
@Test
- public void testSetPowerSaveMode_disable_firstCall_noWarning() throws Exception {
+ public void testSetPowerSaveMode_disable_firstCall_noWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
// When disabling, needFirstTimeWarning doesn't matter.
- assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, false, false));
+ assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, false, false)).isTrue();
verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(false));
@@ -141,12 +139,12 @@ public class BatterySaverUtilsTest {
}
@Test
- public void testSetPowerSaveMode_disable_firstCall_needWarning() throws Exception {
+ public void testSetPowerSaveMode_disable_firstCall_needWarning() {
Secure.putString(mMockResolver, Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
Secure.putString(mMockResolver, Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT, "null");
// When disabling, needFirstTimeWarning doesn't matter.
- assertEquals(true, BatterySaverUtils.setPowerSaveMode(mMockContext, false, true));
+ assertThat(BatterySaverUtils.setPowerSaveMode(mMockContext, false, true)).isTrue();
verify(mMockContext, times(0)).sendBroadcast(any(Intent.class));
verify(mMockPowerManager, times(1)).setPowerSaveMode(eq(false));
@@ -157,7 +155,7 @@ public class BatterySaverUtilsTest {
}
@Test
- public void testEnsureAutoBatterysaver_setNewPositiveValue_doNotOverwrite() throws Exception {
+ public void testEnsureAutoBatterysaver_setNewPositiveValue_doNotOverwrite() {
Global.putInt(mMockResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
BatterySaverUtils.ensureAutoBatterySaver(mMockContext, BATTERY_SAVER_THRESHOLD_1);
@@ -172,7 +170,7 @@ public class BatterySaverUtilsTest {
}
@Test
- public void testSetAutoBatterySaverTriggerLevel_setSuppressSuggestion() throws Exception {
+ public void testSetAutoBatterySaverTriggerLevel_setSuppressSuggestion() {
Global.putString(mMockResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, "null");
Secure.putString(mMockResolver, Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION, "null");
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index 9b1fe5f6029d..bbf807d29402 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -31,7 +31,6 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.os.IDeviceIdleController;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowDefaultDialerManager;
import com.android.settingslib.testutils.shadow.ShadowSmsApplication;
@@ -40,12 +39,13 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowPackageManager;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDefaultDialerManager.class, ShadowSmsApplication.class})
public class PowerWhitelistBackendTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index 49dde0e6fcfa..35743c219129 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -16,8 +16,8 @@
package com.android.settingslib.graph;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -25,17 +25,16 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class BatteryMeterDrawableBaseTest {
private static final int CRITICAL_LEVEL = 5;
private static final int PADDING = 5;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java
index 5dbb5caf60eb..1b350cc83285 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java
@@ -22,14 +22,14 @@ import android.content.Context;
import android.graphics.drawable.VectorDrawable;
import com.android.settingslib.R;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class BluetoothDeviceLayerDrawableTest {
private static final int RES_ID = R.drawable.ic_bt_cellphone;
private static final int BATTERY_LEVEL = 15;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
index fa64afec0461..b930aa6ee1bd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilCompatTest.java
@@ -25,26 +25,21 @@ import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class InputMethodAndSubtypeUtilCompatTest {
private static final HashSet<String> EMPTY_STRING_SET = new HashSet<>();
private static HashSet<String> asHashSet(String... strings) {
- HashSet<String> hashSet = new HashSet<>();
- for (String s : strings) {
- hashSet.add(s);
- }
- return hashSet;
+ return new HashSet<>(Arrays.asList(strings));
}
@Test
@@ -105,7 +100,6 @@ public class InputMethodAndSubtypeUtilCompatTest {
"ime0;subtype0;subtype1:ime1;subtype1;subtype2"))
.containsExactly("ime0", asHashSet("subtype0", "subtype1"),
"ime1", asHashSet("subtype1", "subtype2"));
-
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java
index 03ab261aa75a..84606b4e4502 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/inputmethod/InputMethodAndSubtypeUtilTest.java
@@ -25,26 +25,21 @@ import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class InputMethodAndSubtypeUtilTest {
private static final HashSet<String> EMPTY_STRING_SET = new HashSet<>();
private static HashSet<String> asHashSet(String... strings) {
- HashSet<String> hashSet = new HashSet<>();
- for (String s : strings) {
- hashSet.add(s);
- }
- return hashSet;
+ return new HashSet<>(Arrays.asList(strings));
}
@Test
@@ -103,7 +98,6 @@ public class InputMethodAndSubtypeUtilTest {
"ime0;subtype0;subtype1:ime1;subtype1;subtype2"))
.containsExactly("ime0", asHashSet("subtype0", "subtype1"),
"ime1", asHashSet("subtype1", "subtype2"));
-
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
index b00476b24921..4b5e9097b3fe 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlGeneratorFromXmlTest.java
@@ -18,10 +18,9 @@ package com.android.settingslib.license;
import static com.google.common.truth.Truth.assertThat;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.xmlpull.v1.XmlPullParserException;
import java.io.ByteArrayInputStream;
@@ -32,7 +31,7 @@ import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class LicenseHtmlGeneratorFromXmlTest {
private static final String VALILD_XML_STRING =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
@@ -92,8 +91,8 @@ public class LicenseHtmlGeneratorFromXmlTest {
@Test
public void testParseValidXmlStream() throws XmlPullParserException, IOException {
- Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
- Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();
+ Map<String, String> fileNameToContentIdMap = new HashMap<>();
+ Map<String, String> contentIdToFileContentMap = new HashMap<>();
LicenseHtmlGeneratorFromXml.parse(
new InputStreamReader(new ByteArrayInputStream(VALILD_XML_STRING.getBytes())),
@@ -107,8 +106,8 @@ public class LicenseHtmlGeneratorFromXmlTest {
@Test(expected = XmlPullParserException.class)
public void testParseInvalidXmlStream() throws XmlPullParserException, IOException {
- Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
- Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();
+ Map<String, String> fileNameToContentIdMap = new HashMap<>();
+ Map<String, String> contentIdToFileContentMap = new HashMap<>();
LicenseHtmlGeneratorFromXml.parse(
new InputStreamReader(new ByteArrayInputStream(INVALILD_XML_STRING.getBytes())),
@@ -117,8 +116,8 @@ public class LicenseHtmlGeneratorFromXmlTest {
@Test
public void testGenerateHtml() {
- Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
- Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();
+ Map<String, String> fileNameToContentIdMap = new HashMap<>();
+ Map<String, String> contentIdToFileContentMap = new HashMap<>();
fileNameToContentIdMap.put("/file0", "0");
fileNameToContentIdMap.put("/file1", "0");
@@ -132,8 +131,8 @@ public class LicenseHtmlGeneratorFromXmlTest {
@Test
public void testGenerateHtmlWithCustomHeading() {
- Map<String, String> fileNameToContentIdMap = new HashMap<String, String>();
- Map<String, String> contentIdToFileContentMap = new HashMap<String, String>();
+ Map<String, String> fileNameToContentIdMap = new HashMap<>();
+ Map<String, String> contentIdToFileContentMap = new HashMap<>();
fileNameToContentIdMap.put("/file0", "0");
fileNameToContentIdMap.put("/file1", "0");
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
index c90de5fe621e..e82bc0678108 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/license/LicenseHtmlLoaderCompatTest.java
@@ -20,14 +20,13 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@@ -37,7 +36,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = LicenseHtmlLoaderCompatTest.ShadowLicenseHtmlLoaderCompat.class)
public class LicenseHtmlLoaderCompatTest {
@@ -58,7 +57,7 @@ public class LicenseHtmlLoaderCompatTest {
@Test
public void testLoadInBackground() {
- ArrayList<File> xmlFiles = new ArrayList();
+ ArrayList<File> xmlFiles = new ArrayList<>();
xmlFiles.add(new File("test.xml"));
File cachedHtmlFile = new File("test.html");
@@ -69,7 +68,7 @@ public class LicenseHtmlLoaderCompatTest {
@Test
public void testLoadInBackgroundWithNoVaildXmlFiles() {
- ArrayList<File> xmlFiles = new ArrayList();
+ ArrayList<File> xmlFiles = new ArrayList<>();
File cachedHtmlFile = new File("test.html");
setupFakeData(xmlFiles, cachedHtmlFile, true, true);
@@ -79,7 +78,7 @@ public class LicenseHtmlLoaderCompatTest {
@Test
public void testLoadInBackgroundWithNonOutdatedCachedHtmlFile() {
- ArrayList<File> xmlFiles = new ArrayList();
+ ArrayList<File> xmlFiles = new ArrayList<>();
xmlFiles.add(new File("test.xml"));
File cachedHtmlFile = new File("test.html");
@@ -90,7 +89,7 @@ public class LicenseHtmlLoaderCompatTest {
@Test
public void testLoadInBackgroundWithGenerateHtmlFileFailed() {
- ArrayList<File> xmlFiles = new ArrayList();
+ ArrayList<File> xmlFiles = new ArrayList<>();
xmlFiles.add(new File("test.xml"));
File cachedHtmlFile = new File("test.html");
@@ -112,10 +111,10 @@ public class LicenseHtmlLoaderCompatTest {
@Implements(LicenseHtmlLoaderCompat.class)
public static class ShadowLicenseHtmlLoaderCompat {
- public static List<File> sValidXmlFiles;
- public static File sCachedHtmlFile;
- public static boolean sIsCachedHtmlFileOutdated;
- public static boolean sGenerateHtmlFileSucceeded;
+ private static List<File> sValidXmlFiles;
+ private static File sCachedHtmlFile;
+ private static boolean sIsCachedHtmlFileOutdated;
+ private static boolean sGenerateHtmlFileSucceeded;
@Resetter
public static void reset() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/InjectedSettingTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/InjectedSettingTest.java
index c29481f633a4..8c2e8992fd6a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/InjectedSettingTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/InjectedSettingTest.java
@@ -18,12 +18,11 @@ package com.android.settingslib.location;
import static com.google.common.truth.Truth.assertThat;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public final class InjectedSettingTest {
private static final String TEST_STRING = "test";
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 9c168f7b1a45..08d536720029 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -2,7 +2,7 @@ package com.android.settingslib.location;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.isA;
+import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
@@ -17,20 +17,19 @@ import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class RecentLocationAppsTest {
private static final int TEST_UID = 1234;
@@ -56,8 +55,6 @@ public class RecentLocationAppsTest {
private int mTestUserId;
private RecentLocationApps mRecentLocationApps;
-
-
@Before
public void setUp() throws NameNotFoundException {
MockitoAnnotations.initMocks(this);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
index 50044f2cc0ea..72ed5e123add 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
@@ -42,16 +42,15 @@ import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
import android.util.FeatureFlagUtils;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class DataUsageControllerTest {
private static final String SUB_ID = "Test Subscriber";
@@ -85,7 +84,6 @@ public class DataUsageControllerTest {
doReturn(null).when(mController).getSession();
assertThat(mController.getHistoricalUsageLevel(null /* template */)).isEqualTo(-1L);
-
}
@Test
@@ -95,7 +93,6 @@ public class DataUsageControllerTest {
assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard()))
.isEqualTo(0L);
-
}
@Test
@@ -113,7 +110,6 @@ public class DataUsageControllerTest {
assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard()))
.isEqualTo(receivedBytes + transmittedBytes);
-
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
index 0a036317910e..011f234ab4f1 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleChartDataLoaderTest.java
@@ -27,15 +27,14 @@ import android.net.NetworkPolicyManager;
import android.os.RemoteException;
import android.text.format.DateUtils;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class NetworkCycleChartDataLoaderTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
index 2314f272c8ea..d9159631e8a9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
@@ -19,7 +19,7 @@ package com.android.settingslib.net;
import static android.app.usage.NetworkStats.Bucket.STATE_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -33,15 +33,14 @@ import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.text.format.DateUtils;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class NetworkCycleDataForUidLoaderTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
index 9d60a97f8584..2d8ea125a97e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
@@ -16,8 +16,8 @@
package com.android.settingslib.net;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.nullable;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -37,20 +37,19 @@ import android.os.RemoteException;
import android.text.format.DateUtils;
import android.util.Range;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.util.ReflectionHelpers;
import java.time.ZonedDateTime;
import java.util.Iterator;
import java.util.List;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class NetworkCycleDataLoaderTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
index 89c319a7e483..59d56747ec5d 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -16,11 +16,10 @@
package com.android.settingslib.notification;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
-
+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.anyLong;
@@ -38,16 +37,15 @@ import android.net.Uri;
import android.service.notification.Condition;
import android.view.LayoutInflater;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class EnableZenModeDialogTest {
private EnableZenModeDialog mController;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
index 81476564f9b9..437c0d4f4469 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
@@ -25,27 +25,23 @@ import static org.mockito.Mockito.spy;
import android.content.ContentResolver;
import android.content.Context;
import android.provider.Settings;
-import android.service.notification.Condition;
import android.view.LayoutInflater;
import android.view.View;
import androidx.appcompat.app.AlertDialog;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class ZenDurationDialogTest {
private ZenDurationDialog mController;
private Context mContext;
private LayoutInflater mLayoutInflater;
- private Condition mCountdownCondition;
- private Condition mAlarmCondition;
private ContentResolver mContentResolver;
private AlertDialog.Builder mBuilder;
@@ -102,7 +98,6 @@ public class ZenDurationDialogTest {
ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX).rb.isChecked());
}
-
@Test
public void testChooseAlwaysPromptSetting() {
Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
index 449451a63e2d..ffaa7443eb46 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinCompatTest.java
@@ -31,7 +31,6 @@ import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
import androidx.loader.app.LoaderManager;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.After;
@@ -40,10 +39,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowSuggestionController.class)
public class SuggestionControllerMixinCompatTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
index aac582f9b3ac..4dc80f442649 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionControllerMixinTest.java
@@ -31,7 +31,6 @@ import android.content.Context;
import androidx.lifecycle.LifecycleOwner;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.After;
@@ -40,10 +39,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowSuggestionController.class)
public class SuggestionControllerMixinTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java
index f4afdb11ff95..3e91641a69ae 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/testutils/shadow/ShadowDefaultDialerManager.java
@@ -26,19 +26,19 @@ import org.robolectric.annotation.Resetter;
@Implements(DefaultDialerManager.class)
public class ShadowDefaultDialerManager {
- private static String sDefaultDailer;
+ private static String sDefaultDialer;
@Resetter
public void reset() {
- sDefaultDailer = null;
+ sDefaultDialer = null;
}
@Implementation
public static String getDefaultDialerApplication(Context context) {
- return sDefaultDailer;
+ return sDefaultDialer;
}
public static void setDefaultDialerApplication(String dialer) {
- sDefaultDailer = dialer;
+ sDefaultDialer = dialer;
}
} \ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
index 4705cd2b183b..9a169d2663de 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/UserManagerHelperRoboTest.java
@@ -27,7 +27,6 @@ import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.testutils.shadow.ShadowActivityManager;
import org.junit.After;
@@ -36,6 +35,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
@@ -45,7 +45,7 @@ import org.robolectric.annotation.Resetter;
import java.util.ArrayList;
import java.util.List;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
@Config(shadows = { ShadowActivityManager.class, UserManagerHelperRoboTest.ShadowUserHandle.class})
public class UserManagerHelperRoboTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/IconCacheTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/IconCacheTest.java
index 645dfa127626..026ad47f99a2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/IconCacheTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/IconCacheTest.java
@@ -30,14 +30,13 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class IconCacheTest {
private Icon mIcon;
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
index 6a9579b770ce..7ef31df6ab26 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/PowerUtilTest.java
@@ -22,31 +22,30 @@ import static org.mockito.Mockito.spy;
import android.content.Context;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.time.Duration;
import java.util.regex.Pattern;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class PowerUtilTest {
- public static final String TEST_BATTERY_LEVEL_10 = "10%";
- public static final long SEVENTEEN_MIN_MILLIS = Duration.ofMinutes(17).toMillis();
- public static final long FIVE_MINUTES_MILLIS = Duration.ofMinutes(5).toMillis();
- public static final long TEN_MINUTES_MILLIS = Duration.ofMinutes(10).toMillis();
- public static final long THREE_DAYS_MILLIS = Duration.ofDays(3).toMillis();
- public static final long THIRTY_HOURS_MILLIS = Duration.ofHours(30).toMillis();
- public static final String NORMAL_CASE_EXPECTED_PREFIX = "Should last until about";
- public static final String ENHANCED_SUFFIX = " based on your usage";
+ private static final String TEST_BATTERY_LEVEL_10 = "10%";
+ private static final long SEVENTEEN_MIN_MILLIS = Duration.ofMinutes(17).toMillis();
+ private static final long FIVE_MINUTES_MILLIS = Duration.ofMinutes(5).toMillis();
+ private static final long TEN_MINUTES_MILLIS = Duration.ofMinutes(10).toMillis();
+ private static final long THREE_DAYS_MILLIS = Duration.ofDays(3).toMillis();
+ private static final long THIRTY_HOURS_MILLIS = Duration.ofHours(30).toMillis();
+ private static final String NORMAL_CASE_EXPECTED_PREFIX = "Should last until about";
+ private static final String ENHANCED_SUFFIX = " based on your usage";
// matches a time (ex: '1:15 PM', '2 AM', '23:00')
- public static final String TIME_OF_DAY_REGEX = " (\\d)+:?(\\d)* ((AM)*)|((PM)*)";
+ private static final String TIME_OF_DAY_REGEX = " (\\d)+:?(\\d)* ((AM)*)|((PM)*)";
// matches a percentage with parenthesis (ex: '(10%)')
- public static final String PERCENTAGE_REGEX = " \\(\\d?\\d%\\)";
+ private static final String PERCENTAGE_REGEX = " \\(\\d?\\d%\\)";
private Context mContext;
@@ -108,7 +107,6 @@ public class PowerUtilTest {
+ "(" + PERCENTAGE_REGEX + "){0}")); // no percentage
}
-
@Test
public void testGetBatteryRemainingStringFormatted_lessThanSevenMinutes_usesCorrectString() {
String info = PowerUtil.getBatteryRemainingStringFormatted(mContext,
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
index e4bbbcb0b207..8fbbfbbd5047 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/StringUtilTest.java
@@ -25,14 +25,13 @@ import android.text.SpannableStringBuilder;
import android.text.format.DateUtils;
import android.text.style.TtsSpan;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class StringUtilTest {
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
index 1e066b1b0f74..26db124c0041 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
@@ -15,28 +15,22 @@
*/
package com.android.settingslib.utils;
-
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.shadows.ShadowLooper;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class ThreadUtilsTest {
@Test
public void testMainThread() throws InterruptedException {
assertThat(ThreadUtils.isMainThread()).isTrue();
- Thread background = new Thread(new Runnable() {
- public void run() {
- assertThat(ThreadUtils.isMainThread()).isFalse();
- }
- });
+ Thread background = new Thread(() -> assertThat(ThreadUtils.isMainThread()).isFalse());
background.start();
background.join();
}
@@ -44,13 +38,11 @@ public class ThreadUtilsTest {
@Test
public void testEnsureMainThread() throws InterruptedException {
ThreadUtils.ensureMainThread();
- Thread background = new Thread(new Runnable() {
- public void run() {
- try {
- ThreadUtils.ensureMainThread();
- fail("Should not pass ensureMainThread in a background thread");
- } catch (RuntimeException e) {
- }
+ Thread background = new Thread(() -> {
+ try {
+ ThreadUtils.ensureMainThread();
+ fail("Should not pass ensureMainThread in a background thread");
+ } catch (RuntimeException expected) {
}
});
background.start();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/ActionButtonsPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/ActionButtonsPreferenceTest.java
new file mode 100644
index 000000000000..88fef08bfcb7
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/ActionButtonsPreferenceTest.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.Button;
+
+import androidx.preference.PreferenceViewHolder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class ActionButtonsPreferenceTest {
+
+ private Context mContext;
+ private View mRootView;
+ private ActionButtonsPreference mPref;
+ private PreferenceViewHolder mHolder;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mRootView = View.inflate(mContext, R.layout.settings_action_buttons, null /* parent */);
+ mHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
+ mPref = new ActionButtonsPreference(mContext);
+ }
+
+ @Test
+ public void onBindViewHolder_setTitle_shouldShowButtonByDefault() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton2Text(R.string.install_other_apps);
+ mPref.setButton3Text(R.string.install_other_apps);
+ mPref.setButton4Text(R.string.install_other_apps);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_setIcon_shouldShowButtonByDefault() {
+ mPref.setButton1Icon(R.drawable.ic_plus);
+ mPref.setButton2Icon(R.drawable.ic_plus);
+ mPref.setButton3Icon(R.drawable.ic_plus);
+ mPref.setButton4Icon(R.drawable.ic_plus);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_notSetTitleOrIcon_shouldNotShowButtonByDefault() {
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_setVisibleIsGoneAndSetTitle_shouldNotShowButton() {
+ mPref.setButton1Text(R.string.install_other_apps).setButton1Visible(false);
+ mPref.setButton2Text(R.string.install_other_apps).setButton2Visible(false);
+ mPref.setButton3Text(R.string.install_other_apps).setButton3Visible(false);
+ mPref.setButton4Text(R.string.install_other_apps).setButton4Visible(false);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_setVisibleIsGoneAndSetIcon_shouldNotShowButton() {
+ mPref.setButton1Icon(R.drawable.ic_plus).setButton1Visible(false);
+ mPref.setButton2Icon(R.drawable.ic_plus).setButton2Visible(false);
+ mPref.setButton3Icon(R.drawable.ic_plus).setButton3Visible(false);
+ mPref.setButton4Icon(R.drawable.ic_plus).setButton4Visible(false);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+ .isEqualTo(View.GONE);
+ }
+
+ @Test
+ public void onBindViewHolder_setVisibility_shouldUpdateButtonVisibility() {
+ mPref.setButton1Text(R.string.install_other_apps).setButton1Visible(false);
+ mPref.setButton2Text(R.string.install_other_apps).setButton2Visible(false);
+ mPref.setButton3Text(R.string.install_other_apps).setButton3Visible(false);
+ mPref.setButton4Text(R.string.install_other_apps).setButton4Visible(false);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+ .isEqualTo(View.GONE);
+ assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+ .isEqualTo(View.GONE);
+
+ mPref.setButton1Visible(true);
+ mPref.setButton2Visible(true);
+ mPref.setButton3Visible(true);
+ mPref.setButton4Visible(true);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.button1).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.button2).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.button3).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ assertThat(mRootView.findViewById(R.id.button4).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onBindViewHolder_setEnabled_shouldEnableButton() {
+ mPref.setButton1Enabled(true);
+ mPref.setButton2Enabled(false);
+ mPref.setButton3Enabled(true);
+ mPref.setButton4Enabled(false);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(mRootView.findViewById(R.id.button1).isEnabled()).isTrue();
+ assertThat(mRootView.findViewById(R.id.button2).isEnabled()).isFalse();
+ assertThat(mRootView.findViewById(R.id.button3).isEnabled()).isTrue();
+ assertThat(mRootView.findViewById(R.id.button4).isEnabled()).isFalse();
+ }
+
+ @Test
+ public void onBindViewHolder_setText_shouldShowSameText() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton2Text(R.string.install_other_apps);
+ mPref.setButton3Text(R.string.install_other_apps);
+ mPref.setButton4Text(R.string.install_other_apps);
+
+ mPref.onBindViewHolder(mHolder);
+
+ assertThat(((Button) mRootView.findViewById(R.id.button1)).getText())
+ .isEqualTo(mContext.getText(R.string.install_other_apps));
+ assertThat(((Button) mRootView.findViewById(R.id.button2)).getText())
+ .isEqualTo(mContext.getText(R.string.install_other_apps));
+ assertThat(((Button) mRootView.findViewById(R.id.button3)).getText())
+ .isEqualTo(mContext.getText(R.string.install_other_apps));
+ assertThat(((Button) mRootView.findViewById(R.id.button4)).getText())
+ .isEqualTo(mContext.getText(R.string.install_other_apps));
+ }
+
+ @Test
+ public void onBindViewHolder_setButtonIcon_iconMustDisplayAboveText() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton1Icon(R.drawable.ic_plus);
+
+ mPref.onBindViewHolder(mHolder);
+ final Drawable[] drawablesAroundText =
+ ((Button) mRootView.findViewById(R.id.button1))
+ .getCompoundDrawables();
+
+ assertThat(drawablesAroundText[1 /* top */]).isNotNull();
+ }
+
+ @Test
+ public void setButtonIcon_iconResourceIdIsZero_shouldNotDisplayIcon() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton1Icon(0);
+
+ mPref.onBindViewHolder(mHolder);
+ final Drawable[] drawablesAroundText =
+ ((Button) mRootView.findViewById(R.id.button1))
+ .getCompoundDrawables();
+
+ assertThat(drawablesAroundText[1 /* top */]).isNull();
+ }
+
+ @Test
+ public void setButtonIcon_iconResourceIdNotExisting_shouldNotDisplayIconAndCrash() {
+ mPref.setButton1Text(R.string.install_other_apps);
+ mPref.setButton1Icon(999999999 /* not existing id */);
+ // Should not crash here
+ mPref.onBindViewHolder(mHolder);
+ final Drawable[] drawablesAroundText =
+ ((Button) mRootView.findViewById(R.id.button1))
+ .getCompoundDrawables();
+
+ assertThat(drawablesAroundText[1 /* top */]).isNull();
+ }
+
+ public static ActionButtonsPreference createMock() {
+ final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);
+ when(pref.setButton1Text(anyInt())).thenReturn(pref);
+ when(pref.setButton1Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton1Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton1Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton1OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ when(pref.setButton2Text(anyInt())).thenReturn(pref);
+ when(pref.setButton2Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton2Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ when(pref.setButton3Text(anyInt())).thenReturn(pref);
+ when(pref.setButton3Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton3Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+
+ when(pref.setButton4Text(anyInt())).thenReturn(pref);
+ when(pref.setButton4Icon(anyInt())).thenReturn(pref);
+ when(pref.setButton4Enabled(anyBoolean())).thenReturn(pref);
+ when(pref.setButton4Visible(anyBoolean())).thenReturn(pref);
+ when(pref.setButton4OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
+ return pref;
+ }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
index a00f12d9a6d9..d41d5112e6b2 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AnimatedImageViewTest.java
@@ -22,14 +22,13 @@ import android.app.Activity;
import android.graphics.drawable.AnimatedRotateDrawable;
import android.view.View;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class AnimatedImageViewTest {
private AnimatedImageView mAnimatedImageView;
@@ -47,5 +46,4 @@ public class AnimatedImageViewTest {
AnimatedRotateDrawable drawable = (AnimatedRotateDrawable) mAnimatedImageView.getDrawable();
assertThat(drawable.isRunning()).isTrue();
}
-
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
index e030005e2d09..601da0512c7c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
@@ -18,7 +18,7 @@ package com.android.settingslib.widget;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -29,7 +29,6 @@ import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -37,9 +36,10 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class FooterPreferenceMixinCompatTest {
@Mock
@@ -97,5 +97,4 @@ public class FooterPreferenceMixinCompatTest {
verify(mScreen).removePreference(any(FooterPreference.class));
verify(mScreen, times(2)).addPreference(any(FooterPreference.class));
}
-
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
index 8817ff7f65b3..7ae5d2d97cb8 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
@@ -18,7 +18,7 @@ package com.android.settingslib.widget;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -29,7 +29,6 @@ import androidx.preference.PreferenceFragment;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -37,10 +36,10 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowApplication;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class FooterPreferenceMixinTest {
@Mock
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
index e0eceb418f27..0d2399e3dcab 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceTest.java
@@ -26,14 +26,14 @@ import android.widget.TextView;
import androidx.preference.PreferenceViewHolder;
import com.android.settingslib.R;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class FooterPreferenceTest {
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/LayoutPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/LayoutPreferenceTest.java
index 427a611d61da..99261a38f73b 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/LayoutPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/LayoutPreferenceTest.java
@@ -27,14 +27,13 @@ import android.view.LayoutInflater;
import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceViewHolder;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class LayoutPreferenceTest {
private LayoutPreference mPreference;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
index 10c9dfbe6067..da97cc8b74dd 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/apppreference/AppPreferenceTest.java
@@ -23,14 +23,13 @@ import android.view.View;
import androidx.preference.PreferenceViewHolder;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class AppPreferenceTest {
private Context mContext;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
index 86443bde4667..c5cbea78120f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
@@ -25,16 +25,15 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class AccessPointPreferenceTest {
private Context mContext = RuntimeEnvironment.application;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
index f0e8c66e8544..b059df1fd8cb 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/TimestampedScoredNetworkTest.java
@@ -22,15 +22,14 @@ import android.net.ScoredNetwork;
import android.net.WifiKey;
import android.os.Parcel;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import java.util.Date;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class TimestampedScoredNetworkTest {
private TimestampedScoredNetwork impl;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
index 07c50fde00fa..89960cba2bf5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiUtilsTest.java
@@ -37,19 +37,19 @@ import android.text.format.DateUtils;
import android.util.ArraySet;
import com.android.settingslib.R;
-import com.android.settingslib.SettingsLibRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.Set;
-@RunWith(SettingsLibRobolectricTestRunner.class)
+@RunWith(RobolectricTestRunner.class)
public class WifiUtilsTest {
private static final String TEST_SSID = "\"test_ssid\"";
private static final String TEST_BSSID = "00:00:00:00:00:00";
@@ -79,7 +79,7 @@ public class WifiUtilsTest {
Bundle bundle = new Bundle();
ArrayList<ScanResult> scanResults = buildScanResultCache();
bundle.putParcelableArray(AccessPoint.KEY_SCANRESULTS,
- scanResults.toArray(new Parcelable[scanResults.size()]));
+ scanResults.toArray(new Parcelable[0]));
AccessPoint ap = new AccessPoint(mContext, bundle);
when(mockWifiNetworkScoreCache.getScoredNetwork(any(ScanResult.class)))
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index b2c12b277dc0..56b768feee23 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1914,6 +1914,15 @@ class SettingsProtoDumpUtil {
SecureSettingsProto.Location.CHANGER);
p.end(locationToken);
+ final long locationAccessCheckToken = p.start(SecureSettingsProto.LOCATION_ACCESS_CHECK);
+ dumpSetting(s, p,
+ Settings.Secure.LOCATION_ACCESS_CHECK_INTERVAL_MILLIS,
+ SecureSettingsProto.LocationAccessCheck.INTERVAL_MILLIS);
+ dumpSetting(s, p,
+ Settings.Secure.LOCATION_ACCESS_CHECK_DELAY_MILLIS,
+ SecureSettingsProto.LocationAccessCheck.DELAY_MILLIS);
+ p.end(locationAccessCheckToken);
+
final long lockScreenToken = p.start(SecureSettingsProto.LOCK_SCREEN);
// Settings.Secure.LOCK_BIOMETRIC_WEAK_FLAGS intentionally excluded since it's deprecated.
// Settings.Secure.LOCK_PATTERN_ENABLED intentionally excluded since it's deprecated.
diff --git a/packages/SystemUI/res/drawable/ic_notification_block.xml b/packages/SystemUI/res/drawable/ic_notification_block.xml
index 572e97b6badc..276907401d5a 100644
--- a/packages/SystemUI/res/drawable/ic_notification_block.xml
+++ b/packages/SystemUI/res/drawable/ic_notification_block.xml
@@ -20,6 +20,6 @@ Copyright (C) 2016 The Android Open Source Project
android:viewportHeight="24.0">
<path
- android:fillColor="#FFFFFFFF"
+ android:fillColor="#FF000000"
android:pathData="M12.0,2.0C6.48,2.0 2.0,6.48 2.0,12.0s4.48,10.0 10.0,10.0 10.0,-4.48 10.0,-10.0S17.52,2.0 12.0,2.0zM4.0,12.0c0.0,-4.42 3.58,-8.0 8.0,-8.0 1.85,0.0 3.5,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4.0,13.85 4.0,12.0zm8.0,8.0c-1.85,0.0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20.0,10.15 20.0,12.0c0.0,4.42 -3.58,8.0 -8.0,8.0z"/>
</vector>
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index 5ca34b033f0d..1e8cd5a7e13b 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -160,6 +160,15 @@
android:maxLines="2"
android:text="@string/biometric_dialog_confirm"
android:visibility="gone"/>
+ <!-- Try Again Button -->
+ <Button android:id="@+id/button_try_again"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ style="@*android:style/Widget.DeviceDefault.Button.Colored"
+ android:gravity="center"
+ android:maxLines="2"
+ android:text="@string/biometric_dialog_try_again"
+ android:visibility="gone"/>
<Space android:id="@+id/rightSpacer"
android:layout_width="12dip"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index eb3f70adc48b..d502baa956b0 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -144,6 +144,7 @@
<!-- Settings and Done buttons -->
<LinearLayout
+ android:id="@+id/block_or_minimize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_guts_button_spacing"
@@ -178,13 +179,6 @@
android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
style="@style/TextAppearance.NotificationInfo.Button" />
<TextView
- android:id="@+id/toggle_silent"
- android:text="@string/inline_silent_button_silent"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
- style="@style/TextAppearance.NotificationInfo.Button" />
- <TextView
android:id="@+id/keep"
android:minWidth="48dp"
android:text="@string/inline_keep_button"
@@ -193,6 +187,44 @@
android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
style="@style/TextAppearance.NotificationInfo.Button"/>
</LinearLayout>
+ <LinearLayout
+ android:id="@+id/interruptiveness_settings"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/notification_guts_button_spacing"
+ android:layout_marginStart="@dimen/notification_guts_button_side_margin"
+ android:layout_marginEnd="@dimen/notification_guts_button_side_margin"
+ android:gravity="center"
+ android:orientation="horizontal"
+ android:visibility="gone">
+ <TextView
+ android:id="@+id/int_block"
+ android:text="@string/inline_block_button"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:drawableTop="@drawable/ic_notification_block"
+ android:drawableTint="?android:attr/colorAccent"
+ android:layout_weight="1"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ <TextView
+ android:id="@+id/int_silent"
+ android:text="@string/inline_minimize_button"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:drawableTop="@drawable/ic_notifications_silence"
+ android:drawableTint="?android:attr/colorAccent"
+ android:layout_weight="1"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ <TextView
+ android:id="@+id/int_alert"
+ android:text="@string/inline_keep_button"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:drawableTop="@drawable/ic_notifications_alert"
+ android:drawableTint="?android:attr/colorAccent"
+ android:layout_weight="1"
+ style="@style/TextAppearance.NotificationInfo.Button"/>
+ </LinearLayout>
</LinearLayout>
<com.android.systemui.statusbar.notification.row.NotificationUndoLayout
android:id="@+id/confirmation"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c5654f01e5fc..9917257bba8a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -272,6 +272,8 @@
<string name="accessibility_biometric_dialog_help_area">Help message area</string>
<!-- Message shown when a biometric is authenticated, asking the user to confirm authentication [CHAR LIMIT=30] -->
<string name="biometric_dialog_confirm">Confirm</string>
+ <!-- Button name on BiometricPrompt shown when a biometric is detected but not authenticated. Tapping the button resumes authentication [CHAR_LIMIT=30] -->
+ <string name="biometric_dialog_try_again">Try again</string>
<!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
<string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
@@ -700,6 +702,8 @@
<string name="quick_settings_bluetooth_secondary_label_headset">Headset</string>
<!-- QuickSettings: Bluetooth secondary label for an input/IO device being connected [CHAR LIMIT=20]-->
<string name="quick_settings_bluetooth_secondary_label_input">Input</string>
+ <!-- QuickSettings: Bluetooth secondary label for a Hearing Aids device being connected [CHAR LIMIT=20]-->
+ <string name="quick_settings_bluetooth_secondary_label_hearing_aids">Hearing Aids</string>
<!-- QuickSettings: Bluetooth secondary label shown when bluetooth is being enabled [CHAR LIMIT=NONE] -->
<string name="quick_settings_bluetooth_secondary_label_transient">Turning on&#8230;</string>
<!-- QuickSettings: Brightness [CHAR LIMIT=NONE] -->
@@ -1556,17 +1560,26 @@
<!-- Notification inline controls: block notifications button -->
<string name="inline_stop_button">Stop notifications</string>
+ <!-- Notification inline controls: button to block notifications from this channel [CHAR_LIMIT=35] -->
+ <string name="inline_block_button">Block</string>
+
<!-- Notification inline controls: keep getting notifications button -->
<string name="inline_keep_button">Keep showing</string>
<!-- Notification inline controls: minimize notifications button -->
<string name="inline_minimize_button">Minimize</string>
- <!-- Notification inline controls: show notifications silently button [CHAR_LIMIT=25] -->
+ <!-- Notification inline controls: button to show notifications silently, without alerting the user [CHAR_LIMIT=35] -->
<string name="inline_silent_button_silent">Show silently</string>
- <!-- Notification inline controls: show and alert button [CHAR_LIMIT=25] -->
- <string name="inline_silent_button_alert">Show and alert</string>
+ <!-- Notification inline controls: button to continue showing notifications silently [CHAR_LIMIT=35] -->
+ <string name="inline_silent_button_stay_silent">Stay silent</string>
+
+ <!-- Notification inline controls: button to make notifications alert the user [CHAR_LIMIT=35] -->
+ <string name="inline_silent_button_alert">Alert me</string>
+
+ <!-- Notification inline controls: button to continue alerting the user when notifications arrive [CHAR_LIMIT=35] -->
+ <string name="inline_silent_button_keep_alerting">Keep alerting</string>
<!-- Notification Inline controls: continue receiving notifications prompt, app level -->
<string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
@@ -2255,6 +2268,7 @@
<!-- Text on chip for multiple apps using a single app op [CHAR LIMIT=10] -->
<plurals name="ongoing_privacy_chip_multiple_apps">
+ <item quantity="one"><xliff:g id="num_apps" example="1">%d</xliff:g> app</item>
<item quantity="few"><xliff:g id="num_apps" example="3">%d</xliff:g> apps</item>
<item quantity="other"><xliff:g id="num_apps" example="3">%d</xliff:g> apps</item>
</plurals>
@@ -2267,6 +2281,7 @@
<!-- Content description for ongoing privacy chip. Use with multiple apps using same app op[CHAR LIMIT=NONE]-->
<plurals name="ongoing_privacy_chip_content_multiple_apps_single_op">
+ <item quantity="one"><xliff:g id="num_apps" example="1">%1$d</xliff:g> application is using your <xliff:g id="type" example="camera">%2$s</xliff:g>.</item>
<item quantity="few"><xliff:g id="num_apps" example="3">%1$d</xliff:g> applications are using your <xliff:g id="type" example="camera">%2$s</xliff:g>.</item>
<item quantity="other"><xliff:g id="num_apps" example="3">%1$d</xliff:g> applications are using your <xliff:g id="type" example="camera">%2$s</xliff:g>.</item>
</plurals>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index ece2bb9a9507..f3bdbae97e42 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -71,4 +71,9 @@ interface ISystemUiProxy {
*/
void onStatusBarMotionEvent(in MotionEvent event) = 9;
+ /**
+ * Get the corner radius of windows in pixels.
+ */
+ float getWindowCornerRadius() = 10;
+
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java
index 65c52200a7d8..a9cf857c3e50 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java
@@ -83,6 +83,7 @@ public class SyncRtSurfaceTransactionApplier {
t.setWindowCrop(params.surface, params.windowCrop);
t.setAlpha(params.surface, params.alpha);
t.setLayer(params.surface, params.layer);
+ t.setCornerRadius(params.surface, params.cornerRadius);
t.show(params.surface);
}
@@ -98,12 +99,13 @@ public class SyncRtSurfaceTransactionApplier {
* @param windowCrop Crop to apply.
*/
public SurfaceParams(SurfaceControlCompat surface, float alpha, Matrix matrix,
- Rect windowCrop, int layer) {
+ Rect windowCrop, int layer, float cornerRadius) {
this.surface = surface.mSurfaceControl;
this.alpha = alpha;
this.matrix = new Matrix(matrix);
this.windowCrop = new Rect(windowCrop);
this.layer = layer;
+ this.cornerRadius = cornerRadius;
}
final SurfaceControl surface;
@@ -111,5 +113,6 @@ public class SyncRtSurfaceTransactionApplier {
final Matrix matrix;
final Rect windowCrop;
final int layer;
+ final float cornerRadius;
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index ff9e84ca29c1..8a251ae51f38 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -18,6 +18,7 @@ package com.android.systemui.shared.system;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
@@ -61,7 +62,7 @@ public class WindowManagerWrapper {
public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
public static final int TRANSIT_KEYGUARD_UNOCCLUDE = WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
- public static final int NAV_BAR_POS_INVALID = -1;
+ public static final int NAV_BAR_POS_INVALID = NAV_BAR_INVALID;
public static final int NAV_BAR_POS_LEFT = NAV_BAR_LEFT;
public static final int NAV_BAR_POS_RIGHT = NAV_BAR_RIGHT;
public static final int NAV_BAR_POS_BOTTOM = NAV_BAR_BOTTOM;
@@ -178,10 +179,9 @@ public class WindowManagerWrapper {
* @see #NAV_BAR_POS_BOTTOM
* @see #NAV_BAR_POS_INVALID
*/
- public int getNavBarPosition() {
+ public int getNavBarPosition(int displayId) {
try {
- // TODO: Use WindowManagerService.getNavBarPosition(int displayId)
- return WindowManagerGlobal.getWindowManagerService().getNavBarPosition();
+ return WindowManagerGlobal.getWindowManagerService().getNavBarPosition(displayId);
} catch (RemoteException e) {
Log.w(TAG, "Failed to get nav bar position");
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
index c0047c015813..a90a7d231dc1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogImpl.java
@@ -21,7 +21,7 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricPrompt;
-import android.hardware.biometrics.IBiometricPromptReceiver;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -52,15 +52,20 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
private static final int MSG_BUTTON_NEGATIVE = 6;
private static final int MSG_USER_CANCELED = 7;
private static final int MSG_BUTTON_POSITIVE = 8;
+ private static final int MSG_BIOMETRIC_SHOW_TRY_AGAIN = 9;
+ private static final int MSG_TRY_AGAIN_PRESSED = 10;
private Map<Integer, BiometricDialogView> mDialogs; // BiometricAuthenticator type, view
private SomeArgs mCurrentDialogArgs;
private BiometricDialogView mCurrentDialog;
private WindowManager mWindowManager;
- private IBiometricPromptReceiver mReceiver;
+ private IBiometricServiceReceiverInternal mReceiver;
private boolean mDialogShowing;
private Callback mCallback = new Callback();
+ private boolean mTryAgainShowing; // No good place to save state before config change :/
+ private boolean mConfirmShowing; // No good place to save state before config change :/
+
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -89,6 +94,15 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
case MSG_BUTTON_POSITIVE:
handleButtonPositive();
break;
+ case MSG_BIOMETRIC_SHOW_TRY_AGAIN:
+ handleShowTryAgain();
+ break;
+ case MSG_TRY_AGAIN_PRESSED:
+ handleTryAgainPressed();
+ break;
+ default:
+ Log.w(TAG, "Unknown message: " + msg.what);
+ break;
}
}
};
@@ -96,7 +110,7 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
private class Callback implements DialogViewCallback {
@Override
public void onUserCanceled() {
- mHandler.obtainMessage(BiometricDialogImpl.MSG_USER_CANCELED).sendToTarget();
+ mHandler.obtainMessage(MSG_USER_CANCELED).sendToTarget();
}
@Override
@@ -107,12 +121,17 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
@Override
public void onNegativePressed() {
- mHandler.obtainMessage(BiometricDialogImpl.MSG_BUTTON_NEGATIVE).sendToTarget();
+ mHandler.obtainMessage(MSG_BUTTON_NEGATIVE).sendToTarget();
}
@Override
public void onPositivePressed() {
- mHandler.obtainMessage(BiometricDialogImpl.MSG_BUTTON_POSITIVE).sendToTarget();
+ mHandler.obtainMessage(MSG_BUTTON_POSITIVE).sendToTarget();
+ }
+
+ @Override
+ public void onTryAgainPressed() {
+ mHandler.obtainMessage(MSG_TRY_AGAIN_PRESSED).sendToTarget();
}
}
@@ -139,13 +158,14 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
}
@Override
- public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
- boolean requireConfirmation, int userId) {
+ public void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
+ int type, boolean requireConfirmation, int userId) {
if (DEBUG) Log.d(TAG, "showBiometricDialog, type: " + type);
// Remove these messages as they are part of the previous client
mHandler.removeMessages(MSG_BIOMETRIC_ERROR);
mHandler.removeMessages(MSG_BIOMETRIC_HELP);
mHandler.removeMessages(MSG_BIOMETRIC_AUTHENTICATED);
+ mHandler.removeMessages(MSG_HIDE_DIALOG);
SomeArgs args = SomeArgs.obtain();
args.arg1 = bundle;
args.arg2 = receiver;
@@ -179,6 +199,12 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
mHandler.obtainMessage(MSG_HIDE_DIALOG, false /* userCanceled */).sendToTarget();
}
+ @Override
+ public void showBiometricTryAgain() {
+ if (DEBUG) Log.d(TAG, "showBiometricTryAgain");
+ mHandler.obtainMessage(MSG_BIOMETRIC_SHOW_TRY_AGAIN).sendToTarget();
+ }
+
private void handleShowDialog(SomeArgs args, boolean skipAnimation) {
mCurrentDialogArgs = args;
final int type = args.argi1;
@@ -193,11 +219,13 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
Log.w(TAG, "Dialog already showing");
return;
}
- mReceiver = (IBiometricPromptReceiver) args.arg2;
+ mReceiver = (IBiometricServiceReceiverInternal) args.arg2;
mCurrentDialog.setBundle((Bundle)args.arg1);
mCurrentDialog.setRequireConfirmation((boolean) args.arg3);
mCurrentDialog.setUserId(args.argi2);
mCurrentDialog.setSkipIntro(skipAnimation);
+ mCurrentDialog.setPendingTryAgain(mTryAgainShowing);
+ mCurrentDialog.setPendingConfirm(mConfirmShowing);
mWindowManager.addView(mCurrentDialog, mCurrentDialog.getLayoutParams());
mDialogShowing = true;
}
@@ -209,7 +237,8 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
mContext.getResources()
.getText(mCurrentDialog.getAuthenticatedAccessibilityResourceId()));
if (mCurrentDialog.requiresConfirmation()) {
- mCurrentDialog.showConfirmationButton();
+ mConfirmShowing = true;
+ mCurrentDialog.showConfirmationButton(true /* show */);
} else {
handleHideDialog(false /* userCanceled */);
}
@@ -226,6 +255,7 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
if (DEBUG) Log.d(TAG, "Dialog already dismissed");
return;
}
+ mTryAgainShowing = false;
mCurrentDialog.showErrorMessage(error);
}
@@ -246,6 +276,8 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
}
mReceiver = null;
mDialogShowing = false;
+ mConfirmShowing = false;
+ mTryAgainShowing = false;
mCurrentDialog.startDismiss();
}
@@ -259,6 +291,7 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
} catch (RemoteException e) {
Log.e(TAG, "Remote exception when handling negative button", e);
}
+ mTryAgainShowing = false;
handleHideDialog(false /* userCanceled */);
}
@@ -272,13 +305,31 @@ public class BiometricDialogImpl extends SystemUI implements CommandQueue.Callba
} catch (RemoteException e) {
Log.e(TAG, "Remote exception when handling positive button", e);
}
+ mConfirmShowing = false;
handleHideDialog(false /* userCanceled */);
}
private void handleUserCanceled() {
+ mTryAgainShowing = false;
+ mConfirmShowing = false;
handleHideDialog(true /* userCanceled */);
}
+ private void handleShowTryAgain() {
+ mCurrentDialog.showTryAgainButton(true /* show */);
+ mTryAgainShowing = true;
+ }
+
+ private void handleTryAgainPressed() {
+ try {
+ mCurrentDialog.clearTemporaryMessage();
+ mTryAgainShowing = false;
+ mReceiver.onTryAgainPressed();
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException when handling try again", e);
+ }
+ }
+
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index 38427adfd42a..e085f2368214 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -87,6 +87,9 @@ public abstract class BiometricDialogView extends LinearLayout {
protected boolean mRequireConfirmation;
private int mUserId; // used to determine if we should show work background
+ private boolean mPendingShowTryAgain;
+ private boolean mPendingShowConfirm;
+
protected abstract void updateIcon(int lastState, int newState);
protected abstract int getHintStringResourceId();
protected abstract int getAuthenticatedAccessibilityResourceId();
@@ -178,6 +181,7 @@ public abstract class BiometricDialogView extends LinearLayout {
final Button negative = mLayout.findViewById(R.id.button2);
final Button positive = mLayout.findViewById(R.id.button1);
final ImageView icon = mLayout.findViewById(R.id.biometric_icon);
+ final Button tryAgain = mLayout.findViewById(R.id.button_try_again);
icon.setContentDescription(getResources().getString(getIconDescriptionResourceId()));
@@ -193,6 +197,11 @@ public abstract class BiometricDialogView extends LinearLayout {
mCallback.onPositivePressed();
});
+ tryAgain.setOnClickListener((View v) -> {
+ showTryAgainButton(false /* show */);
+ mCallback.onTryAgainPressed();
+ });
+
mLayout.setFocusableInTouchMode(true);
mLayout.requestFocus();
}
@@ -207,7 +216,6 @@ public abstract class BiometricDialogView extends LinearLayout {
final TextView subtitle = mLayout.findViewById(R.id.subtitle);
final TextView description = mLayout.findViewById(R.id.description);
final Button negative = mLayout.findViewById(R.id.button2);
- final Button positive = mLayout.findViewById(R.id.button1);
final ImageView backgroundView = mLayout.findViewById(R.id.background);
if (mUserManager.isManagedProfile(mUserId)) {
@@ -233,8 +241,6 @@ public abstract class BiometricDialogView extends LinearLayout {
title.setText(titleText);
title.setSelected(true);
- positive.setVisibility(View.INVISIBLE);
-
final CharSequence subtitleText = mBundle.getCharSequence(BiometricPrompt.KEY_SUBTITLE);
if (TextUtils.isEmpty(subtitleText)) {
subtitle.setVisibility(View.GONE);
@@ -243,7 +249,8 @@ public abstract class BiometricDialogView extends LinearLayout {
subtitle.setText(subtitleText);
}
- final CharSequence descriptionText = mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION);
+ final CharSequence descriptionText =
+ mBundle.getCharSequence(BiometricPrompt.KEY_DESCRIPTION);
if (TextUtils.isEmpty(descriptionText)) {
description.setVisibility(View.GONE);
} else {
@@ -253,6 +260,9 @@ public abstract class BiometricDialogView extends LinearLayout {
negative.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
+ showTryAgainButton(mPendingShowTryAgain);
+ showConfirmationButton(mPendingShowConfirm);
+
if (mWasForceRemoved || mSkipIntro) {
// Show the dialog immediately
mLayout.animate().cancel();
@@ -281,11 +291,17 @@ public abstract class BiometricDialogView extends LinearLayout {
public void startDismiss() {
mAnimatingAway = true;
+ // This is where final cleanup should occur.
final Runnable endActionRunnable = new Runnable() {
@Override
public void run() {
mWindowManager.removeView(BiometricDialogView.this);
mAnimatingAway = false;
+ // Set the icons / text back to normal state
+ handleClearMessage();
+ showTryAgainButton(false /* show */);
+ mPendingShowTryAgain = false;
+ mPendingShowConfirm = false;
}
};
@@ -345,9 +361,13 @@ public abstract class BiometricDialogView extends LinearLayout {
return mRequireConfirmation;
}
- public void showConfirmationButton() {
+ public void showConfirmationButton(boolean show) {
final Button positive = mLayout.findViewById(R.id.button1);
- positive.setVisibility(View.VISIBLE);
+ if (show) {
+ positive.setVisibility(View.VISIBLE);
+ } else {
+ positive.setVisibility(View.GONE);
+ }
}
public void setUserId(int userId) {
@@ -376,12 +396,18 @@ public abstract class BiometricDialogView extends LinearLayout {
BiometricPrompt.HIDE_DIALOG_DELAY);
}
+ public void clearTemporaryMessage() {
+ mHandler.removeMessages(MSG_CLEAR_MESSAGE);
+ mHandler.obtainMessage(MSG_CLEAR_MESSAGE).sendToTarget();
+ }
+
public void showHelpMessage(String message) {
showTemporaryMessage(message);
}
public void showErrorMessage(String error) {
showTemporaryMessage(error);
+ showTryAgainButton(false /* show */);
mCallback.onErrorShown();
}
@@ -390,6 +416,25 @@ public abstract class BiometricDialogView extends LinearLayout {
mLastState = newState;
}
+ public void showTryAgainButton(boolean show) {
+ final Button tryAgain = mLayout.findViewById(R.id.button_try_again);
+ if (show) {
+ tryAgain.setVisibility(View.VISIBLE);
+ } else {
+ tryAgain.setVisibility(View.GONE);
+ }
+ }
+
+ // Set the state before the window is attached, so we know if the dialog should be started
+ // with or without the button. This is because there's no good onPause signal
+ public void setPendingTryAgain(boolean show) {
+ mPendingShowTryAgain = show;
+ }
+
+ public void setPendingConfirm(boolean show) {
+ mPendingShowConfirm = show;
+ }
+
public WindowManager.LayoutParams getLayoutParams() {
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java b/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java
index f388d9c67718..24fd22e2ee80 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/DialogViewCallback.java
@@ -43,4 +43,9 @@ public interface DialogViewCallback {
* should be dismissed.
*/
void onPositivePressed();
+
+ /**
+ * Invoked when the "try again" button is pressed.
+ */
+ void onTryAgainPressed();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
index 9a5a5b855999..be504ef5eb9c 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
@@ -23,6 +23,7 @@ import android.os.ServiceManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
import java.io.PrintWriter;
@@ -80,11 +81,12 @@ public class DozeWallpaperState implements DozeMachine.Part {
if (isAmbientMode != mIsAmbientMode) {
mIsAmbientMode = isAmbientMode;
try {
+ long duration = animated ? StackStateAnimator.ANIMATION_DURATION_WAKEUP : 0L;
if (DEBUG) {
Log.i(TAG, "AOD wallpaper state changed to: " + mIsAmbientMode
- + ", animated: " + animated);
+ + ", animationDuration: " + duration);
}
- mWallpaperManagerService.setInAmbientMode(mIsAmbientMode, animated);
+ mWallpaperManagerService.setInAmbientMode(mIsAmbientMode, duration);
} catch (RemoteException e) {
// Cannot notify wallpaper manager service, but it's fine, let's just skip it.
Log.w(TAG, "Cannot notify state to WallpaperManagerService: " + mIsAmbientMode);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 8b434a546504..496aa0e572ae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -323,7 +323,9 @@ public class QSDetail extends LinearLayout {
post(new Runnable() {
@Override
public void run() {
- handleShowingDetail(detail, x, y, false /* toggleQs */);
+ if (isAttachedToWindow()) {
+ handleShowingDetail(detail, x, y, false /* toggleQs */);
+ }
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 591e9e015897..9d2be39b28fc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -26,6 +26,7 @@ import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
+import android.provider.Settings;
import android.service.quicksettings.TileService;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -69,7 +70,8 @@ public class TileQueryHelper {
mSpecs.clear();
mFinished = false;
// Enqueue jobs to fetch every system tile and then ever package tile.
- addStockTiles(host);
+ addCurrentAndStockTiles(host);
+
addPackageTiles(host);
}
@@ -77,16 +79,28 @@ public class TileQueryHelper {
return mFinished;
}
- private void addStockTiles(QSTileHost host) {
- String possible = mContext.getString(R.string.quick_settings_tiles_stock);
+ private void addCurrentAndStockTiles(QSTileHost host) {
+ String stock = mContext.getString(R.string.quick_settings_tiles_stock);
+ String current = Settings.Secure.getString(mContext.getContentResolver(),
+ Settings.Secure.QS_TILES);
final ArrayList<String> possibleTiles = new ArrayList<>();
- possibleTiles.addAll(Arrays.asList(possible.split(",")));
- if (Build.IS_DEBUGGABLE) {
+ if (current != null) {
+ // The setting QS_TILES is not populated immediately upon Factory Reset
+ possibleTiles.addAll(Arrays.asList(current.split(",")));
+ }
+ String[] stockSplit = stock.split(",");
+ for (String spec : stockSplit) {
+ if (!current.contains(spec)) {
+ possibleTiles.add(spec);
+ }
+ }
+ if (Build.IS_DEBUGGABLE && !current.contains(GarbageMonitor.MemoryTile.TILE_SPEC)) {
possibleTiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
}
final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
for (String spec : possibleTiles) {
+ // Only add current and stock tiles that can be created from QSFactoryImpl
final QSTile tile = host.createTile(spec);
if (tile == null) {
continue;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index b2f60436fecd..7d52f0b2763d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -114,7 +114,7 @@ public class QSFactoryImpl implements QSFactory {
}
// Broken tiles.
- Log.w(TAG, "Bad tile spec: " + tileSpec);
+ Log.w(TAG, "No stock tile spec: " + tileSpec);
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index 0638998d8e67..3a96595dee06 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -198,7 +198,8 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView {
mIcon.setIcon(state, allowAnimations);
setContentDescription(state.contentDescription);
- mAccessibilityClass = state.expandedAccessibilityClassName;
+ mAccessibilityClass =
+ state.state == Tile.STATE_UNAVAILABLE ? null : state.expandedAccessibilityClassName;
if (state instanceof QSTile.BooleanState) {
boolean newState = ((BooleanState) state).value;
if (mTileState != newState) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index c62a592be8e2..3ab1c21b5066 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -205,7 +205,10 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
} else {
final BluetoothClass bluetoothClass = lastDevice.getBtClass();
if (bluetoothClass != null) {
- if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
+ if (lastDevice.isHearingAidDevice()) {
+ return mContext.getString(
+ R.string.quick_settings_bluetooth_secondary_label_hearing_aids);
+ } else if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
return mContext.getString(
R.string.quick_settings_bluetooth_secondary_label_audio);
} else if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 1b89324209de..12b6f673de1c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -43,6 +43,7 @@ import android.provider.Settings;
import android.util.Log;
import android.view.MotionEvent;
+import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.Prefs;
@@ -97,6 +98,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private int mCurrentBoundedUserId = -1;
private float mBackButtonAlpha;
private MotionEvent mStatusBarGestureDownEvent;
+ private float mWindowCornerRadius;
private ISystemUiProxy mSysUiProxy = new ISystemUiProxy.Stub() {
@@ -228,6 +230,18 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
}
}
+ public float getWindowCornerRadius() {
+ if (!verifyCaller("getWindowCornerRadius")) {
+ return 0;
+ }
+ long token = Binder.clearCallingIdentity();
+ try {
+ return mWindowCornerRadius;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
private boolean verifyCaller(String reason) {
final int callerId = Binder.getCallingUserHandle().getIdentifier();
if (callerId != mCurrentBoundedUserId) {
@@ -334,6 +348,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
.setPackage(mRecentsComponentName.getPackageName());
mInteractionFlags = Prefs.getInt(mContext, Prefs.Key.QUICK_STEP_INTERACTION_FLAGS,
getDefaultInteractionFlags());
+ mWindowCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(mContext.getResources());
// Listen for the package update changes.
if (mDeviceProvisionedController.getCurrentUser() == UserHandle.USER_SYSTEM) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 0c8f48752455..8b9399536969 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -21,7 +21,7 @@ import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.graphics.Rect;
-import android.hardware.biometrics.IBiometricPromptReceiver;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -96,6 +96,7 @@ public class CommandQueue extends IStatusBar.Stub {
private static final int MSG_SHOW_CHARGING_ANIMATION = 44 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ENTER_EXIT = 45 << MSG_SHIFT;
private static final int MSG_SHOW_PINNING_TOAST_ESCAPE = 46 << MSG_SHIFT;
+ private static final int MSG_BIOMETRIC_TRY_AGAIN = 47 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -163,12 +164,13 @@ public class CommandQueue extends IStatusBar.Stub {
default void onRotationProposal(int rotation, boolean isValid) { }
- default void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver,
+ default void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
int type, boolean requireConfirmation, int userId) { }
default void onBiometricAuthenticated() { }
default void onBiometricHelp(String message) { }
default void onBiometricError(String error) { }
default void hideBiometricDialog() { }
+ default void showBiometricTryAgain() { }
}
@VisibleForTesting
@@ -523,8 +525,8 @@ public class CommandQueue extends IStatusBar.Stub {
}
@Override
- public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
- boolean requireConfirmation, int userId) {
+ public void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
+ int type, boolean requireConfirmation, int userId) {
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = bundle;
@@ -565,6 +567,13 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
+ @Override
+ public void showBiometricTryAgain() {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_BIOMETRIC_TRY_AGAIN).sendToTarget();
+ }
+ }
+
private final class H extends Handler {
private H(Looper l) {
super(l);
@@ -774,7 +783,7 @@ public class CommandQueue extends IStatusBar.Stub {
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).showBiometricDialog(
(Bundle) someArgs.arg1,
- (IBiometricPromptReceiver) someArgs.arg2,
+ (IBiometricServiceReceiverInternal) someArgs.arg2,
someArgs.argi1 /* type */,
(boolean) someArgs.arg3 /* requireConfirmation */,
someArgs.argi2 /* userId */);
@@ -816,6 +825,11 @@ public class CommandQueue extends IStatusBar.Stub {
mCallbacks.get(i).showPinningEscapeToast();
}
break;
+ case MSG_BIOMETRIC_TRY_AGAIN:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showBiometricTryAgain();
+ }
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index f0e5462bc167..f506753379a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -29,6 +29,7 @@ import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
+import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.shared.system.SurfaceControlCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier;
@@ -55,6 +56,7 @@ public class ActivityLaunchAnimator {
private final NotificationPanelView mNotificationPanel;
private final NotificationListContainer mNotificationContainer;
private final StatusBarWindowView mStatusBarWindow;
+ private final float mWindowCornerRadius;
private Callback mCallback;
private final Runnable mTimeoutRunnable = () -> {
setAnimationPending(false);
@@ -72,6 +74,8 @@ public class ActivityLaunchAnimator {
mNotificationContainer = container;
mStatusBarWindow = statusBarWindow;
mCallback = callback;
+ mWindowCornerRadius = ScreenDecorationsUtils
+ .getWindowCornerRadius(statusBarWindow.getResources());
}
public RemoteAnimationAdapter getLaunchAnimation(
@@ -124,6 +128,8 @@ public class ActivityLaunchAnimator {
private final ExpandableNotificationRow mSourceNotification;
private final ExpandAnimationParameters mParams;
private final Rect mWindowCrop = new Rect();
+ private final float mNotificationCornerRadius;
+ private float mCornerRadius;
private boolean mIsFullScreenLaunch = true;
private final SyncRtSurfaceTransactionApplier mSyncRtTransactionApplier;
@@ -131,6 +137,8 @@ public class ActivityLaunchAnimator {
mSourceNotification = sourceNofitication;
mParams = new ExpandAnimationParameters();
mSyncRtTransactionApplier = new SyncRtSurfaceTransactionApplier(mSourceNotification);
+ mNotificationCornerRadius = Math.max(mSourceNotification.getCurrentTopRoundness(),
+ mSourceNotification.getCurrentBottomRoundness());
}
@Override
@@ -181,8 +189,7 @@ public class ActivityLaunchAnimator {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mParams.linearProgress = animation.getAnimatedFraction();
- float progress
- = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
+ float progress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
mParams.linearProgress);
int newWidth = (int) MathUtils.lerp(notificationWidth,
targetWidth, progress);
@@ -194,6 +201,8 @@ public class ActivityLaunchAnimator {
+ notificationHeight,
primary.position.y + primary.sourceContainerBounds.bottom,
progress);
+ mCornerRadius = MathUtils.lerp(mNotificationCornerRadius,
+ mWindowCornerRadius, progress);
applyParamsToWindow(primary);
applyParamsToNotification(mParams);
applyParamsToNotificationList(mParams);
@@ -259,7 +268,7 @@ public class ActivityLaunchAnimator {
m.postTranslate(0, (float) (mParams.top - app.position.y));
mWindowCrop.set(mParams.left, 0, mParams.right, mParams.getHeight());
SurfaceParams params = new SurfaceParams(new SurfaceControlCompat(app.leash),
- 1f /* alpha */, m, mWindowCrop, app.prefixOrderIndex);
+ 1f /* alpha */, m, mWindowCrop, app.prefixOrderIndex, mCornerRadius);
mSyncRtTransactionApplier.scheduleApply(params);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
index 314a31d336fd..0a2e04fd9430 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MessagingLayoutTransformState.java
@@ -250,23 +250,24 @@ public class MessagingLayoutTransformState extends TransformState {
otherChild = null;
}
}
- if (otherChild == null) {
+ if (otherChild == null && previousTranslation < 0) {
+ // Let's fade out as we approach the top of the screen. We can only do this if
+ // we're actually moving up
float distanceToTop = child.getTop() + child.getHeight() + previousTranslation;
transformationAmount = distanceToTop / child.getHeight();
transformationAmount = Math.max(0.0f, Math.min(1.0f, transformationAmount));
- if (to) {
- transformationAmount = 1.0f - transformationAmount;
- }
}
transformView(transformationAmount, to, child, otherChild, false, /* sameAsAny */
useLinearTransformation);
- if (transformationAmount == 0.0f
- && otherGroup.getIsolatedMessage() == otherChild) {
+ boolean otherIsIsolated = otherGroup.getIsolatedMessage() == otherChild;
+ if (transformationAmount == 0.0f && otherIsIsolated) {
ownGroup.setTransformingImages(true);
}
if (otherChild == null) {
child.setTranslationY(previousTranslation);
setClippingDeactivated(child, true);
+ } else if (ownGroup.getIsolatedMessage() == child || otherIsIsolated) {
+ // We don't want to add any translation for the image that is transforming
} else if (to) {
float totalTranslation = child.getTop() + ownGroup.getTop()
- otherChild.getTop() - otherChild.getTop();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index d7680b3523ba..3f8583c6241b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -66,7 +66,6 @@ import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGuts;
import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -174,7 +173,6 @@ public class NotificationData {
public void populateFromRanking(@NonNull Ranking ranking) {
channel = ranking.getChannel();
audiblyAlerted = ranking.audiblyAlerted();
- noisy = ranking.isNoisy();
importance = ranking.getImportance();
snoozeCriteria = ranking.getSnoozeCriteria();
userSentiment = ranking.getUserSentiment();
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 7970f166d8a6..1616b6dc53de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -176,9 +176,12 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
}
// Check if the notification is displaying the menu, if so slide notification back
- if (row.getProvider() != null && row.getProvider().isMenuVisible()) {
+ if (isMenuVisible(row)) {
row.animateTranslateNotification(0);
return;
+ } else if (row.isChildInGroup() && isMenuVisible(row.getNotificationParent())) {
+ row.getNotificationParent().animateTranslateNotification(0);
+ return;
}
// Mark notification for one frame.
@@ -193,6 +196,10 @@ public class NotificationEntryManager implements Dumpable, NotificationInflater.
mCallback.onNotificationClicked(sbn, row);
}
+ private boolean isMenuVisible(ExpandableNotificationRow row) {
+ return row.getProvider() != null && row.getProvider().isMenuVisible();
+ }
+
public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
if (notification.contentIntent != null || notification.fullScreenIntent != null) {
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 0cd431f9d25b..d4d45ea52a85 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
@@ -2067,6 +2067,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private void setChildIsExpanding(boolean isExpanding) {
mChildIsExpanding = isExpanding;
+ updateClipping();
+ invalidate();
}
@Override
@@ -2968,7 +2970,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return true;
}
} else if (child == mChildrenContainer) {
- if (!mChildIsExpanding && (isClippingNeeded() || !hasNoRounding())) {
+ if (isClippingNeeded() || !hasNoRounding()) {
return true;
}
} else if (child instanceof NotificationGuts) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index a7aed5fce2e1..0efb1308e83e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -115,12 +115,14 @@ public abstract class ExpandableOutlineView extends ExpandableView {
if (!mCustomOutline) {
int translation = mShouldTranslateContents && !ignoreTranslation
? (int) getTranslation() : 0;
- left = Math.max(translation, 0);
+ int halfExtraWidth = (int) (mExtraWidthForClipping / 2.0f);
+ left = Math.max(translation, 0) - halfExtraWidth;
top = mClipTopAmount + mBackgroundTop;
- right = getWidth() + Math.min(translation, 0);
+ right = getWidth() + halfExtraWidth + Math.min(translation, 0);
// If the top is rounded we want the bottom to be at most at the top roundness, in order
// to avoid the shadow changing when scrolling up.
- bottom = Math.max(getActualHeight() - mClipBottomAmount, (int) (top + topRoundness));
+ bottom = Math.max(mMinimumHeightForClipping,
+ Math.max(getActualHeight() - mClipBottomAmount, (int) (top + topRoundness)));
} else {
left = mOutlineRect.left;
top = mOutlineRect.top;
@@ -219,10 +221,12 @@ public abstract class ExpandableOutlineView extends ExpandableView {
public void setExtraWidthForClipping(float extraWidthForClipping) {
mExtraWidthForClipping = extraWidthForClipping;
+ invalidate();
}
public void setMinimumHeightForClipping(int minimumHeightForClipping) {
mMinimumHeightForClipping = minimumHeightForClipping;
+ invalidate();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 92d1b452bf44..689d6d530308 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -492,12 +492,12 @@ public class NotificationContentView extends FrameLayout {
if (child == null) {
mExpandedChild = null;
mExpandedWrapper = null;
- if (mVisibleType == VISIBLE_TYPE_EXPANDED) {
- mVisibleType = VISIBLE_TYPE_CONTRACTED;
- }
if (mTransformationStartVisibleType == VISIBLE_TYPE_EXPANDED) {
mTransformationStartVisibleType = UNDEFINED;
}
+ if (mVisibleType == VISIBLE_TYPE_EXPANDED) {
+ selectLayout(false /* animate */, true /* force */);
+ }
return;
}
addView(child);
@@ -530,12 +530,12 @@ public class NotificationContentView extends FrameLayout {
if (child == null) {
mHeadsUpChild = null;
mHeadsUpWrapper = null;
- if (mVisibleType == VISIBLE_TYPE_HEADSUP) {
- mVisibleType = VISIBLE_TYPE_CONTRACTED;
- }
if (mTransformationStartVisibleType == VISIBLE_TYPE_HEADSUP) {
mTransformationStartVisibleType = UNDEFINED;
}
+ if (mVisibleType == VISIBLE_TYPE_HEADSUP) {
+ selectLayout(false /* animate */, true /* force */);
+ }
return;
}
addView(child);
@@ -557,12 +557,12 @@ public class NotificationContentView extends FrameLayout {
if (child == null) {
mAmbientChild = null;
mAmbientWrapper = null;
- if (mVisibleType == VISIBLE_TYPE_AMBIENT) {
- mVisibleType = VISIBLE_TYPE_CONTRACTED;
- }
if (mTransformationStartVisibleType == VISIBLE_TYPE_AMBIENT) {
mTransformationStartVisibleType = UNDEFINED;
}
+ if (mVisibleType == VISIBLE_TYPE_AMBIENT) {
+ selectLayout(false /* animate */, true /* force */);
+ }
return;
}
addView(child);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 3b407b5f8a65..3dc50ae55c56 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -290,7 +290,6 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
row.getIsNonblockable(),
isForBlockingHelper,
row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE,
- row.getEntry().noisy,
row.getEntry().importance);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 213ac704b06a..5329541db92a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -104,7 +104,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
private AnimatorSet mExpandAnimation;
private boolean mIsForeground;
private boolean mIsDeviceProvisioned;
- private boolean mIsNoisy;
private CheckSaveListener mCheckSaveListener;
private OnSettingsClickListener mOnSettingsClickListener;
@@ -186,13 +185,12 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
final OnAppSettingsClickListener onAppSettingsClick,
boolean isDeviceProvisioned,
boolean isNonblockable,
- boolean isNoisy,
int importance)
throws RemoteException {
bindNotification(pm, iNotificationManager, pkg, notificationChannel,
numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
onAppSettingsClick, isDeviceProvisioned, isNonblockable,
- false /* isBlockingHelper */, false /* isUserSentimentNegative */, isNoisy,
+ false /* isBlockingHelper */, false /* isUserSentimentNegative */,
importance);
}
@@ -210,7 +208,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
boolean isNonblockable,
boolean isForBlockingHelper,
boolean isUserSentimentNegative,
- boolean isNoisy,
int importance)
throws RemoteException {
mINotificationManager = iNotificationManager;
@@ -236,7 +233,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
mAppUid = mSbn.getUid();
mDelegatePkg = mSbn.getOpPkg();
mIsDeviceProvisioned = isDeviceProvisioned;
- mIsNoisy = isNoisy;
int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
pkg, mAppUid, false /* includeDeleted */);
@@ -411,54 +407,74 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
}
private void bindButtons() {
- // Set up stay-in-notification actions
- View block = findViewById(R.id.block);
- TextView keep = findViewById(R.id.keep);
- TextView silent = findViewById(R.id.toggle_silent);
- View minimize = findViewById(R.id.minimize);
-
findViewById(R.id.undo).setOnClickListener(mOnUndo);
- block.setOnClickListener(mOnStopOrMinimizeNotifications);
- keep.setOnClickListener(mOnKeepShowing);
- silent.setOnClickListener(mOnToggleSilent);
- minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
- if (mIsNonblockable) {
- keep.setText(android.R.string.ok);
- block.setVisibility(GONE);
- silent.setVisibility(GONE);
- minimize.setVisibility(GONE);
- } else if (mIsForeground) {
- block.setVisibility(GONE);
- silent.setVisibility(GONE);
- minimize.setVisibility(VISIBLE);
- } else {
- block.setVisibility(VISIBLE);
- boolean showToggleSilent = mIsNoisy
- && NotificationUtils.useNewInterruptionModel(mContext);
- silent.setVisibility(showToggleSilent ? VISIBLE : GONE);
+ boolean showInterruptivenessSettings =
+ !mIsNonblockable
+ && !mIsForeground
+ && !mIsForBlockingHelper
+ && NotificationUtils.useNewInterruptionModel(mContext);
+ if (showInterruptivenessSettings) {
+ findViewById(R.id.block_or_minimize).setVisibility(GONE);
+ findViewById(R.id.interruptiveness_settings).setVisibility(VISIBLE);
+ View block = findViewById(R.id.int_block);
+ TextView silent = findViewById(R.id.int_silent);
+ TextView alert = findViewById(R.id.int_alert);
+
boolean isCurrentlyAlerting =
mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT;
- silent.setText(isCurrentlyAlerting
- ? R.string.inline_silent_button_silent
- : R.string.inline_silent_button_alert);
- minimize.setVisibility(GONE);
- }
- // Set up app settings link (i.e. Customize)
- TextView settingsLinkView = findViewById(R.id.app_settings);
- Intent settingsIntent = getAppSettingsIntent(mPm, mPackageName, mSingleNotificationChannel,
- mSbn.getId(), mSbn.getTag());
- if (!mIsForBlockingHelper
- && settingsIntent != null
- && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
- settingsLinkView.setVisibility(VISIBLE);
- settingsLinkView.setText(mContext.getString(R.string.notification_app_settings));
- settingsLinkView.setOnClickListener((View view) -> {
- mAppSettingsClickListener.onClick(view, settingsIntent);
- });
+ block.setOnClickListener(mOnStopOrMinimizeNotifications);
+ if (isCurrentlyAlerting) {
+ silent.setOnClickListener(mOnToggleSilent);
+ silent.setText(R.string.inline_silent_button_silent);
+ alert.setOnClickListener(mOnKeepShowing);
+ alert.setText(R.string.inline_silent_button_keep_alerting);
+ } else {
+ silent.setOnClickListener(mOnKeepShowing);
+ silent.setText(R.string.inline_silent_button_stay_silent);
+ alert.setOnClickListener(mOnToggleSilent);
+ alert.setText(R.string.inline_silent_button_alert);
+ }
} else {
- settingsLinkView.setVisibility(View.GONE);
+ findViewById(R.id.block_or_minimize).setVisibility(VISIBLE);
+ findViewById(R.id.interruptiveness_settings).setVisibility(GONE);
+ View block = findViewById(R.id.block);
+ TextView keep = findViewById(R.id.keep);
+ View minimize = findViewById(R.id.minimize);
+
+ block.setOnClickListener(mOnStopOrMinimizeNotifications);
+ keep.setOnClickListener(mOnKeepShowing);
+ minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
+
+ if (mIsNonblockable) {
+ keep.setText(android.R.string.ok);
+ block.setVisibility(GONE);
+ minimize.setVisibility(GONE);
+ } else if (mIsForeground) {
+ block.setVisibility(GONE);
+ minimize.setVisibility(VISIBLE);
+ } else {
+ block.setVisibility(VISIBLE);
+ minimize.setVisibility(GONE);
+ }
+
+ // Set up app settings link (i.e. Customize)
+ TextView settingsLinkView = findViewById(R.id.app_settings);
+ Intent settingsIntent = getAppSettingsIntent(mPm, mPackageName,
+ mSingleNotificationChannel,
+ mSbn.getId(), mSbn.getTag());
+ if (!mIsForBlockingHelper
+ && settingsIntent != null
+ && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
+ settingsLinkView.setVisibility(VISIBLE);
+ settingsLinkView.setText(mContext.getString(R.string.notification_app_settings));
+ settingsLinkView.setOnClickListener((View view) -> {
+ mAppSettingsClickListener.onClick(view, settingsIntent);
+ });
+ } else {
+ settingsLinkView.setVisibility(View.GONE);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 713bd90b30c3..fef28cf1393e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -375,12 +375,9 @@ public class StackStateAnimator {
// Find the amount to translate up. This is needed in order to understand the
// direction of the remove animation (either downwards or upwards)
- ExpandableViewState viewState =
- ((ExpandableView) event.viewAfterChangingView).getViewState();
- int actualHeight = changingView.getActualHeight();
// upwards by default
float translationDirection = -1.0f;
- if (viewState != null) {
+ if (event.viewAfterChangingView != null) {
float ownPosition = changingView.getTranslationY();
if (changingView instanceof ExpandableNotificationRow
&& event.viewAfterChangingView instanceof ExpandableNotificationRow) {
@@ -396,8 +393,11 @@ public class StackStateAnimator {
ownPosition = changingRow.getTranslationWhenRemoved();
}
}
+ int actualHeight = changingView.getActualHeight();
// there was a view after this one, Approximate the distance the next child
// travelled
+ ExpandableViewState viewState =
+ ((ExpandableView) event.viewAfterChangingView).getViewState();
translationDirection = ((viewState.yTranslation
- (ownPosition + actualHeight / 2.0f)) * 2 /
actualHeight);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 33d022c83c16..cd6e1d794428 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
@@ -950,10 +951,10 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
private void updateTaskSwitchHelper() {
if (mGestureHelper == null) return;
boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
- int navBarPos = 0;
+ int navBarPos = NAV_BAR_INVALID;
try {
- // TODO: Use WindowManagerService.getNavBarPosition(int displayId)
- navBarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition();
+ navBarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition(
+ mDisplay.getDisplayId());
} catch (RemoteException e) {
Slog.e(TAG, "Failed to get nav bar position.", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index 497fdfb2deb1..43e86d66b8be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
@@ -421,6 +422,9 @@ public class QuickStepController implements GestureHelper {
mDragHPositive = !isRTL;
mDragVPositive = true;
break;
+ case NAV_BAR_INVALID:
+ Log.e(TAG, "Invalid nav bar position");
+ break;
}
for (NavigationGestureAction action: mGestureActions) {
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 2fc3adc4c98f..cfd53be8979b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -721,7 +721,7 @@ public class StatusBar extends SystemUI implements DemoMode,
IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
ServiceManager.getService(Context.WALLPAPER_SERVICE));
try {
- wallpaperManager.setInAmbientMode(false /* ambientMode */, false /* animated */);
+ wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */);
} catch (RemoteException e) {
// Just pass, nothing critical.
}
@@ -1211,7 +1211,8 @@ public class StatusBar extends SystemUI implements DemoMode,
}
int dockSide = WindowManagerProxy.getInstance().getDockSide();
if (dockSide == WindowManager.DOCKED_INVALID) {
- final int navbarPos = WindowManagerWrapper.getInstance().getNavBarPosition();
+ final int navbarPos = WindowManagerWrapper.getInstance().getNavBarPosition(
+ mDisplay.getDisplayId());
if (navbarPos == NAV_BAR_POS_INVALID) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 62b6d91fc192..158ee8ae8fbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -283,7 +283,6 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
applyModalFlag(state);
applyBrightness(state);
applyHasTopUi(state);
- applySleepToken(state);
applyNotTouchable(state);
if (mLp.copyFrom(mLpChanged) != 0) {
mWindowManager.updateViewLayout(mStatusBarView, mLp);
@@ -328,14 +327,6 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
mHasTopUiChanged = isExpanded(state);
}
- private void applySleepToken(State state) {
- if (state.dozing) {
- mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
- } else {
- mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
- }
- }
-
private void applyNotTouchable(State state) {
if (state.notTouchable) {
mLpChanged.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
index 6ac44628b52f..ec2319d80194 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
@@ -16,9 +16,8 @@
package com.android.systemui.doze;
-import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,8 +26,8 @@ import android.app.IWallpaperManager;
import android.os.RemoteException;
import android.support.test.filters.SmallTest;
-import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
import org.junit.Before;
@@ -59,14 +58,14 @@ public class DozeWallpaperStateTest extends SysuiTestCase {
mDozeWallpaperState.transitionTo(DozeMachine.State.UNINITIALIZED,
DozeMachine.State.DOZE_AOD);
- verify(mIWallpaperManager).setInAmbientMode(eq(true), anyBoolean());
+ verify(mIWallpaperManager).setInAmbientMode(eq(true), anyLong());
mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_AOD, DozeMachine.State.FINISH);
- verify(mIWallpaperManager).setInAmbientMode(eq(false), anyBoolean());
+ verify(mIWallpaperManager).setInAmbientMode(eq(false), anyLong());
// Make sure we're sending false when AoD is off
reset(mDozeParameters);
mDozeWallpaperState.transitionTo(DozeMachine.State.FINISH, DozeMachine.State.DOZE_AOD);
- verify(mIWallpaperManager).setInAmbientMode(eq(false), anyBoolean());
+ verify(mIWallpaperManager).setInAmbientMode(eq(false), anyLong());
}
@Test
@@ -78,10 +77,12 @@ public class DozeWallpaperStateTest extends SysuiTestCase {
mDozeWallpaperState.transitionTo(DozeMachine.State.UNINITIALIZED,
DozeMachine.State.DOZE_AOD);
- verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(true));
+ verify(mIWallpaperManager).setInAmbientMode(eq(true),
+ eq((long) StackStateAnimator.ANIMATION_DURATION_WAKEUP));
mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_AOD, DozeMachine.State.FINISH);
- verify(mIWallpaperManager).setInAmbientMode(eq(false), eq(true));
+ verify(mIWallpaperManager).setInAmbientMode(eq(false),
+ eq((long) StackStateAnimator.ANIMATION_DURATION_WAKEUP));
}
@Test
@@ -93,24 +94,24 @@ public class DozeWallpaperStateTest extends SysuiTestCase {
mDozeWallpaperState.transitionTo(DozeMachine.State.UNINITIALIZED,
DozeMachine.State.DOZE_AOD);
- verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(false));
+ verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(0L));
mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_AOD, DozeMachine.State.FINISH);
- verify(mIWallpaperManager).setInAmbientMode(eq(false), eq(false));
+ verify(mIWallpaperManager).setInAmbientMode(eq(false), eq(0L));
}
@Test
public void testTransitionTo_requestPulseIsAmbientMode() throws RemoteException {
mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE,
DozeMachine.State.DOZE_REQUEST_PULSE);
- verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(false));
+ verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(0L));
}
@Test
public void testTransitionTo_pulseIsAmbientMode() throws RemoteException {
mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE,
DozeMachine.State.DOZE_PULSING);
- verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(false));
+ verify(mIWallpaperManager).setInAmbientMode(eq(true), eq(0L));
}
@Test
@@ -120,6 +121,7 @@ public class DozeWallpaperStateTest extends SysuiTestCase {
reset(mIWallpaperManager);
mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_PULSING,
DozeMachine.State.FINISH);
- verify(mIWallpaperManager).setInAmbientMode(eq(false), eq(true));
+ verify(mIWallpaperManager).setInAmbientMode(eq(false),
+ eq((long) StackStateAnimator.ANIMATION_DURATION_WAKEUP));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index f63d2360d976..26fa20de4e86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -14,41 +14,76 @@
package com.android.systemui.qs.customize;
-import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
+import android.text.TextUtils;
+import android.util.ArraySet;
import com.android.systemui.Dependency;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSTileHost;
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 java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
public class TileQueryHelperTest extends SysuiTestCase {
- @Mock private TileQueryHelper.TileStateListener mListener;
- @Mock private QSTileHost mQSTileHost;
+ private static final String CURRENT_TILES = "wifi,dnd,nfc";
+ private static final String ONLY_STOCK_TILES = "wifi,dnd";
+ private static final String WITH_OTHER_TILES = "wifi,dnd,other";
+ // Note no nfc in stock tiles
+ private static final String STOCK_TILES = "wifi,dnd,cell,battery";
+ private static final String ALL_TILES = "wifi,dnd,nfc,cell,battery";
+ private static final Set<String> FACTORY_TILES = new ArraySet<>();
+
+ static {
+ FACTORY_TILES.addAll(Arrays.asList(
+ new String[]{"wifi", "bt", "cell", "dnd", "inversion", "airplane", "work",
+ "rotation", "flashlight", "location", "cast", "hotspot", "user", "battery",
+ "saver", "night", "nfc"}));
+ }
- private TestableLooper mBGLooper;
+ @Mock
+ private TileQueryHelper.TileStateListener mListener;
+ @Mock
+ private QSTileHost mQSTileHost;
+ @Mock
+ private PackageManager mPackageManager;
+ private QSTile.State mState;
+ private TestableLooper mBGLooper;
private TileQueryHelper mTileQueryHelper;
@Before
@@ -56,6 +91,23 @@ public class TileQueryHelperTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mBGLooper = TestableLooper.get(this);
mDependency.injectTestDependency(Dependency.BG_LOOPER, mBGLooper.getLooper());
+ mContext.setMockPackageManager(mPackageManager);
+
+ mState = new QSTile.State();
+ doAnswer(invocation -> {
+ String spec = (String) invocation.getArguments()[0];
+ if (FACTORY_TILES.contains(spec)) {
+ QSTile m = mock(QSTile.class);
+ when(m.isAvailable()).thenReturn(true);
+ when(m.getTileSpec()).thenReturn(spec);
+ when(m.getState()).thenReturn(mState);
+ return m;
+ } else {
+ return null;
+ }
+ }
+ ).when(mQSTileHost).createTile(anyString());
+
mTileQueryHelper = new TileQueryHelper(mContext, mListener);
}
@@ -98,4 +150,72 @@ public class TileQueryHelperTest extends SysuiTestCase {
assertTrue(mTileQueryHelper.isFinished());
}
+
+ @Test
+ public void testQueryTiles_correctTilesAndOrderOnlyStockTiles() {
+ ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class);
+
+ Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
+ ONLY_STOCK_TILES);
+ mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
+ STOCK_TILES);
+
+ mTileQueryHelper.queryTiles(mQSTileHost);
+
+ mBGLooper.processAllMessages();
+ waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+
+ verify(mListener, atLeastOnce()).onTilesChanged(captor.capture());
+ List<String> specs = new ArrayList<>();
+ for (TileQueryHelper.TileInfo t : captor.getValue()) {
+ specs.add(t.spec);
+ }
+ String tiles = TextUtils.join(",", specs);
+ assertThat(tiles, is(equalTo(STOCK_TILES)));
+ }
+
+ @Test
+ public void testQueryTiles_correctTilesAndOrderOtherFactoryTiles() {
+ ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class);
+
+ Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
+ CURRENT_TILES);
+ mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
+ STOCK_TILES);
+
+ mTileQueryHelper.queryTiles(mQSTileHost);
+
+ mBGLooper.processAllMessages();
+ waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+
+ verify(mListener, atLeastOnce()).onTilesChanged(captor.capture());
+ List<String> specs = new ArrayList<>();
+ for (TileQueryHelper.TileInfo t : captor.getValue()) {
+ specs.add(t.spec);
+ }
+ String tiles = TextUtils.join(",", specs);
+ assertThat(tiles, is(equalTo(ALL_TILES)));
+ }
+
+ @Test
+ public void testQueryTiles_otherTileNotIncluded() {
+ ArgumentCaptor<List<TileQueryHelper.TileInfo>> captor = ArgumentCaptor.forClass(List.class);
+
+ Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.QS_TILES,
+ WITH_OTHER_TILES);
+ mContext.getOrCreateTestableResources().addOverride(R.string.quick_settings_tiles_stock,
+ STOCK_TILES);
+
+ mTileQueryHelper.queryTiles(mQSTileHost);
+
+ mBGLooper.processAllMessages();
+ waitForIdleSync(Dependency.get(Dependency.MAIN_HANDLER));
+
+ verify(mListener, atLeastOnce()).onTilesChanged(captor.capture());
+ List<String> specs = new ArrayList<>();
+ for (TileQueryHelper.TileInfo t : captor.getValue()) {
+ specs.add(t.spec);
+ }
+ assertFalse(specs.contains("other"));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
index 435ede4d8ff0..55583931af43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
@@ -62,6 +62,7 @@ public class ActivityLaunchAnimatorTest extends SysuiTestCase {
@Before
public void setUp() throws Exception {
+ when(mStatusBarWindowView.getResources()).thenReturn(mContext.getResources());
when(mCallback.areLaunchAnimationsEnabled()).thenReturn(true);
mLaunchAnimator = new ActivityLaunchAnimator(
mStatusBarWindowView,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 84bfae650ce3..766c5d2377c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -311,7 +311,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(false),
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
- eq(false) /*isNoisy */,
eq(0));
}
@@ -340,37 +339,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(false),
eq(false) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
- eq(false) /*isNoisy */,
- eq(0));
- }
-
- @Test
- public void testInitializeNotificationInfoView_noisy() throws Exception {
- NotificationInfo notificationInfoView = mock(NotificationInfo.class);
- ExpandableNotificationRow row = spy(mHelper.createRow());
- row.setBlockingHelperShowing(true);
- row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
- row.getEntry().noisy = true;
- when(row.getIsNonblockable()).thenReturn(false);
- StatusBarNotification statusBarNotification = row.getStatusBarNotification();
-
- mGutsManager.initializeNotificationInfo(row, notificationInfoView);
-
- verify(notificationInfoView).bindNotification(
- any(PackageManager.class),
- any(INotificationManager.class),
- eq(statusBarNotification.getPackageName()),
- any(NotificationChannel.class),
- anyInt(),
- eq(statusBarNotification),
- any(NotificationInfo.CheckSaveListener.class),
- any(NotificationInfo.OnSettingsClickListener.class),
- any(NotificationInfo.OnAppSettingsClickListener.class),
- eq(false),
- eq(false),
- eq(true) /* isForBlockingHelper */,
- eq(true) /* isUserSentimentNegative */,
- eq(true) /*isNoisy */,
eq(0));
}
@@ -400,7 +368,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(false),
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
- eq(false) /*isNoisy */,
eq(IMPORTANCE_DEFAULT));
}
@@ -430,7 +397,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(false),
eq(false) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
- eq(false) /*isNoisy */,
eq(0));
}
@@ -459,7 +425,6 @@ public class NotificationGutsManagerTest extends SysuiTestCase {
eq(false),
eq(true) /* isForBlockingHelper */,
eq(true) /* isUserSentimentNegative */,
- eq(false) /*isNoisy */,
eq(0));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 3dd493f0cd44..d28f0172e7e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -50,12 +50,9 @@ import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.IBinder;
import android.os.UserHandle;
@@ -86,8 +83,6 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
-import java.util.ArrayList;
-import java.util.List;
import java.util.concurrent.CountDownLatch;
@SmallTest
@@ -187,7 +182,7 @@ public class NotificationInfoTest extends SysuiTestCase {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
assertTrue(textView.getText().toString().contains("App Name"));
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -200,7 +195,7 @@ public class NotificationInfoTest extends SysuiTestCase {
.thenReturn(iconDrawable);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -209,7 +204,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_noDelegate() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(GONE, nameView.getVisibility());
final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider);
@@ -228,7 +223,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(VISIBLE, nameView.getVisibility());
assertTrue(nameView.getText().toString().contains("Other"));
@@ -240,7 +235,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(GONE, groupNameView.getVisibility());
final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
@@ -257,7 +252,7 @@ public class NotificationInfoTest extends SysuiTestCase {
.thenReturn(notificationChannelGroup);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
assertEquals("Test Group Name", groupNameView.getText());
@@ -269,7 +264,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_SetsTextChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
}
@@ -278,7 +273,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false, false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, textView.getVisibility());
}
@@ -291,7 +286,7 @@ public class NotificationInfoTest extends SysuiTestCase {
eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
- false, false, IMPORTANCE_DEFAULT);
+ false, IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -300,7 +295,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -309,62 +304,104 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_BlockButton() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
- final View block = mNotificationInfo.findViewById(R.id.block);
- final View toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
- final View minimize = mNotificationInfo.findViewById(R.id.minimize);
+ IMPORTANCE_DEFAULT);
+ final View block = mNotificationInfo.findViewById(R.id.int_block);
+ final View minimize = mNotificationInfo.findViewById(R.id.block_or_minimize);
assertEquals(VISIBLE, block.getVisibility());
- assertEquals(GONE, toggleSilent.getVisibility());
assertEquals(GONE, minimize.getVisibility());
}
@Test
- public void testBindNotification_SilenceButton() throws Exception {
+ public void testBindNotification_BlockButton_BlockHelper() throws Exception {
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ true /* isBlockingHelper */, false, IMPORTANCE_DEFAULT);
+ final View block = mNotificationInfo.findViewById(R.id.block);
+ final View interruptivenessSettings = mNotificationInfo.findViewById(
+ R.id.interruptiveness_settings);
+ assertEquals(VISIBLE, block.getVisibility());
+ assertEquals(GONE, interruptivenessSettings.getVisibility());
+ }
+
+ @Test
+ public void testBindNotification_SilenceButton_CurrentlyAlerting() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
- final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
- assertEquals(VISIBLE, toggleSilent.getVisibility());
+ IMPORTANCE_DEFAULT);
+ final TextView silent = mNotificationInfo.findViewById(R.id.int_silent);
+ assertEquals(VISIBLE, silent.getVisibility());
assertEquals(
- mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+ mContext.getString(R.string.inline_silent_button_silent), silent.getText());
}
@Test
- public void testBindNotification_UnSilenceButton() throws Exception {
+ public void testBindNotification_SilenceButton_CurrentlySilent() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_LOW);
- final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
- assertEquals(VISIBLE, toggleSilent.getVisibility());
+ IMPORTANCE_LOW);
+ final TextView silent = mNotificationInfo.findViewById(R.id.int_silent);
+ assertEquals(VISIBLE, silent.getVisibility());
assertEquals(
- mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+ mContext.getString(R.string.inline_silent_button_stay_silent),
+ silent.getText());
}
@Test
- public void testBindNotification_SilenceButton_ChannelImportanceUnspecified() throws Exception {
+ public void testBindNotification_AlertButton_CurrentlySilent() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_LOW);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ IMPORTANCE_LOW);
+ final TextView alert = mNotificationInfo.findViewById(R.id.int_alert);
+ assertEquals(VISIBLE, alert.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_alert), alert.getText());
+ }
+
+ @Test
+ public void testBindNotification_UnSilenceButton_currentlyAlerting() throws Exception {
+ mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+ mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ IMPORTANCE_DEFAULT);
+ final TextView alert = mNotificationInfo.findViewById(R.id.int_alert);
+ assertEquals(VISIBLE, alert.getVisibility());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_keep_alerting), alert.getText());
+ }
+
+ @Test
+ public void testBindNotification_ChannelImportanceUnspecified_NotifAlerting() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
- final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
- assertEquals(VISIBLE, toggleSilent.getVisibility());
+ IMPORTANCE_DEFAULT);
+ final TextView silent = mNotificationInfo.findViewById(R.id.int_silent);
+ final TextView alert = mNotificationInfo.findViewById(R.id.int_alert);
+ assertEquals(VISIBLE, silent.getVisibility());
+ assertEquals(VISIBLE, alert.getVisibility());
assertEquals(
- mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+ mContext.getString(R.string.inline_silent_button_silent), silent.getText());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_keep_alerting), alert.getText());
}
@Test
- public void testBindNotification_UnSilenceButton_ChannelImportanceUnspecified()
- throws Exception {
+ public void testBindNotification_ChannelImportanceUnspecified_NotifSilent() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_LOW);
- final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
- assertEquals(VISIBLE, toggleSilent.getVisibility());
+ IMPORTANCE_LOW);
+ final TextView silent = mNotificationInfo.findViewById(R.id.int_silent);
+ final TextView alert = mNotificationInfo.findViewById(R.id.int_alert);
+ assertEquals(VISIBLE, silent.getVisibility());
+ assertEquals(VISIBLE, alert.getVisibility());
assertEquals(
- mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+ mContext.getString(R.string.inline_silent_button_stay_silent), silent.getText());
+ assertEquals(
+ mContext.getString(R.string.inline_silent_button_alert), alert.getText());
}
@Test
@@ -372,10 +409,13 @@ public class NotificationInfoTest extends SysuiTestCase {
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final View block = mNotificationInfo.findViewById(R.id.block);
+ final View interruptivenessSettings = mNotificationInfo.findViewById(
+ R.id.interruptiveness_settings);
final View minimize = mNotificationInfo.findViewById(R.id.minimize);
assertEquals(GONE, block.getVisibility());
+ assertEquals(GONE, interruptivenessSettings.getVisibility());
assertEquals(VISIBLE, minimize.getVisibility());
}
@@ -387,7 +427,7 @@ public class NotificationInfoTest extends SysuiTestCase {
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
latch.countDown();
- }, null, true, false, false, IMPORTANCE_DEFAULT);
+ }, null, true, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
settingsButton.performClick();
@@ -399,7 +439,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -411,7 +451,7 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
assertEquals(mNotificationChannel, c);
- }, null, false, false, false, IMPORTANCE_DEFAULT);
+ }, null, false, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -420,11 +460,11 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
(View v, NotificationChannel c, int appUid) -> {
- }, null, true, false, false, IMPORTANCE_DEFAULT);
+ }, null, true, false, IMPORTANCE_DEFAULT);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertEquals(View.VISIBLE, settingsButton.getVisibility());
}
@@ -433,7 +473,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
}
@@ -442,7 +482,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
- true, true, false, IMPORTANCE_DEFAULT);
+ true, true, IMPORTANCE_DEFAULT);
mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
}
@@ -455,7 +495,7 @@ public class NotificationInfoTest extends SysuiTestCase {
(View v, NotificationChannel c, int appUid) -> {
assertEquals(null, c);
latch.countDown();
- }, null, true, true, false, IMPORTANCE_DEFAULT);
+ }, null, true, true, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.info).performClick();
// Verify that listener was triggered.
@@ -468,7 +508,7 @@ public class NotificationInfoTest extends SysuiTestCase {
throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true, false, IMPORTANCE_DEFAULT);
+ null, true, true, IMPORTANCE_DEFAULT);
final TextView channelNameView =
mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, channelNameView.getVisibility());
@@ -479,7 +519,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
- null, true, true, false, IMPORTANCE_DEFAULT);
+ null, true, true, IMPORTANCE_DEFAULT);
final TextView blockView = mNotificationInfo.findViewById(R.id.block);
assertEquals(GONE, blockView.getVisibility());
}
@@ -488,7 +528,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testbindNotification_BlockingHelper() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
- true, true, false, IMPORTANCE_DEFAULT);
+ true, true, IMPORTANCE_DEFAULT);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
@@ -498,7 +538,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.notification_unblockable_desc),
@@ -509,7 +549,7 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
@@ -520,9 +560,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
@@ -534,7 +574,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
mTestableLooper.processAllMessages();
@@ -548,9 +588,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mNotificationInfo.findViewById(R.id.int_silent).performClick();
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
@@ -562,9 +602,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mNotificationInfo.findViewById(R.id.int_alert).performClick();
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
@@ -576,7 +616,7 @@ public class NotificationInfoTest extends SysuiTestCase {
int originalImportance = mNotificationChannel.getImportance();
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
@@ -591,7 +631,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
@@ -609,10 +649,10 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
- true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT
+ true, false /* isNonblockable */, IMPORTANCE_DEFAULT
);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
@@ -631,10 +671,10 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */,
- true, false /* isNonblockable */, false /* isNoisy */, IMPORTANCE_DEFAULT
+ true, false /* isNonblockable */, IMPORTANCE_DEFAULT
);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
@@ -653,7 +693,7 @@ public class NotificationInfoTest extends SysuiTestCase {
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT);
+ true /* isUserSentimentNegative */, IMPORTANCE_DEFAULT);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -681,7 +721,7 @@ public class NotificationInfoTest extends SysuiTestCase {
10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ , true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT);
+ true /* isUserSentimentNegative */, IMPORTANCE_DEFAULT);
NotificationGuts guts = spy(new NotificationGuts(mContext, null));
when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -709,7 +749,7 @@ public class NotificationInfoTest extends SysuiTestCase {
10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
null /* onSettingsClick */, null /* onAppSettingsClick */ ,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true, true /* isUserSentimentNegative */, false /* isNoisy */,
+ true, true /* isUserSentimentNegative */, /* isNoisy */
IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
@@ -729,7 +769,7 @@ public class NotificationInfoTest extends SysuiTestCase {
null /* onSettingsClick */, null /* onAppSettingsClick */,
true /* provisioned */,
false /* isNonblockable */, true /* isForBlockingHelper */,
- true /* isUserSentimentNegative */, false /* isNoisy */, IMPORTANCE_DEFAULT);
+ true /* isUserSentimentNegative */, IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
mTestableLooper.processAllMessages();
@@ -752,7 +792,7 @@ public class NotificationInfoTest extends SysuiTestCase {
true /* isForBlockingHelper */,
true,
false /* isUserSentimentNegative */,
- false /* isNoisy */, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
NotificationGuts guts = mock(NotificationGuts.class);
doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
mNotificationInfo.setGutsParent(guts);
@@ -767,7 +807,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -781,9 +821,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
@@ -814,7 +854,7 @@ public class NotificationInfoTest extends SysuiTestCase {
false /* isNonblockable */,
true /* isForBlockingHelper */,
true /* isUserSentimentNegative */,
- false/* isNoisy */, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.block).performClick();
waitForUndoButton();
@@ -836,7 +876,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -851,7 +891,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -872,7 +912,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.handleCloseControls(true, false);
@@ -890,9 +930,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
waitForUndoButton();
mNotificationInfo.findViewById(R.id.undo).performClick();
waitForStopButton();
@@ -911,8 +951,8 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+ IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -934,9 +974,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mNotificationInfo.findViewById(R.id.int_silent).performClick();
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
@@ -955,9 +995,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mNotificationInfo.findViewById(R.id.int_alert).performClick();
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
@@ -977,9 +1017,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- true, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mNotificationInfo.findViewById(R.id.int_silent).performClick();
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
@@ -999,9 +1039,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
- false, IMPORTANCE_LOW);
+ IMPORTANCE_LOW);
- mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mNotificationInfo.findViewById(R.id.int_alert).performClick();
waitForUndoButton();
mNotificationInfo.handleCloseControls(true, false);
@@ -1016,11 +1056,11 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@Test
- public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
+ public void testCloseControlsDoesNotUpdateMinIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -1035,10 +1075,10 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
waitForUndoButton();
mNotificationInfo.handleCloseControls(false, false);
@@ -1053,9 +1093,9 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
- }, null, null, true, true, false, IMPORTANCE_DEFAULT);
+ }, null, null, true, true, IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
mTestableLooper.processAllMessages();
ensureNoUndoButton();
mNotificationInfo.handleCloseControls(true, false);
@@ -1071,10 +1111,10 @@ public class NotificationInfoTest extends SysuiTestCase {
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
(Runnable saveImportance, StatusBarNotification sbn) -> {
saveImportance.run();
- }, null, null, true, false, false, IMPORTANCE_DEFAULT
+ }, null, null, true, false, IMPORTANCE_DEFAULT
);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
@@ -1088,124 +1128,6 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@Test
- public void testDisplaySettingsLink() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- final String settingsText = "work chats";
- final ResolveInfo ri = new ResolveInfo();
- ri.activityInfo = new ActivityInfo();
- ri.activityInfo.packageName = TEST_PACKAGE_NAME;
- ri.activityInfo.name = "something";
- List<ResolveInfo> ris = new ArrayList<>();
- ris.add(ri);
- when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
- mNotificationChannel.setImportance(IMPORTANCE_LOW);
- Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
- .setSettingsText(settingsText).build();
- StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
- 0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
- (View v, Intent intent) -> {
- latch.countDown();
- }, true, false, false, IMPORTANCE_DEFAULT);
- final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
- assertEquals(View.VISIBLE, settingsLink.getVisibility());
- settingsLink.performClick();
- assertEquals(0, latch.getCount());
- }
-
- @Test
- public void testDisplaySettingsLink_multipleChannels() throws Exception {
- final CountDownLatch latch = new CountDownLatch(1);
- final String settingsText = "work chats";
- final ResolveInfo ri = new ResolveInfo();
- ri.activityInfo = new ActivityInfo();
- ri.activityInfo.packageName = TEST_PACKAGE_NAME;
- ri.activityInfo.name = "something";
- List<ResolveInfo> ris = new ArrayList<>();
- ris.add(ri);
- when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
- mNotificationChannel.setImportance(IMPORTANCE_LOW);
- Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
- .setSettingsText(settingsText).build();
- StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
- 0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
- (View v, Intent intent) -> {
- latch.countDown();
- }, true, false, false, IMPORTANCE_DEFAULT);
- final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
- assertEquals(View.VISIBLE, settingsLink.getVisibility());
- settingsLink.performClick();
- assertEquals(0, latch.getCount());
- }
-
- @Test
- public void testNoSettingsLink_noHandlingActivity() throws Exception {
- final String settingsText = "work chats";
- when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(null);
- mNotificationChannel.setImportance(IMPORTANCE_LOW);
- Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
- .setSettingsText(settingsText).build();
- StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
- 0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
- null, true, false, false, IMPORTANCE_DEFAULT);
- final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
- assertEquals(GONE, settingsLink.getVisibility());
- }
-
- @Test
- public void testNoSettingsLink_noLinkText() throws Exception {
- final ResolveInfo ri = new ResolveInfo();
- ri.activityInfo = new ActivityInfo();
- ri.activityInfo.packageName = TEST_PACKAGE_NAME;
- ri.activityInfo.name = "something";
- List<ResolveInfo> ris = new ArrayList<>();
- ris.add(ri);
- when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
- mNotificationChannel.setImportance(IMPORTANCE_LOW);
- Notification n = new Notification.Builder(mContext, mNotificationChannel.getId()).build();
- StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
- 0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false,
- false, IMPORTANCE_DEFAULT);
- final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
- assertEquals(GONE, settingsLink.getVisibility());
- }
-
- @Test
- public void testBindHeader_noSettingsLinkWhenIsForBlockingHelper() throws Exception {
- final String settingsText = "work chats";
- final ResolveInfo ri = new ResolveInfo();
- ri.activityInfo = new ActivityInfo();
- ri.activityInfo.packageName = TEST_PACKAGE_NAME;
- ri.activityInfo.name = "something";
- List<ResolveInfo> ris = new ArrayList<>();
- ris.add(ri);
- when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
- mNotificationChannel.setImportance(IMPORTANCE_LOW);
- Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
- .setSettingsText(settingsText).build();
- StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
- 0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
-
- mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
- true, true, false, IMPORTANCE_DEFAULT);
- final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
- assertEquals(GONE, settingsLink.getVisibility());
- }
-
-
- @Test
public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
assertFalse(mNotificationInfo.willBeRemoved());
}
@@ -1216,7 +1138,7 @@ public class NotificationInfoTest extends SysuiTestCase {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ IMPORTANCE_DEFAULT);
mNotificationInfo.findViewById(R.id.minimize).performClick();
waitForUndoButton();
@@ -1228,10 +1150,10 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testUndoText_block() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
waitForUndoButton();
TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
assertTrue(confirmationText.getText().toString().contains("won't see"));
@@ -1241,10 +1163,10 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testUndoText_silence() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- true, IMPORTANCE_DEFAULT);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mNotificationInfo.findViewById(R.id.int_silent).performClick();
waitForUndoButton();
TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
assertEquals(mContext.getString(R.string.notification_channel_silenced),
@@ -1255,10 +1177,10 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testUndoText_unsilence() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- true, IMPORTANCE_DEFAULT);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+ mNotificationInfo.findViewById(R.id.int_alert).performClick();
waitForUndoButton();
TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
assertEquals(mContext.getString(R.string.notification_channel_unsilenced),
@@ -1269,10 +1191,10 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testNoHeaderOnConfirmation() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
waitForUndoButton();
assertEquals(GONE, mNotificationInfo.findViewById(R.id.header).getVisibility());
}
@@ -1281,10 +1203,10 @@ public class NotificationInfoTest extends SysuiTestCase {
public void testHeaderOnUndo() throws Exception {
mNotificationChannel.setImportance(IMPORTANCE_LOW);
mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
- TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
- false, IMPORTANCE_DEFAULT);
+ TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+ IMPORTANCE_DEFAULT);
- mNotificationInfo.findViewById(R.id.block).performClick();
+ mNotificationInfo.findViewById(R.id.int_block).performClick();
waitForUndoButton();
mNotificationInfo.findViewById(R.id.undo).performClick();
waitForStopButton();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index 93d8aad4e0d6..d99e46d6de12 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -40,7 +40,7 @@ import org.junit.runner.RunWith;
import org.mockito.Mockito;
@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
+@RunWithLooper()
@SmallTest
public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 21047217e942..59a49378e9e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -16,6 +16,7 @@ package com.android.systemui.statusbar.phone;
import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.StatusBarManager;
@@ -63,9 +64,11 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
mContext.putComponent(CommandQueue.class, mCommandQueue);
mDependency.injectTestDependency(ShadeController.class, mShadeController);
+ StatusBarWindowView statusBarWindowView = mock(StatusBarWindowView.class);
+ when(statusBarWindowView.getResources()).thenReturn(mContext.getResources());
mStatusBar = new StatusBarNotificationPresenter(mContext,
mock(NotificationPanelView.class), mock(HeadsUpManagerPhone.class),
- mock(StatusBarWindowView.class), mock(NotificationListContainerViewGroup.class),
+ statusBarWindowView, mock(NotificationListContainerViewGroup.class),
mock(DozeScrimController.class), mock(ScrimController.class),
mock(ActivityLaunchAnimator.Callback.class));
}
diff --git a/packages/overlays/ExperimentNavigationBarDefaultOverlay/Android.mk b/packages/overlays/ExperimentNavigationBarDefaultOverlay/Android.mk
new file mode 100644
index 000000000000..ecad42097738
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarDefaultOverlay/Android.mk
@@ -0,0 +1,30 @@
+#
+# Copyright 2018, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := ExperimentNavigationBarDefault
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := ExperimentNavigationBarDefaultOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE) \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarDefaultOverlay/AndroidManifest.xml b/packages/overlays/ExperimentNavigationBarDefaultOverlay/AndroidManifest.xml
new file mode 100644
index 000000000000..1639fc5fc302
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarDefaultOverlay/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.experiment.navbar.default"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android"
+ android:category="com.android.internal.experiment_navbar_default"
+ android:priority="1"/>
+
+ <application android:label="@string/experiment_navigationbar_overlay" android:hasCode="false"/>
+</manifest> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-as/strings.xml b/packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values/config.xml
index 8cce57046c37..d8b69cde863b 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-as/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values/config.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
/**
* Copyright (c) 2018, The Android Open Source Project
*
@@ -15,9 +15,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"লাহী নেভিগে’শ্বন বাৰ সম্পৰীক্ষা"</string>
-</resources>
+-->
+<resources>
+ <!-- Height of the bottom navigation / system bar frame; navigation buttons height. -->
+ <dimen name="navigation_bar_frame_width">48dp</dimen>
+ <!-- Width of the navigation bar frame when it is placed vertically on the screen -->
+ <dimen name="navigation_bar_frame_height">48dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-gu/strings.xml b/packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values/strings.xml
index 96418aec29bc..c9332903be2e 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-gu/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarDefaultOverlay/res/values/strings.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
/**
* Copyright (c) 2018, The Android Open Source Project
*
@@ -15,9 +15,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"સ્લિમ નૅવિગેશન બારનો પ્રયોગ"</string>
-</resources>
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Name of overlay [CHAR LIMIT=64] -->
+ <string name="experiment_navigationbar_overlay">Default Navigation Bar Experiment (48dp)</string>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml
index b4b2b161ad71..b4cc34f15af7 100644
--- a/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml
@@ -16,7 +16,7 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.internal.experiment.navbar.floating"
+ package="com.android.internal.experiment.navbar.type.floating"
android:versionCode="1"
android:versionName="1.0">
<overlay android:targetPackage="android"
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml
index 6a5845321556..30bca3c00164 100644
--- a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml
@@ -21,8 +21,4 @@
<dimen name="navigation_bar_height">0dp</dimen>
<!-- Width of the navigation bar when it is placed vertically on the screen -->
<dimen name="navigation_bar_width">0dp</dimen>
- <!-- Height of the bottom navigation / system bar frame; navigation buttons height. -->
- <dimen name="navigation_bar_frame_height">48dp</dimen>
- <!-- Width of the navigation bar frame when it is placed vertically on the screen -->
- <dimen name="navigation_bar_frame_width">48dp</dimen>
</resources> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/Android.mk b/packages/overlays/ExperimentNavigationBarSlim24Overlay/Android.mk
index e642a68f1a3a..58cf134fd04d 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/Android.mk
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/Android.mk
@@ -17,14 +17,14 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_RRO_THEME := ExperimentNavigationBarSlim
+LOCAL_RRO_THEME := ExperimentNavigationBarSlim24
LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_PACKAGE_NAME := ExperimentNavigationBarSlimOverlay
+LOCAL_PACKAGE_NAME := ExperimentNavigationBarSlimOverlay24
LOCAL_SDK_VERSION := current
include $(BUILD_RRO_PACKAGE) \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/AndroidManifest.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/AndroidManifest.xml
index a1bd58274fc0..aee543a0b23b 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/AndroidManifest.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/AndroidManifest.xml
@@ -16,11 +16,11 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.internal.experiment.navbar.slim"
+ package="com.android.internal.experiment.navbar.slim24"
android:versionCode="1"
android:versionName="1.0">
<overlay android:targetPackage="android"
- android:category="com.android.internal.experiment_navbar_slim"
+ android:category="com.android.internal.experiment_navbar_slim24"
android:priority="1"/>
<application android:label="@string/experiment_navigationbar_overlay" android:hasCode="false"/>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-af/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-af/strings.xml
index 21a0003bdaa7..21a0003bdaa7 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-af/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-af/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-am/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-am/strings.xml
index 6a7d644ff432..6a7d644ff432 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-am/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-am/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ar/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ar/strings.xml
index 2cebf40c0cba..2cebf40c0cba 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ar/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ar/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-az/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-az/strings.xml
index 266c051abc7d..266c051abc7d 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-az/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-az/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-b+sr+Latn/strings.xml
index dc57a3f6a076..dc57a3f6a076 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-b+sr+Latn/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-b+sr+Latn/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-be/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-be/strings.xml
index 8b53bcdfe9d7..8b53bcdfe9d7 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-be/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-be/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bg/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bg/strings.xml
index 4bf000e193c0..4bf000e193c0 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bg/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bg/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bs/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bs/strings.xml
index 981420945aea..981420945aea 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bs/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-bs/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ca/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ca/strings.xml
index 4a9b598158e6..4a9b598158e6 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ca/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ca/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-cs/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-cs/strings.xml
index d923a3cc4376..d923a3cc4376 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-cs/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-cs/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-da/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-da/strings.xml
index 12bb2f23fe1e..12bb2f23fe1e 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-da/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-da/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-de/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-de/strings.xml
index 960a7d94e7ae..960a7d94e7ae 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-de/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-de/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-el/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-el/strings.xml
index 119b7e611cf9..119b7e611cf9 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-el/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-el/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rAU/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rAU/strings.xml
index 5ebf40348199..5ebf40348199 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rAU/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rAU/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rCA/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rCA/strings.xml
index 5ebf40348199..5ebf40348199 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rCA/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rCA/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rGB/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rGB/strings.xml
index 5ebf40348199..5ebf40348199 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rGB/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rGB/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rIN/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rIN/strings.xml
index 5ebf40348199..5ebf40348199 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rIN/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rIN/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rXC/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml
index 79884ce615cf..79884ce615cf 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-en-rXC/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-en-rXC/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-es-rUS/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es-rUS/strings.xml
index 00b044459777..00b044459777 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-es-rUS/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es-rUS/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-es/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es/strings.xml
index 58bdaa26115b..58bdaa26115b 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-es/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-es/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-et/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-et/strings.xml
index 4c5023cf1d14..4c5023cf1d14 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-et/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-et/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-eu/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-eu/strings.xml
index fc16eeb8dc3e..fc16eeb8dc3e 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-eu/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-eu/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fa/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fa/strings.xml
index e4246d79decb..e4246d79decb 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fa/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fa/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fi/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fi/strings.xml
index 9385a470368f..9385a470368f 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fi/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fi/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr-rCA/strings.xml
index d22848beda3d..d22848beda3d 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fr-rCA/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr-rCA/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr/strings.xml
index cfa1db2a06d3..cfa1db2a06d3 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-fr/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-fr/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-gl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-gl/strings.xml
index d2194ce1a820..d2194ce1a820 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-gl/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-gl/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hi/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hi/strings.xml
index d51cee34f895..d51cee34f895 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hi/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hi/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hr/strings.xml
index 410c58ef2cbc..410c58ef2cbc 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hr/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hr/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hu/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hu/strings.xml
index d7eafed699ab..d7eafed699ab 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hu/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hu/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hy/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hy/strings.xml
index b0200cab636b..b0200cab636b 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-hy/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-hy/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-in/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-in/strings.xml
index 3e0bded06e68..3e0bded06e68 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-in/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-in/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-is/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-is/strings.xml
index 03ccaf3de068..03ccaf3de068 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-is/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-is/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-it/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-it/strings.xml
index f7c5d253e5ab..f7c5d253e5ab 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-it/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-it/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-iw/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-iw/strings.xml
index 0d0ec2c7c2a5..0d0ec2c7c2a5 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-iw/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-iw/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ja/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ja/strings.xml
index a3d6874e84f6..a3d6874e84f6 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ja/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ja/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ka/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ka/strings.xml
index ffddf3bee802..ffddf3bee802 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ka/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ka/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-kk/strings.xml
index f34ac0810127..f34ac0810127 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-kk/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-km/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-km/strings.xml
index 114a78270d79..114a78270d79 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-km/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-km/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ko/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ko/strings.xml
index fca02c3e49bd..fca02c3e49bd 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ko/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ko/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ky/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ky/strings.xml
index 449de4fadfbc..449de4fadfbc 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ky/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ky/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-lo/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lo/strings.xml
index 6ec48ca13d19..6ec48ca13d19 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-lo/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lo/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-lt/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lt/strings.xml
index 1df54aa3fc02..1df54aa3fc02 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-lt/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lt/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-lv/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lv/strings.xml
index 5c6c5658406b..5c6c5658406b 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-lv/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-lv/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-mk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mk/strings.xml
index 3517813f74ad..3517813f74ad 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-mk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mk/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-mn/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mn/strings.xml
index a2282c4c71c9..a2282c4c71c9 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-mn/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mn/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-mr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mr/strings.xml
index c714370cdc7e..c714370cdc7e 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-mr/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-mr/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ms/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ms/strings.xml
index 68f831e39b46..68f831e39b46 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ms/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ms/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-my/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-my/strings.xml
index 84db27962308..84db27962308 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-my/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-my/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-nb/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nb/strings.xml
index e1ff863ac5c8..e1ff863ac5c8 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-nb/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nb/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-nl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nl/strings.xml
index 01190bc624c8..01190bc624c8 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-nl/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-nl/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pl/strings.xml
index 1742aadbcdd3..1742aadbcdd3 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pl/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pl/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rBR/strings.xml
index 22194b7e1ca5..22194b7e1ca5 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pt-rBR/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rBR/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rPT/strings.xml
index f6c030983578..f6c030983578 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pt-rPT/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt-rPT/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pt/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt/strings.xml
index 22194b7e1ca5..22194b7e1ca5 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pt/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-pt/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ro/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ro/strings.xml
index e1655f27b977..e1655f27b977 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ro/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ro/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ru/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ru/strings.xml
index cac66dc921b1..cac66dc921b1 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ru/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
index 6a1ce4128cd9..6a1ce4128cd9 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sk/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sl/strings.xml
index beab7b67f60e..beab7b67f60e 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sl/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sl/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sq/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sq/strings.xml
index b7a28d57391d..b7a28d57391d 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sq/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sq/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sr/strings.xml
index 048f649ddb7b..048f649ddb7b 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sr/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sr/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sv/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sv/strings.xml
index b94438f6971a..b94438f6971a 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sv/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sv/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sw/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sw/strings.xml
index 3a5a73cd0afa..3a5a73cd0afa 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-sw/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-sw/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-th/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-th/strings.xml
index 945297bec53d..945297bec53d 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-th/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-th/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-tl/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tl/strings.xml
index 0c8087c68b8b..0c8087c68b8b 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-tl/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tl/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-tr/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tr/strings.xml
index a3ca75455391..a3ca75455391 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-tr/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-tr/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-uk/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uk/strings.xml
index 656c4a97bd6c..656c4a97bd6c 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-uk/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uk/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ur/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ur/strings.xml
index bcd6bc3f257e..bcd6bc3f257e 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ur/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-ur/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-uz/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uz/strings.xml
index 0d40981784c8..0d40981784c8 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-uz/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-uz/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-vi/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-vi/strings.xml
index dad56b41ae39..dad56b41ae39 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-vi/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-vi/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rCN/strings.xml
index b2602e0e0093..b2602e0e0093 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zh-rCN/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rCN/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rHK/strings.xml
index d5259d38ffa1..d5259d38ffa1 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zh-rHK/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rHK/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rTW/strings.xml
index 6586a573b494..6586a573b494 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zh-rTW/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zh-rTW/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zu/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zu/strings.xml
index 12d04d3b21f6..12d04d3b21f6 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-zu/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values-zu/strings.xml
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/config.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values/config.xml
index 4c3571a1e7d4..58c653d23e44 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/config.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values/config.xml
@@ -18,11 +18,11 @@
-->
<resources>
<!-- Height of the bottom navigation / system bar. -->
- <dimen name="navigation_bar_height">36dp</dimen>
+ <dimen name="navigation_bar_height">24dp</dimen>
<!-- Width of the navigation bar when it is placed vertically on the screen -->
- <dimen name="navigation_bar_width">36dp</dimen>
+ <dimen name="navigation_bar_width">24dp</dimen>
<!-- Height of the bottom navigation / system bar frame; navigation buttons height. -->
- <dimen name="navigation_bar_frame_width">36dp</dimen>
+ <dimen name="navigation_bar_frame_width">24dp</dimen>
<!-- Width of the navigation bar frame when it is placed vertically on the screen -->
- <dimen name="navigation_bar_frame_height">36dp</dimen>
+ <dimen name="navigation_bar_frame_height">24dp</dimen>
</resources> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/strings.xml b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values/strings.xml
index 5ca9d155cb08..670bc5538474 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim24Overlay/res/values/strings.xml
@@ -18,5 +18,5 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Name of overlay [CHAR LIMIT=64] -->
- <string name="experiment_navigationbar_overlay">Slim Navigation Bar Experiment</string>
+ <string name="experiment_navigationbar_overlay">Slim Navigation Bar Experiment (24dp)</string>
</resources> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlim32Overlay/Android.mk b/packages/overlays/ExperimentNavigationBarSlim32Overlay/Android.mk
new file mode 100644
index 000000000000..7ebbb7458922
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlim32Overlay/Android.mk
@@ -0,0 +1,30 @@
+#
+# Copyright 2018, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := ExperimentNavigationBarSlim32
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := ExperimentNavigationBarSlimOverlay32
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE) \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bn/strings.xml b/packages/overlays/ExperimentNavigationBarSlim32Overlay/AndroidManifest.xml
index c0ab3b1b321d..10cf6a15a782 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-bn/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim32Overlay/AndroidManifest.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
+<!--
/**
* Copyright (c) 2018, The Android Open Source Project
*
@@ -15,9 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
- -->
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.experiment.navbar.slim32"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android"
+ android:category="com.android.internal.experiment_navbar_slim32"
+ android:priority="1"/>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"স্লিম নেভিগেশন বার সম্পর্কিত পরীক্ষা"</string>
-</resources>
+ <application android:label="@string/experiment_navigationbar_overlay" android:hasCode="false"/>
+</manifest> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values/config.xml b/packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values/config.xml
new file mode 100644
index 000000000000..00dd8fecbf8c
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_height">32dp</dimen>
+ <!-- Width of the navigation bar when it is placed vertically on the screen -->
+ <dimen name="navigation_bar_width">32dp</dimen>
+ <!-- Height of the bottom navigation / system bar frame; navigation buttons height. -->
+ <dimen name="navigation_bar_frame_width">32dp</dimen>
+ <!-- Width of the navigation bar frame when it is placed vertically on the screen -->
+ <dimen name="navigation_bar_frame_height">32dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-si/strings.xml b/packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values/strings.xml
index a1abb64fbf47..b48661c387ab 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-si/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim32Overlay/res/values/strings.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
/**
* Copyright (c) 2018, The Android Open Source Project
*
@@ -15,9 +15,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"සිහින් සංචාලන තීරු අත්දැකීම"</string>
-</resources>
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Name of overlay [CHAR LIMIT=64] -->
+ <string name="experiment_navigationbar_overlay">Slim Navigation Bar Experiment (32dp)</string>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlim40Overlay/Android.mk b/packages/overlays/ExperimentNavigationBarSlim40Overlay/Android.mk
new file mode 100644
index 000000000000..28354e3a3473
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlim40Overlay/Android.mk
@@ -0,0 +1,30 @@
+#
+# Copyright 2018, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := ExperimentNavigationBarSlim40
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := ExperimentNavigationBarSlimOverlay40
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE) \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlim40Overlay/AndroidManifest.xml b/packages/overlays/ExperimentNavigationBarSlim40Overlay/AndroidManifest.xml
new file mode 100644
index 000000000000..ce8133f3ed40
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlim40Overlay/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.experiment.navbar.slim40"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android"
+ android:category="com.android.internal.experiment_navbar_slim40"
+ android:priority="1"/>
+
+ <application android:label="@string/experiment_navigationbar_overlay" android:hasCode="false"/>
+</manifest> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values/config.xml b/packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values/config.xml
new file mode 100644
index 000000000000..4e65f3399114
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_height">40dp</dimen>
+ <!-- Width of the navigation bar when it is placed vertically on the screen -->
+ <dimen name="navigation_bar_width">40dp</dimen>
+ <!-- Height of the bottom navigation / system bar frame; navigation buttons height. -->
+ <dimen name="navigation_bar_frame_width">40dp</dimen>
+ <!-- Width of the navigation bar frame when it is placed vertically on the screen -->
+ <dimen name="navigation_bar_frame_height">40dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ml/strings.xml b/packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values/strings.xml
index b65afe35950c..8fe3a5c17bba 100644
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ml/strings.xml
+++ b/packages/overlays/ExperimentNavigationBarSlim40Overlay/res/values/strings.xml
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
/**
* Copyright (c) 2018, The Android Open Source Project
*
@@ -15,9 +15,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"സ്ലിം നാവിഗേഷൻ ബാർ പരീക്ഷണം"</string>
-</resources>
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Name of overlay [CHAR LIMIT=64] -->
+ <string name="experiment_navigationbar_overlay">Slim Navigation Bar Experiment (40dp)</string>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kn/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kn/strings.xml
deleted file mode 100644
index ccdddea95afa..000000000000
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-kn/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ಸ್ಲಿಮ್ ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್ ಪ್ರಯೋಗ"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ne/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ne/strings.xml
deleted file mode 100644
index 6022b7f495d4..000000000000
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ne/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"पातलो नेभिगेसन पट्टीको परीक्षण"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-or/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-or/strings.xml
deleted file mode 100644
index 1db9783d4503..000000000000
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-or/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ସ୍ଲିମ୍‍ ନାଭିଗେସନ୍‍ ବାର୍‍‍‍‍‍ର ପ୍ରୟୋଗ"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pa/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pa/strings.xml
deleted file mode 100644
index a782f46b2e23..000000000000
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-pa/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"ਸਲਿਮ ਦਿਸ਼ਾ-ਨਿਰਦੇਸ਼ ਪੱਟੀ ਪ੍ਰਯੋਗ"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ta/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ta/strings.xml
deleted file mode 100644
index 9e95c3872155..000000000000
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-ta/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"மெலிதான வழிசெலுத்துதல் பட்டி சோதனை"</string>
-</resources>
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-te/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-te/strings.xml
deleted file mode 100644
index d273ab744d9b..000000000000
--- a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values-te/strings.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-/**
- * Copyright (c) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="experiment_navigationbar_overlay" msgid="6953777362606036161">"సన్నని నావిగేషన్ పట్టీ ప్రయోగం"</string>
-</resources>
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index 645723e655f8..d1dbbffc6708 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -1,7 +1,5 @@
anniemeng@google.com
-artikz@google.com
brufino@google.com
bryanmawhinney@google.com
ctate@google.com
jorlow@google.com
-mkarpinski@google.com
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 356a4daba66e..8d912fadf6d1 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -692,7 +692,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
});
- if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+ if (!StorageManager.hasIsolatedStorage()) {
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
storageManagerInternal.addExternalStoragePolicy(
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index dd960751ab21..98203213e996 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -56,6 +56,7 @@ public class BinderCallsStatsService extends Binder {
private static final String SETTINGS_DETAILED_TRACKING_KEY = "detailed_tracking";
private static final String SETTINGS_UPLOAD_DATA_KEY = "upload_data";
private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval";
+ private static final String SETTINGS_MAX_CALL_STATS_KEY = "max_call_stats_count";
private boolean mEnabled;
private final Uri mUri = Settings.Global.getUriFor(Settings.Global.BINDER_CALLS_STATS);
@@ -97,6 +98,9 @@ public class BinderCallsStatsService extends Binder {
mBinderCallsStats.setSamplingInterval(mParser.getInt(
SETTINGS_SAMPLING_INTERVAL_KEY,
BinderCallsStats.PERIODIC_SAMPLING_INTERVAL_DEFAULT));
+ mBinderCallsStats.setSamplingInterval(mParser.getInt(
+ SETTINGS_MAX_CALL_STATS_KEY,
+ BinderCallsStats.MAX_BINDER_CALL_STATS_COUNT_DEFAULT));
final boolean enabled =
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index e5275e50e484..cc7bf3373bdd 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -19,7 +19,6 @@ package com.android.server;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.provider.Settings.Global.LOCATION_DISABLE_STATUS_CALLBACKS;
-import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -85,7 +84,6 @@ import com.android.internal.location.ProviderRequest;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Preconditions;
import com.android.server.location.ActivityRecognitionProxy;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
@@ -114,7 +112,6 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
-import java.util.Objects;
import java.util.Set;
/**
@@ -3413,48 +3410,6 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- @Override
- public PendingIntent createManageLocationPermissionIntent(String packageName,
- String permission) {
- Preconditions.checkNotNull(packageName);
- Preconditions.checkArgument(permission.equals(Manifest.permission.ACCESS_FINE_LOCATION)
- || permission.equals(Manifest.permission.ACCESS_COARSE_LOCATION)
- || permission.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION));
-
- int callingUid = Binder.getCallingUid();
- long token = Binder.clearCallingIdentity();
- try {
- String locProvider = getNetworkProviderPackage();
- if (locProvider == null) {
- return null;
- }
-
- PackageInfo locProviderInfo;
- try {
- locProviderInfo = mContext.getPackageManager().getPackageInfo(
- locProvider, PackageManager.MATCH_DIRECT_BOOT_AUTO);
- } catch (NameNotFoundException e) {
- Log.e(TAG, "Could not resolve " + locProvider, e);
- return null;
- }
-
- if (locProviderInfo.applicationInfo.uid != callingUid) {
- throw new SecurityException("Only " + locProvider + " can call this API");
- }
-
- Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
- intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
- intent.putExtra(Intent.EXTRA_PERMISSION_NAME, permission);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- return PendingIntent.getActivity(mContext,
- Objects.hash(packageName, permission), intent,
- PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
private void log(String log) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Slog.d(TAG, log);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 923ac0063baf..e933bd0bc7ff 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -183,8 +183,7 @@ class StorageManagerService extends IStorageManager.Stub
private static final String ZRAM_ENABLED_PROPERTY =
"persist.sys.zram_enabled";
- private static final boolean ENABLE_ISOLATED_STORAGE = SystemProperties
- .getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false);
+ private static final boolean ENABLE_ISOLATED_STORAGE = StorageManager.hasIsolatedStorage();
public static class Lifecycle extends SystemService {
private StorageManagerService mStorageManagerService;
@@ -2686,24 +2685,35 @@ class StorageManagerService extends IStorageManager.Stub
class AppFuseMountScope extends AppFuseBridge.MountScope {
boolean opened = false;
- public AppFuseMountScope(int uid, int pid, int mountId) {
- super(uid, pid, mountId);
+ public AppFuseMountScope(int uid, int mountId) {
+ super(uid, mountId);
}
@Override
public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
try {
return new ParcelFileDescriptor(
- mVold.mountAppFuse(uid, Process.myPid(), mountId));
+ mVold.mountAppFuse(uid, mountId));
} catch (Exception e) {
throw new NativeDaemonConnectorException("Failed to mount", e);
}
}
@Override
+ public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
+ throws NativeDaemonConnectorException {
+ try {
+ return new ParcelFileDescriptor(
+ mVold.openAppFuseFile(uid, mountId, fileId, flags));
+ } catch (Exception e) {
+ throw new NativeDaemonConnectorException("Failed to open", e);
+ }
+ }
+
+ @Override
public void close() throws Exception {
if (opened) {
- mVold.unmountAppFuse(uid, Process.myPid(), mountId);
+ mVold.unmountAppFuse(uid, mountId);
opened = false;
}
}
@@ -2713,7 +2723,6 @@ class StorageManagerService extends IStorageManager.Stub
public @Nullable AppFuseMount mountProxyFileDescriptorBridge() {
Slog.v(TAG, "mountProxyFileDescriptorBridge");
final int uid = Binder.getCallingUid();
- final int pid = Binder.getCallingPid();
while (true) {
synchronized (mAppFuseLock) {
@@ -2727,7 +2736,7 @@ class StorageManagerService extends IStorageManager.Stub
final int name = mNextAppFuseName++;
try {
return new AppFuseMount(
- name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, pid, name)));
+ name, mAppFuseBridge.addBridge(new AppFuseMountScope(uid, name)));
} catch (FuseUnavailableMountException e) {
if (newlyCreated) {
// If newly created bridge fails, it's a real error.
@@ -2748,14 +2757,13 @@ class StorageManagerService extends IStorageManager.Stub
public @Nullable ParcelFileDescriptor openProxyFileDescriptor(
int mountId, int fileId, int mode) {
Slog.v(TAG, "mountProxyFileDescriptor");
- final int pid = Binder.getCallingPid();
try {
synchronized (mAppFuseLock) {
if (mAppFuseBridge == null) {
Slog.e(TAG, "FuseBridge has not been created");
return null;
}
- return mAppFuseBridge.openFile(pid, mountId, fileId, mode);
+ return mAppFuseBridge.openFile(mountId, fileId, mode);
}
} catch (FuseUnavailableMountException | InterruptedException error) {
Slog.v(TAG, "The mount point has already been invalid", error);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b62f648956dd..0e354d515eef 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -328,6 +328,7 @@ import com.android.server.AlarmManagerInternal;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.DeviceIdleController;
+import com.android.server.DisplayThread;
import com.android.server.IntentResolver;
import com.android.server.IoThread;
import com.android.server.LocalServices;
@@ -2262,7 +2263,8 @@ public class ActivityManagerService extends IActivityManager.Stub
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mActivityTaskManager = atm;
- mActivityTaskManager.setActivityManagerService(mIntentFirewall, mPendingIntentController);
+ mActivityTaskManager.initialize(mIntentFirewall, mPendingIntentController,
+ DisplayThread.get().getLooper());
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mProcessCpuThread = new Thread("CpuTracker") {
@@ -18912,7 +18914,6 @@ public class ActivityManagerService extends IActivityManager.Stub
if (memoryStat == null) {
continue;
}
- // TODO(rslawik): Delete RSS high-water mark field.
ProcessMemoryState processMemoryState =
new ProcessMemoryState(uid,
r.processName,
@@ -18922,7 +18923,6 @@ public class ActivityManagerService extends IActivityManager.Stub
memoryStat.rssInBytes,
memoryStat.cacheInBytes,
memoryStat.swapInBytes,
- memoryStat.rssHighWatermarkInBytes,
memoryStat.startTimeNanos);
processMemoryStates.add(processMemoryState);
}
@@ -19348,7 +19348,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public boolean isAppStorageSandboxed(int pid, int uid) {
- if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+ if (!StorageManager.hasIsolatedStorage()) {
return false;
}
if (uid == SHELL_UID || uid == ROOT_UID) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index a0977be0e25d..8c39d75ea6a4 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -58,8 +58,9 @@ import java.util.Set;
/**
* BROADCASTS
*
- * We keep two broadcast queues and associated bookkeeping, one for those at
- * foreground priority, and one for normal (background-priority) broadcasts.
+ * We keep three broadcast queues and associated bookkeeping, one for those at
+ * foreground priority, and one for normal (background-priority) broadcasts, and one to
+ * offload special broadcasts that we know take a long time, such as BOOT_COMPLETED.
*/
public final class BroadcastQueue {
private static final String TAG = "BroadcastQueue";
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index cc3da1c63c00..90fe30c7c718 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -49,13 +49,8 @@ public final class MemoryStatUtil {
private static final boolean DEVICE_HAS_PER_APP_MEMCG =
SystemProperties.getBoolean("ro.config.per_app_memcg", false);
- /** Path to check if device has memcg */
- private static final String MEMCG_TEST_PATH = "/dev/memcg/apps/memory.stat";
/** Path to memory stat file for logging app start memory state */
private static final String MEMORY_STAT_FILE_FMT = "/dev/memcg/apps/uid_%d/pid_%d/memory.stat";
- /** Path to memory max usage file for logging app memory state */
- private static final String MEMORY_MAX_USAGE_FILE_FMT =
- "/dev/memcg/apps/uid_%d/pid_%d/memory.max_usage_in_bytes";
/** Path to procfs stat file for logging app start memory state */
private static final String PROC_STAT_FILE_FMT = "/proc/%d/stat";
/** Path to procfs status file for logging app memory state */
@@ -98,14 +93,7 @@ public final class MemoryStatUtil {
@Nullable
static MemoryStat readMemoryStatFromMemcg(int uid, int pid) {
final String statPath = String.format(Locale.US, MEMORY_STAT_FILE_FMT, uid, pid);
- MemoryStat stat = parseMemoryStatFromMemcg(readFileContents(statPath));
- if (stat == null) {
- return null;
- }
- String maxUsagePath = String.format(Locale.US, MEMORY_MAX_USAGE_FILE_FMT, uid, pid);
- stat.rssHighWatermarkInBytes = parseMemoryMaxUsageFromMemCg(
- readFileContents(maxUsagePath));
- return stat;
+ return parseMemoryStatFromMemcg(readFileContents(statPath));
}
/**
@@ -116,12 +104,7 @@ public final class MemoryStatUtil {
@Nullable
public static MemoryStat readMemoryStatFromProcfs(int pid) {
final String statPath = String.format(Locale.US, PROC_STAT_FILE_FMT, pid);
- MemoryStat stat = parseMemoryStatFromProcfs(readFileContents(statPath));
- if (stat == null) {
- return null;
- }
- stat.rssHighWatermarkInBytes = readRssHighWaterMarkFromProcfs(pid);
- return stat;
+ return parseMemoryStatFromProcfs(readFileContents(statPath));
}
/**
@@ -185,19 +168,6 @@ public final class MemoryStatUtil {
return memoryStat;
}
- @VisibleForTesting
- static long parseMemoryMaxUsageFromMemCg(String memoryMaxUsageContents) {
- if (memoryMaxUsageContents == null || memoryMaxUsageContents.isEmpty()) {
- return 0;
- }
- try {
- return Long.parseLong(memoryMaxUsageContents);
- } catch (NumberFormatException e) {
- Slog.e(TAG, "Failed to parse value", e);
- return 0;
- }
- }
-
/**
* Parses relevant statistics out from the contents of the /proc/pid/stat file in procfs.
*/
@@ -258,8 +228,6 @@ public final class MemoryStatUtil {
public long cacheInBytes;
/** Number of bytes of swap usage */
public long swapInBytes;
- /** Number of bytes of peak anonymous and swap cache memory */
- public long rssHighWatermarkInBytes;
/** Device time when the processes started. */
public long startTimeNanos;
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 4b19398cc73d..7991783e08c8 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -27,7 +27,6 @@ import static android.os.Process.getFreeMemory;
import static android.os.Process.getTotalMemory;
import static android.os.Process.killProcessQuiet;
import static android.os.Process.startWebView;
-import static android.os.storage.StorageManager.PROP_ISOLATED_STORAGE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
@@ -73,6 +72,7 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
import android.text.TextUtils;
import android.util.EventLog;
@@ -1281,8 +1281,7 @@ public final class ProcessList {
final IPackageManager pm = AppGlobals.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName,
MATCH_DIRECT_BOOT_AUTO, app.userId);
- if (SystemProperties.getBoolean(PROP_ISOLATED_STORAGE, false)
- && mountExtStorageFull) {
+ if (StorageManager.hasIsolatedStorage() && mountExtStorageFull) {
mountExternal = Zygote.MOUNT_EXTERNAL_FULL;
} else {
StorageManagerInternal storageManagerInternal = LocalServices.getService(
diff --git a/services/core/java/com/android/server/biometrics/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
index 2c2d4045b205..eaa7a83fab0d 100644
--- a/services/core/java/com/android/server/biometrics/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/AuthenticationClient.java
@@ -19,19 +19,11 @@ package com.android.server.biometrics;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.BiometricPrompt;
-import android.hardware.biometrics.IBiometricPromptReceiver;
-import android.os.Bundle;
-import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.RemoteException;
import android.security.KeyStore;
-import android.text.TextUtils;
import android.util.Slog;
-import com.android.internal.statusbar.IStatusBarService;
-
import java.util.ArrayList;
/**
@@ -39,88 +31,15 @@ import java.util.ArrayList;
*/
public abstract class AuthenticationClient extends ClientMonitor {
private long mOpId;
- private Handler mHandler;
public abstract int handleFailedAttempt();
public abstract void resetFailedAttempts();
- public abstract String getErrorString(int error, int vendorCode);
- public abstract String getAcquiredString(int acquireInfo, int vendorCode);
- /**
- * @return one of {@link #TYPE_FINGERPRINT} {@link #TYPE_IRIS} or {@link #TYPE_FACE}
- */
- public abstract int getBiometricType();
public static final int LOCKOUT_NONE = 0;
public static final int LOCKOUT_TIMED = 1;
public static final int LOCKOUT_PERMANENT = 2;
private final boolean mRequireConfirmation;
- // Callback mechanism received from the client
- // (BiometricPrompt -> BiometricPromptService -> <Biometric>Service -> AuthenticationClient)
- private IBiometricPromptReceiver mDialogReceiverFromClient;
- private Bundle mBundle;
- private IStatusBarService mStatusBarService;
- private boolean mInLockout;
- private TokenEscrow mEscrow;
- protected boolean mDialogDismissed;
-
- /**
- * Container that holds the identifier and authToken. For biometrics that require user
- * confirmation, these should not be sent to their final destinations until the user confirms.
- */
- class TokenEscrow {
- final BiometricAuthenticator.Identifier mIdentifier;
- final ArrayList<Byte> mToken;
-
- TokenEscrow(BiometricAuthenticator.Identifier identifier, ArrayList<Byte> token) {
- mIdentifier = identifier;
- mToken = token;
- }
-
- BiometricAuthenticator.Identifier getIdentifier() {
- return mIdentifier;
- }
-
- ArrayList<Byte> getToken() {
- return mToken;
- }
- }
-
- // Receives events from SystemUI and handles them before forwarding them to BiometricDialog
- protected IBiometricPromptReceiver mDialogReceiver = new IBiometricPromptReceiver.Stub() {
- @Override // binder call
- public void onDialogDismissed(int reason) {
- if (mBundle != null && mDialogReceiverFromClient != null) {
- try {
- if (reason != BiometricPrompt.DISMISSED_REASON_POSITIVE) {
- // Positive button is used by passive modalities as a "confirm" button,
- // do not send to client
- mDialogReceiverFromClient.onDialogDismissed(reason);
- }
- if (reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL) {
- onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
- 0 /* vendorCode */);
- } else if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) {
- // Have the service send the token to KeyStore, and send onAuthenticated
- // to the application.
- if (mEscrow != null) {
- if (DEBUG) Slog.d(getLogTag(), "Confirmed");
- addTokenToKeyStore(mEscrow.getToken());
- notifyClientAuthenticationSucceeded(mEscrow.getIdentifier());
- mEscrow = null;
- onAuthenticationConfirmed();
- } else {
- Slog.e(getLogTag(), "Escrow is null!!!");
- }
- }
- mDialogDismissed = true;
- } catch (RemoteException e) {
- Slog.e(getLogTag(), "Remote exception", e);
- }
- stop(true /* initiatedByClient */);
- }
- }
- };
/**
* This method is called when authentication starts.
@@ -133,25 +52,13 @@ public abstract class AuthenticationClient extends ClientMonitor {
*/
public abstract void onStop();
- /**
- * This method is called when biometric authentication was confirmed by the user. The client
- * should be removed.
- */
- public abstract void onAuthenticationConfirmed();
-
public AuthenticationClient(Context context, Metrics metrics,
BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token,
BiometricServiceBase.ServiceListener listener, int targetUserId, int groupId, long opId,
- boolean restricted, String owner, Bundle bundle,
- IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService,
- boolean requireConfirmation) {
+ boolean restricted, String owner, int cookie, boolean requireConfirmation) {
super(context, metrics, daemon, halDeviceId, token, listener, targetUserId, groupId,
- restricted, owner);
+ restricted, owner, cookie);
mOpId = opId;
- mBundle = bundle;
- mDialogReceiverFromClient = dialogReceiver;
- mStatusBarService = statusBarService;
- mHandler = new Handler(Looper.getMainLooper());
mRequireConfirmation = requireConfirmation;
}
@@ -164,175 +71,99 @@ public abstract class AuthenticationClient extends ClientMonitor {
stop(false /* initiatedByClient */);
}
- @Override
- public boolean onAcquired(int acquiredInfo, int vendorCode) {
- // If the dialog is showing, the client doesn't need to receive onAcquired messages.
- if (mBundle != null) {
- try {
- if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
- mStatusBarService.onBiometricHelp(getAcquiredString(acquiredInfo, vendorCode));
- }
- return false; // acquisition continues
- } catch (RemoteException e) {
- Slog.e(getLogTag(), "Remote exception when sending acquired message", e);
- return true; // client failed
- } finally {
- // Good scans will keep the device awake
- if (acquiredInfo == BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
- notifyUserActivity();
- }
- }
- } else {
- return super.onAcquired(acquiredInfo, vendorCode);
- }
- }
-
- @Override
- public boolean onError(long deviceId, int error, int vendorCode) {
- if (mDialogDismissed) {
- // If user cancels authentication, the application has already received the
- // ERROR_USER_CANCELED message from onDialogDismissed()
- // and stopped the biometric hardware, so there is no need to send a
- // ERROR_CANCELED message.
- return true;
- }
- if (mBundle != null && error != BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED) {
- try {
- mStatusBarService.onBiometricError(getErrorString(error, vendorCode));
- } catch (RemoteException e) {
- Slog.e(getLogTag(), "Remote exception when sending error", e);
- }
- }
- return super.onError(deviceId, error, vendorCode);
- }
-
- public void setTitleIfEmpty(CharSequence title) {
- if (TextUtils.isEmpty(mBundle.getCharSequence(BiometricPrompt.KEY_TITLE))) {
- mBundle.putCharSequence(BiometricPrompt.KEY_TITLE, title);
- }
- }
-
public boolean isBiometricPrompt() {
- return mBundle != null;
- }
-
- private void notifyClientAuthenticationSucceeded(BiometricAuthenticator.Identifier identifier)
- throws RemoteException {
- final BiometricServiceBase.ServiceListener listener = getListener();
- // Explicitly have if/else here to make it super obvious in case the code is
- // touched in the future.
- if (!getIsRestricted()) {
- listener.onAuthenticationSucceeded(
- getHalDeviceId(), identifier, getTargetUserId());
- } else {
- listener.onAuthenticationSucceeded(
- getHalDeviceId(), null, getTargetUserId());
- }
+ return getCookie() != 0;
}
- private void addTokenToKeyStore(ArrayList<Byte> token) {
- // Send the token to KeyStore
- final byte[] byteToken = new byte[token.size()];
- for (int i = 0; i < token.size(); i++) {
- byteToken[i] = token.get(i);
- }
- KeyStore.getInstance().addAuthToken(byteToken);
+ public boolean getRequireConfirmation() {
+ return mRequireConfirmation;
}
@Override
public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
boolean authenticated, ArrayList<Byte> token) {
- if (authenticated) {
- mAlreadyDone = true;
- if (mRequireConfirmation) {
- // Store the token so it can be sent to keystore after the user presses confirm
- mEscrow = new TokenEscrow(identifier, token);
- } else {
- addTokenToKeyStore(token);
- }
- }
+ final BiometricServiceBase.ServiceListener listener = getListener();
+ mMetricsLogger.action(mMetrics.actionBiometricAuth(), authenticated);
boolean result = false;
- // If the biometric dialog is showing, notify authentication succeeded
- if (mBundle != null) {
- try {
- if (authenticated) {
- mStatusBarService.onBiometricAuthenticated();
- } else {
- mStatusBarService.onBiometricHelp(getContext().getResources().getString(
- com.android.internal.R.string.biometric_not_recognized));
+ try {
+ if (authenticated) {
+ mAlreadyDone = true;
+ if (DEBUG) Slog.v(getLogTag(), "onAuthenticated(" + getOwnerString()
+ + ", ID:" + identifier.getBiometricId()
+ + ", isBP: " + isBiometricPrompt()
+ + ", listener: " + listener
+ + ", requireConfirmation: " + mRequireConfirmation);
+ if (listener != null) {
+ vibrateSuccess();
}
- } catch (RemoteException e) {
- Slog.e(getLogTag(), "Failed to notify Authenticated:", e);
- }
- }
+ result = true;
+ resetFailedAttempts();
+ onStop();
- final BiometricServiceBase.ServiceListener listener = getListener();
- if (listener != null) {
- try {
- mMetricsLogger.action(mMetrics.actionBiometricAuth(), authenticated);
- if (!authenticated) {
- listener.onAuthenticationFailed(getHalDeviceId());
- } else {
- if (DEBUG) {
- Slog.v(getLogTag(), "onAuthenticated(owner=" + getOwnerString()
- + ", id=" + identifier.getBiometricId());
- }
- if (!mRequireConfirmation) {
- notifyClientAuthenticationSucceeded(identifier);
+ final byte[] byteToken = new byte[token.size()];
+ for (int i = 0; i < token.size(); i++) {
+ byteToken[i] = token.get(i);
+ }
+ if (isBiometricPrompt() && listener != null) {
+ // BiometricService will add the token to keystore
+ listener.onAuthenticationSucceededInternal(mRequireConfirmation, byteToken);
+ } else if (!isBiometricPrompt() && listener != null) {
+ KeyStore.getInstance().addAuthToken(byteToken);
+ try {
+ // Explicitly have if/else here to make it super obvious in case the code is
+ // touched in the future.
+ if (!getIsRestricted()) {
+ listener.onAuthenticationSucceeded(
+ getHalDeviceId(), identifier, getTargetUserId());
+ } else {
+ listener.onAuthenticationSucceeded(
+ getHalDeviceId(), null, getTargetUserId());
+ }
+ } catch (RemoteException e) {
+ Slog.e(getLogTag(), "Remote exception", e);
}
+ } else {
+ // Client not listening
+ Slog.w(getLogTag(), "Client not listening");
+ result = true;
}
- } catch (RemoteException e) {
- Slog.w(getLogTag(), "Failed to notify Authenticated:", e);
- result = true; // client failed
- }
- } else {
- result = true; // client not listening
- }
- if (!authenticated) {
- if (listener != null) {
- vibrateError();
- }
- // allow system-defined limit of number of attempts before giving up
- int lockoutMode = handleFailedAttempt();
- if (lockoutMode != LOCKOUT_NONE) {
- try {
- mInLockout = true;
- Slog.w(getLogTag(), "Forcing lockout (fp driver code should do this!), mode(" +
- lockoutMode + ")");
+ } else {
+ if (listener != null) {
+ vibrateError();
+ }
+ // Allow system-defined limit of number of attempts before giving up
+ final int lockoutMode = handleFailedAttempt();
+ if (lockoutMode != LOCKOUT_NONE) {
+ Slog.w(getLogTag(), "Forcing lockout (driver code should do this!), mode("
+ + lockoutMode + ")");
stop(false);
- int errorCode = lockoutMode == LOCKOUT_TIMED ?
- BiometricConstants.BIOMETRIC_ERROR_LOCKOUT :
- BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
-
- // Send the lockout message to the system dialog
- if (mBundle != null) {
- mStatusBarService.onBiometricError(
- getErrorString(errorCode, 0 /* vendorCode */));
- mHandler.postDelayed(() -> {
- try {
- listener.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
- } catch (RemoteException e) {
- Slog.w(getLogTag(), "RemoteException while sending error");
- }
- }, BiometricPrompt.HIDE_DIALOG_DELAY);
- } else {
- listener.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
+ final int errorCode = lockoutMode == LOCKOUT_TIMED
+ ? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT
+ : BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
+ if (listener != null) {
+ listener.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */,
+ getCookie());
+ }
+ } else {
+ // Don't send onAuthenticationFailed if we're in lockout, it causes a
+ // janky UI on Keyguard/BiometricPrompt since "authentication failed"
+ // will show briefly and be replaced by "device locked out" message.
+ if (listener != null) {
+ if (isBiometricPrompt()) {
+ listener.onAuthenticationFailedInternal(getCookie(),
+ getRequireConfirmation());
+ } else {
+ listener.onAuthenticationFailed(getHalDeviceId());
+ }
}
- } catch (RemoteException e) {
- Slog.w(getLogTag(), "Failed to notify lockout:", e);
}
+ result |= lockoutMode != LOCKOUT_NONE; // in a lockout mode
}
- result |= lockoutMode != LOCKOUT_NONE; // in a lockout mode
- } else {
- if (listener != null) {
- vibrateSuccess();
- }
- // we have a valid biometric that doesn't require confirmation, done
- result |= !mRequireConfirmation;
- resetFailedAttempts();
- onStop();
+ } catch (RemoteException e) {
+ Slog.e(getLogTag(), "Remote exception", e);
+ result = true;
}
return result;
}
@@ -353,16 +184,6 @@ public abstract class AuthenticationClient extends ClientMonitor {
return result;
}
if (DEBUG) Slog.w(getLogTag(), "client " + getOwnerString() + " is authenticating...");
-
- // If authenticating with system dialog, show the dialog
- if (mBundle != null) {
- try {
- mStatusBarService.showBiometricDialog(mBundle, mDialogReceiver,
- getBiometricType(), mRequireConfirmation, getTargetUserId());
- } catch (RemoteException e) {
- Slog.e(getLogTag(), "Unable to show biometric dialog", e);
- }
- }
} catch (RemoteException e) {
Slog.e(getLogTag(), "startAuthentication failed", e);
return ERROR_ESRCH;
@@ -390,18 +211,6 @@ public abstract class AuthenticationClient extends ClientMonitor {
} catch (RemoteException e) {
Slog.e(getLogTag(), "stopAuthentication failed", e);
return ERROR_ESRCH;
- } finally {
- // If the user already cancelled authentication (via some interaction with the
- // dialog, we do not need to hide it since it's already hidden.
- // If the device is in lockout, don't hide the dialog - it will automatically hide
- // after BiometricPrompt.HIDE_DIALOG_DELAY
- if (mBundle != null && !mDialogDismissed && !mInLockout) {
- try {
- mStatusBarService.hideBiometricDialog();
- } catch (RemoteException e) {
- Slog.e(getLogTag(), "Unable to hide biometric dialog", e);
- }
- }
}
mAlreadyCancelled = true;
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 5f09189bd84a..add55eaad166 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -19,9 +19,17 @@ package com.android.server.biometrics;
import static android.Manifest.permission.USE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.Manifest.permission.USE_FINGERPRINT;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
+import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE;
import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
+import android.app.IActivityTaskManager;
+import android.app.TaskStackListener;
import android.app.UserSwitchObserver;
import android.content.ContentResolver;
import android.content.Context;
@@ -32,9 +40,9 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
-import android.hardware.biometrics.IBiometricPromptReceiver;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.IBiometricServiceReceiver;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.face.FaceManager;
import android.hardware.face.IFaceService;
import android.hardware.fingerprint.FingerprintManager;
@@ -50,14 +58,21 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.provider.Settings;
+import android.security.KeyStore;
+import android.text.TextUtils;
import android.util.Pair;
import android.util.Slog;
import com.android.internal.R;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.server.SystemService;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Random;
/**
* System service that arbitrates the modality for BiometricPrompt to use.
@@ -66,32 +81,10 @@ public class BiometricService extends SystemService {
private static final String TAG = "BiometricService";
- /**
- * No biometric methods or nothing has been enrolled.
- * Move/expose these in BiometricPrompt if we ever want to allow applications to "blacklist"
- * modalities when calling authenticate().
- */
- private static final int BIOMETRIC_NONE = 0;
-
- /**
- * Constant representing fingerprint.
- */
- private static final int BIOMETRIC_FINGERPRINT = 1 << 0;
-
- /**
- * Constant representing iris.
- */
- private static final int BIOMETRIC_IRIS = 1 << 1;
-
- /**
- * Constant representing face.
- */
- private static final int BIOMETRIC_FACE = 1 << 2;
-
private static final int[] FEATURE_ID = {
- BIOMETRIC_FINGERPRINT,
- BIOMETRIC_IRIS,
- BIOMETRIC_FACE
+ TYPE_FINGERPRINT,
+ TYPE_IRIS,
+ TYPE_FACE
};
private final AppOpsManager mAppOps;
@@ -242,10 +235,367 @@ public class BiometricService extends SystemService {
*/
private final class BiometricServiceWrapper extends IBiometricService.Stub {
+ /**
+ * Authentication either just called and we have not transitioned to the CALLED state, or
+ * authentication terminated (success or error).
+ */
+ private static final int STATE_AUTH_IDLE = 0;
+ /**
+ * Authentication was called and we are waiting for the <Biometric>Services to return their
+ * cookies before starting the hardware and showing the BiometricPrompt.
+ */
+ private static final int STATE_AUTH_CALLED = 1;
+ /**
+ * Authentication started, BiometricPrompt is showing and the hardware is authenticating.
+ */
+ private static final int STATE_AUTH_STARTED = 2;
+ /**
+ * Authentication is paused, waiting for the user to press "try again" button. Since the
+ * try again button requires us to cancel authentication, this represents the state where
+ * ERROR_CANCELED is not received yet.
+ */
+ private static final int STATE_AUTH_PAUSED = 3;
+ /**
+ * Same as above, except the ERROR_CANCELED has been received.
+ */
+ private static final int STATE_AUTH_PAUSED_CANCELED = 4;
+ /**
+ * Authentication is successful, but we're waiting for the user to press "confirm" button.
+ */
+ private static final int STATE_AUTH_PENDING_CONFIRM = 5;
+
+ final class AuthSession {
+ // Map of Authenticator/Cookie pairs. We expect to receive the cookies back from
+ // <Biometric>Services before we can start authenticating. Pairs that have been returned
+ // are moved to mModalitiesMatched.
+ final HashMap<Integer, Integer> mModalitiesWaiting;
+ // Pairs that have been matched.
+ final HashMap<Integer, Integer> mModalitiesMatched = new HashMap<>();
+
+ // The following variables are passed to authenticateInternal, which initiates the
+ // appropriate <Biometric>Services.
+ final IBinder mToken;
+ final long mSessionId;
+ final int mUserId;
+ // Original receiver from BiometricPrompt.
+ final IBiometricServiceReceiver mClientReceiver;
+ final String mOpPackageName;
+ // Info to be shown on BiometricDialog when all cookies are returned.
+ final Bundle mBundle;
+ final int mCallingUid;
+ final int mCallingPid;
+ final int mCallingUserId;
+ // Continue authentication with the same modality/modalities after "try again" is
+ // pressed
+ final int mModality;
+
+ // The current state, which can be either idle, called, or started
+ private int mState = STATE_AUTH_IDLE;
+ // For explicit confirmation, do not send to keystore until the user has confirmed
+ // the authentication.
+ byte[] mTokenEscrow;
+
+ AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId,
+ int userId, IBiometricServiceReceiver receiver, String opPackageName,
+ Bundle bundle, int callingUid, int callingPid, int callingUserId,
+ int modality) {
+ mModalitiesWaiting = modalities;
+ mToken = token;
+ mSessionId = sessionId;
+ mUserId = userId;
+ mClientReceiver = receiver;
+ mOpPackageName = opPackageName;
+ mBundle = bundle;
+ mCallingUid = callingUid;
+ mCallingPid = callingPid;
+ mCallingUserId = callingUserId;
+ mModality = modality;
+ }
+
+ boolean containsCookie(int cookie) {
+ if (mModalitiesWaiting != null && mModalitiesWaiting.containsValue(cookie)) {
+ return true;
+ }
+ if (mModalitiesMatched != null && mModalitiesMatched.containsValue(cookie)) {
+ return true;
+ }
+ return false;
+ }
+ }
+
+ final class BiometricTaskStackListener extends TaskStackListener {
+ @Override
+ public void onTaskStackChanged() {
+ try {
+ final List<ActivityManager.RunningTaskInfo> runningTasks =
+ mActivityTaskManager.getTasks(1);
+ if (!runningTasks.isEmpty()) {
+ final String topPackage = runningTasks.get(0).topActivity.getPackageName();
+ if (mCurrentAuthSession != null
+ && !topPackage.contentEquals(mCurrentAuthSession.mOpPackageName)
+ && mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
+ // We only care about this state, since <Biometric>Service will
+ // cancel any client that's still in STATE_AUTH_STARTED
+ mStatusBarService.hideBiometricDialog();
+ mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+ mCurrentAuthSession.mClientReceiver.onError(
+ BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+ getContext().getString(
+ com.android.internal.R.string.biometric_error_canceled)
+ );
+ mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+ mCurrentAuthSession = null;
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to get running tasks", e);
+ }
+ }
+ }
+
+ private final IActivityTaskManager mActivityTaskManager = getContext().getSystemService(
+ ActivityTaskManager.class).getService();
+ private final IStatusBarService mStatusBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ private final BiometricTaskStackListener mTaskStackListener =
+ new BiometricTaskStackListener();
+ private final Random mRandom = new Random();
+
+ // The current authentication session, null if idle/done. We need to track both the current
+ // and pending sessions since errors may be sent to either.
+ private AuthSession mCurrentAuthSession;
+ private AuthSession mPendingAuthSession;
+
+ // Wrap the client's receiver so we can do things with the BiometricDialog first
+ private final IBiometricServiceReceiverInternal mInternalReceiver =
+ new IBiometricServiceReceiverInternal.Stub() {
+ @Override
+ public void onAuthenticationSucceeded(boolean requireConfirmation, byte[] token)
+ throws RemoteException {
+ try {
+ if (!requireConfirmation) {
+ mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+ KeyStore.getInstance().addAuthToken(token);
+ mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
+ mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+ mCurrentAuthSession = null;
+ } else {
+ // Store the auth token and submit it to keystore after the confirmation
+ // button has been pressed.
+ mCurrentAuthSession.mTokenEscrow = token;
+ mCurrentAuthSession.mState = STATE_AUTH_PENDING_CONFIRM;
+ }
+
+ // Notify SysUI that the biometric has been authenticated. SysUI already knows
+ // the implicit/explicit state and will react accordingly.
+ mStatusBarService.onBiometricAuthenticated();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
+ }
+
+ @Override
+ public void onAuthenticationFailed(int cookie, boolean requireConfirmation)
+ throws RemoteException {
+ try {
+ mStatusBarService.onBiometricHelp(getContext().getResources().getString(
+ com.android.internal.R.string.biometric_not_recognized));
+ if (requireConfirmation) {
+ mCurrentAuthSession.mState = STATE_AUTH_PAUSED;
+ mStatusBarService.showBiometricTryAgain();
+ // Cancel authentication. Skip the token/package check since we are
+ // cancelling from system server. The interface is permission protected so
+ // this is fine.
+ cancelInternal(null /* token */, null /* package */,
+ false /* fromClient */);
+ }
+ mCurrentAuthSession.mClientReceiver.onAuthenticationFailed();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
+ }
+
+ @Override
+ public void onError(int cookie, int error, String message) throws RemoteException {
+ Slog.d(TAG, "Error: " + error + " cookie: " + cookie);
+ // Errors can either be from the current auth session or the pending auth session.
+ // The pending auth session may receive errors such as ERROR_LOCKOUT before
+ // it becomes the current auth session. Similarly, the current auth session may
+ // receive errors such as ERROR_CANCELED while the pending auth session is preparing
+ // to be started. Thus we must match error messages with their cookies to be sure
+ // of their intended receivers.
+ try {
+ if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) {
+ if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
+ mStatusBarService.onBiometricError(message);
+ mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+ if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
+ mCurrentAuthSession.mClientReceiver.onError(error, message);
+ mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+ mCurrentAuthSession = null;
+ mStatusBarService.hideBiometricDialog();
+ } else {
+ // Send errors after the dialog is dismissed.
+ mHandler.postDelayed(() -> {
+ try {
+ mCurrentAuthSession.mClientReceiver.onError(error, message);
+ mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+ mCurrentAuthSession = null;
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
+ }, BiometricPrompt.HIDE_DIALOG_DELAY);
+ }
+ } else if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED
+ || mCurrentAuthSession.mState == STATE_AUTH_PAUSED_CANCELED) {
+ if (mCurrentAuthSession.mState == STATE_AUTH_PAUSED
+ && error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
+ // Skip the first ERROR_CANCELED message when this happens, since
+ // "try again" requires us to cancel authentication but keep
+ // the prompt showing.
+ mCurrentAuthSession.mState = STATE_AUTH_PAUSED_CANCELED;
+ } else {
+ // In the "try again" state, we should forward canceled errors to
+ // the client and and clean up.
+ mCurrentAuthSession.mClientReceiver.onError(error, message);
+ mStatusBarService.onBiometricError(message);
+ mActivityTaskManager.unregisterTaskStackListener(
+ mTaskStackListener);
+ mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+ mCurrentAuthSession = null;
+ }
+ } else {
+ Slog.e(TAG, "Impossible session error state: "
+ + mCurrentAuthSession.mState);
+ }
+ } else if (mPendingAuthSession != null
+ && mPendingAuthSession.containsCookie(cookie)) {
+ if (mPendingAuthSession.mState == STATE_AUTH_CALLED) {
+ mPendingAuthSession.mClientReceiver.onError(error, message);
+ mPendingAuthSession.mState = STATE_AUTH_IDLE;
+ mPendingAuthSession = null;
+ } else {
+ Slog.e(TAG, "Impossible pending session error state: "
+ + mPendingAuthSession.mState);
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
+ }
+
+ @Override
+ public void onAcquired(int acquiredInfo, String message) throws RemoteException {
+ if (acquiredInfo != BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
+ try {
+ mStatusBarService.onBiometricHelp(message);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
+ }
+ }
+
+ @Override
+ public void onDialogDismissed(int reason) throws RemoteException {
+ if (reason != BiometricPrompt.DISMISSED_REASON_POSITIVE) {
+ // Positive button is used by passive modalities as a "confirm" button,
+ // do not send to client
+ mCurrentAuthSession.mClientReceiver.onDialogDismissed(reason);
+ // Cancel authentication. Skip the token/package check since we are cancelling
+ // from system server. The interface is permission protected so this is fine.
+ cancelInternal(null /* token */, null /* package */, false /* fromClient */);
+ }
+ if (reason == BiometricPrompt.DISMISSED_REASON_USER_CANCEL) {
+ mCurrentAuthSession.mClientReceiver.onError(
+ BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED,
+ getContext().getString(
+ com.android.internal.R.string.biometric_error_user_canceled));
+ } else if (reason == BiometricPrompt.DISMISSED_REASON_POSITIVE) {
+ // Have the service send the token to KeyStore, and send onAuthenticated
+ // to the application
+ KeyStore.getInstance().addAuthToken(mCurrentAuthSession.mTokenEscrow);
+ mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
+ }
+ mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+ mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+ mCurrentAuthSession = null;
+ }
+
+ @Override
+ public void onTryAgainPressed() {
+ Slog.d(TAG, "onTryAgainPressed");
+ // No need to check permission, since it can only be invoked by SystemUI
+ // (or system server itself).
+ mHandler.post(() -> {
+ authenticateInternal(mCurrentAuthSession.mToken,
+ mCurrentAuthSession.mSessionId,
+ mCurrentAuthSession.mUserId,
+ mCurrentAuthSession.mClientReceiver,
+ mCurrentAuthSession.mOpPackageName,
+ mCurrentAuthSession.mBundle,
+ mCurrentAuthSession.mCallingUid,
+ mCurrentAuthSession.mCallingPid,
+ mCurrentAuthSession.mCallingUserId,
+ mCurrentAuthSession.mModality);
+ });
+ }
+ };
+
+ @Override // Binder call
+ public void onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId) {
+ checkInternalPermission();
+
+ Iterator it = mPendingAuthSession.mModalitiesWaiting.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
+ if (pair.getValue() == cookie) {
+ mPendingAuthSession.mModalitiesMatched.put(pair.getKey(), pair.getValue());
+ mPendingAuthSession.mModalitiesWaiting.remove(pair.getKey());
+ Slog.d(TAG, "Matched cookie: " + cookie + ", "
+ + mPendingAuthSession.mModalitiesWaiting.size() + " remaining");
+ break;
+ }
+ }
+
+ if (mPendingAuthSession.mModalitiesWaiting.isEmpty()) {
+ final boolean mContinuing = mCurrentAuthSession != null
+ && mCurrentAuthSession.mState == STATE_AUTH_PAUSED;
+ mCurrentAuthSession = mPendingAuthSession;
+ mPendingAuthSession = null;
+
+ mCurrentAuthSession.mState = STATE_AUTH_STARTED;
+ try {
+ int modality = TYPE_NONE;
+ it = mCurrentAuthSession.mModalitiesMatched.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<Integer, Integer> pair = (Map.Entry) it.next();
+ if (pair.getKey() == TYPE_FINGERPRINT) {
+ mFingerprintService.startPreparedClient(pair.getValue());
+ } else if (pair.getKey() == TYPE_IRIS) {
+ Slog.e(TAG, "Iris unsupported");
+ } else if (pair.getKey() == TYPE_FACE) {
+ mFaceService.startPreparedClient(pair.getValue());
+ } else {
+ Slog.e(TAG, "Unknown modality: " + pair.getKey());
+ }
+ modality |= pair.getKey();
+ }
+
+ if (!mContinuing) {
+ mStatusBarService.showBiometricDialog(mCurrentAuthSession.mBundle,
+ mInternalReceiver, modality, requireConfirmation, userId);
+ mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
+ }
+ }
+
@Override // Binder call
public void authenticate(IBinder token, long sessionId, int userId,
- IBiometricServiceReceiver receiver, int flags, String opPackageName,
- Bundle bundle, IBiometricPromptReceiver dialogReceiver) throws RemoteException {
+ IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle)
+ throws RemoteException {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
@@ -261,16 +611,45 @@ public class BiometricService extends SystemService {
checkInternalPermission();
}
- if (token == null || receiver == null || opPackageName == null || bundle == null
- || dialogReceiver == null) {
+ if (token == null || receiver == null || opPackageName == null || bundle == null) {
Slog.e(TAG, "Unable to authenticate, one or more null arguments");
return;
}
// Check the usage of this in system server. Need to remove this check if it becomes
// a public API.
- if (bundle.getBoolean(BiometricPrompt.KEY_USE_DEFAULT_TITLE, false)) {
+ final boolean useDefaultTitle =
+ bundle.getBoolean(BiometricPrompt.KEY_USE_DEFAULT_TITLE, false);
+ if (useDefaultTitle) {
checkInternalPermission();
+ // Set the default title if necessary
+ try {
+ if (useDefaultTitle) {
+ final List<ActivityManager.RunningAppProcessInfo> procs =
+ ActivityManager.getService().getRunningAppProcesses();
+ for (int i = 0; i < procs.size(); i++) {
+ final ActivityManager.RunningAppProcessInfo info = procs.get(i);
+ if (info.uid == callingUid
+ && info.importance == IMPORTANCE_FOREGROUND) {
+ PackageManager pm = getContext().getPackageManager();
+ final CharSequence label = pm.getApplicationLabel(
+ pm.getApplicationInfo(info.processName,
+ PackageManager.GET_META_DATA));
+ final String title = getContext()
+ .getString(R.string.biometric_dialog_default_title, label);
+ if (TextUtils.isEmpty(
+ bundle.getCharSequence(BiometricPrompt.KEY_TITLE))) {
+ bundle.putCharSequence(BiometricPrompt.KEY_TITLE, title);
+ }
+ break;
+ }
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "Name not found", e);
+ }
}
mHandler.post(() -> {
@@ -285,13 +664,13 @@ public class BiometricService extends SystemService {
getContext().getString(R.string.biometric_error_hw_unavailable);
switch (error) {
case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT:
- receiver.onError(0 /* deviceId */, error, hardwareUnavailable);
+ receiver.onError(error, hardwareUnavailable);
break;
case BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE:
- receiver.onError(0 /* deviceId */, error, hardwareUnavailable);
+ receiver.onError(error, hardwareUnavailable);
break;
case BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS:
- receiver.onError(0 /* deviceId */, error,
+ receiver.onError(error,
getErrorString(modality, error, 0 /* vendorCode */));
break;
default:
@@ -304,60 +683,91 @@ public class BiometricService extends SystemService {
return;
}
- // Actually start authentication
mCurrentModality = modality;
- try {
- // No polymorphism :(
- if (mCurrentModality == BIOMETRIC_FINGERPRINT) {
- mFingerprintService.authenticateFromService(token, sessionId, userId,
- receiver, flags, opPackageName, bundle, dialogReceiver,
- callingUid, callingPid, callingUserId);
- } else if (mCurrentModality == BIOMETRIC_IRIS) {
- Slog.w(TAG, "Unsupported modality");
- } else if (mCurrentModality == BIOMETRIC_FACE) {
- mFaceService.authenticateFromService(true /* requireConfirmation */,
- token, sessionId, userId, receiver, flags, opPackageName,
- bundle, dialogReceiver, callingUid, callingPid, callingUserId);
- } else {
- Slog.w(TAG, "Unsupported modality");
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to start authentication", e);
- }
+
+ // Actually start authentication
+ authenticateInternal(token, sessionId, userId, receiver, opPackageName, bundle,
+ callingUid, callingPid, callingUserId, modality);
});
}
+ /**
+ * authenticate() (above) which is called from BiometricPrompt determines which
+ * modality/modalities to start authenticating with. authenticateInternal() should only be
+ * used for:
+ * 1) Preparing <Biometric>Services for authentication when BiometricPrompt#authenticate is,
+ * invoked, shortly after which BiometricPrompt is shown and authentication starts
+ * 2) Preparing <Biometric>Services for authentication when BiometricPrompt is already shown
+ * and the user has pressed "try again"
+ */
+ private void authenticateInternal(IBinder token, long sessionId, int userId,
+ IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
+ int callingUid, int callingPid, int callingUserId, int modality) {
+ try {
+ // Generate random cookies to pass to the services that should prepare to start
+ // authenticating. Store the cookie here and wait for all services to "ack"
+ // with the cookie. Once all cookies are received, we can show the prompt
+ // and let the services start authenticating. The cookie should be non-zero.
+ final int cookie = mRandom.nextInt(Integer.MAX_VALUE - 1) + 1;
+ Slog.d(TAG, "Creating auth session. Modality: " + modality
+ + ", cookie: " + cookie);
+ final HashMap<Integer, Integer> authenticators = new HashMap<>();
+ authenticators.put(modality, cookie);
+ mPendingAuthSession = new AuthSession(authenticators, token, sessionId, userId,
+ receiver, opPackageName, bundle, callingUid, callingPid, callingUserId,
+ modality);
+ mPendingAuthSession.mState = STATE_AUTH_CALLED;
+ // No polymorphism :(
+ if ((modality & TYPE_FINGERPRINT) != 0) {
+ mFingerprintService.prepareForAuthentication(token, sessionId, userId,
+ mInternalReceiver, opPackageName, cookie,
+ callingUid, callingPid, callingUserId);
+ }
+ if ((modality & TYPE_IRIS) != 0) {
+ Slog.w(TAG, "Iris unsupported");
+ }
+ if ((modality & TYPE_FACE) != 0) {
+ mFaceService.prepareForAuthentication(true /* requireConfirmation */,
+ token, sessionId, userId, mInternalReceiver, opPackageName,
+ cookie, callingUid, callingPid, callingUserId);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to start authentication", e);
+ }
+ }
+
@Override // Binder call
public void cancelAuthentication(IBinder token, String opPackageName)
throws RemoteException {
checkPermission();
-
if (token == null || opPackageName == null) {
Slog.e(TAG, "Unable to cancel, one or more null arguments");
return;
}
- final int callingUid = Binder.getCallingUid();
- final int callingPid = Binder.getCallingPid();
- final int callingUserId = UserHandle.getCallingUserId();
-
- mHandler.post(() -> {
- try {
- if (mCurrentModality == BIOMETRIC_FINGERPRINT) {
- mFingerprintService.cancelAuthenticationFromService(token, opPackageName,
- callingUid, callingPid, callingUserId);
- } else if (mCurrentModality == BIOMETRIC_IRIS) {
- Slog.w(TAG, "Unsupported modality");
- } else if (mCurrentModality == BIOMETRIC_FACE) {
- mFaceService.cancelAuthenticationFromService(token, opPackageName,
- callingUid, callingPid, callingUserId);
- } else {
- Slog.w(TAG, "Unsupported modality");
+ // We need to check the current authenticators state. If we're pending confirm
+ // or idle, we need to dismiss the dialog and send an ERROR_CANCELED to the client,
+ // since we won't be getting an onError from the driver.
+ if (mCurrentAuthSession != null && mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
+ mHandler.post(() -> {
+ try {
+ // Send error to client
+ mCurrentAuthSession.mClientReceiver.onError(
+ BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+ getContext().getString(
+ com.android.internal.R.string.biometric_error_user_canceled)
+ );
+
+ mCurrentAuthSession.mState = STATE_AUTH_IDLE;
+ mCurrentAuthSession = null;
+ mStatusBarService.hideBiometricDialog();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to cancel authentication");
- }
- });
+ });
+ } else {
+ cancelInternal(token, opPackageName, true /* fromClient */);
+ }
}
@Override // Binder call
@@ -402,6 +812,31 @@ public class BiometricService extends SystemService {
Binder.restoreCallingIdentity(ident);
}
}
+
+ void cancelInternal(IBinder token, String opPackageName, boolean fromClient) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int callingUserId = UserHandle.getCallingUserId();
+ mHandler.post(() -> {
+ try {
+ // TODO: For multiple modalities, send a single ERROR_CANCELED only when all
+ // drivers have canceled authentication.
+ if ((mCurrentModality & TYPE_FINGERPRINT) != 0) {
+ mFingerprintService.cancelAuthenticationFromService(token, opPackageName,
+ callingUid, callingPid, callingUserId, fromClient);
+ }
+ if ((mCurrentModality & TYPE_IRIS) != 0) {
+ Slog.w(TAG, "Iris unsupported");
+ }
+ if ((mCurrentModality & TYPE_FACE) != 0) {
+ mFaceService.cancelAuthenticationFromService(token, opPackageName,
+ callingUid, callingPid, callingUserId, fromClient);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to cancel authentication");
+ }
+ });
+ }
}
private void checkAppOp(String opPackageName, int callingUid) {
@@ -413,7 +848,7 @@ public class BiometricService extends SystemService {
}
private void checkInternalPermission() {
- getContext().enforceCallingPermission(USE_BIOMETRIC_INTERNAL,
+ getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL,
"Must have USE_BIOMETRIC_INTERNAL permission");
}
@@ -490,16 +925,19 @@ public class BiometricService extends SystemService {
* returns errors through the callback (no biometric feature, hardware not detected, no
* templates enrolled, etc). This service must not start authentication if errors are sent.
*
- * @Returns A pair [Modality, Error] with Modality being one of {@link #BIOMETRIC_NONE},
- * {@link #BIOMETRIC_FINGERPRINT}, {@link #BIOMETRIC_IRIS}, {@link #BIOMETRIC_FACE}
+ * @Returns A pair [Modality, Error] with Modality being one of
+ * {@link BiometricAuthenticator#TYPE_NONE},
+ * {@link BiometricAuthenticator#TYPE_FINGERPRINT},
+ * {@link BiometricAuthenticator#TYPE_IRIS},
+ * {@link BiometricAuthenticator#TYPE_FACE}
* and the error containing one of the {@link BiometricConstants} errors.
*/
private Pair<Integer, Integer> checkAndGetBiometricModality(int callingUid) {
- int modality = BIOMETRIC_NONE;
+ int modality = TYPE_NONE;
// No biometric features, send error
if (mAuthenticators.isEmpty()) {
- return new Pair<>(BIOMETRIC_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT);
+ return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT);
}
// Assuming that authenticators are listed in priority-order, the rest of this function
@@ -512,13 +950,13 @@ public class BiometricService extends SystemService {
boolean hasTemplatesEnrolled = false;
boolean enabledForApps = false;
- int firstHwAvailable = BIOMETRIC_NONE;
+ int firstHwAvailable = TYPE_NONE;
for (int i = 0; i < mAuthenticators.size(); i++) {
modality = mAuthenticators.get(i).getType();
BiometricAuthenticator authenticator = mAuthenticators.get(i).getAuthenticator();
if (authenticator.isHardwareDetected()) {
isHardwareDetected = true;
- if (firstHwAvailable == BIOMETRIC_NONE) {
+ if (firstHwAvailable == TYPE_NONE) {
// Store the first one since we want to return the error in correct priority
// order.
firstHwAvailable = modality;
@@ -538,13 +976,13 @@ public class BiometricService extends SystemService {
// Check error conditions
if (!isHardwareDetected) {
- return new Pair<>(BIOMETRIC_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
+ return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
} else if (!hasTemplatesEnrolled) {
// Return the modality here so the correct error string can be sent. This error is
// preferred over !enabledForApps
return new Pair<>(firstHwAvailable, BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS);
} else if (!enabledForApps) {
- return new Pair<>(BIOMETRIC_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
+ return new Pair<>(TYPE_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
}
return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS);
@@ -552,11 +990,11 @@ public class BiometricService extends SystemService {
private boolean isEnabledForApp(int modality) {
switch(modality) {
- case BIOMETRIC_FINGERPRINT:
+ case TYPE_FINGERPRINT:
return true;
- case BIOMETRIC_IRIS:
+ case TYPE_IRIS:
return true;
- case BIOMETRIC_FACE:
+ case TYPE_FACE:
return mSettingObserver.getFaceEnabledForApps();
default:
Slog.w(TAG, "Unsupported modality: " + modality);
@@ -566,12 +1004,12 @@ public class BiometricService extends SystemService {
private String getErrorString(int type, int error, int vendorCode) {
switch (type) {
- case BIOMETRIC_FINGERPRINT:
+ case TYPE_FINGERPRINT:
return FingerprintManager.getErrorString(getContext(), error, vendorCode);
- case BIOMETRIC_IRIS:
+ case TYPE_IRIS:
Slog.w(TAG, "Modality not supported");
return null; // not supported
- case BIOMETRIC_FACE:
+ case TYPE_FACE:
return FaceManager.getErrorString(getContext(), error, vendorCode);
default:
Slog.w(TAG, "Unable to get error string for modality: " + type);
@@ -581,12 +1019,12 @@ public class BiometricService extends SystemService {
private BiometricAuthenticator getAuthenticator(int type) {
switch (type) {
- case BIOMETRIC_FINGERPRINT:
+ case TYPE_FINGERPRINT:
return (FingerprintManager)
getContext().getSystemService(Context.FINGERPRINT_SERVICE);
- case BIOMETRIC_IRIS:
+ case TYPE_IRIS:
return null;
- case BIOMETRIC_FACE:
+ case TYPE_FACE:
return (FaceManager)
getContext().getSystemService(Context.FACE_SERVICE);
default:
@@ -596,11 +1034,11 @@ public class BiometricService extends SystemService {
private boolean hasFeature(int type) {
switch (type) {
- case BIOMETRIC_FINGERPRINT:
+ case TYPE_FINGERPRINT:
return mHasFeatureFingerprint;
- case BIOMETRIC_IRIS:
+ case TYPE_IRIS:
return mHasFeatureIris;
- case BIOMETRIC_FACE:
+ case TYPE_FACE:
return mHasFeatureFace;
default:
return false;
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index 74d742af5b84..9649ccd3c750 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -16,7 +16,6 @@
package com.android.server.biometrics;
-import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
import android.app.ActivityManager;
@@ -36,8 +35,9 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.IBiometricPromptReceiver;
+import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.fingerprint.Fingerprint;
import android.os.Binder;
import android.os.Bundle;
@@ -56,7 +56,6 @@ import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
-import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.server.SystemService;
@@ -106,6 +105,7 @@ public abstract class BiometricServiceBase extends SystemService
protected final AppOpsManager mAppOps;
protected final H mHandler = new H();
+ private IBiometricService mBiometricService;
private ClientMonitor mCurrentClient;
private ClientMonitor mPendingClient;
private PerformanceStats mPerformanceStats;
@@ -223,12 +223,9 @@ public abstract class BiometricServiceBase extends SystemService
public AuthenticationClientImpl(Context context, DaemonWrapper daemon, long halDeviceId,
IBinder token, ServiceListener listener, int targetUserId, int groupId, long opId,
- boolean restricted, String owner, Bundle bundle,
- IBiometricPromptReceiver dialogReceiver,
- IStatusBarService statusBarService, boolean requireConfirmation) {
- super(context, getMetrics(), daemon, halDeviceId, token, listener,
- targetUserId, groupId, opId, restricted, owner, bundle, dialogReceiver,
- statusBarService, requireConfirmation);
+ boolean restricted, String owner, int cookie, boolean requireConfirmation) {
+ super(context, getMetrics(), daemon, halDeviceId, token, listener, targetUserId,
+ groupId, opId, restricted, owner, cookie, requireConfirmation);
}
@Override
@@ -279,11 +276,6 @@ public abstract class BiometricServiceBase extends SystemService
}
return AuthenticationClient.LOCKOUT_NONE;
}
-
- @Override
- public void onAuthenticationConfirmed() {
- removeClient(mCurrentClient);
- }
}
protected class EnrollClientImpl extends EnrollClient {
@@ -345,18 +337,28 @@ public abstract class BiometricServiceBase extends SystemService
default void onEnrollResult(BiometricAuthenticator.Identifier identifier,
int remaining) throws RemoteException {};
- void onAcquired(long deviceId, int acquiredInfo, int vendorCode)
- throws RemoteException;
+ void onAcquired(long deviceId, int acquiredInfo, int vendorCode) throws RemoteException;
- void onAuthenticationSucceeded(long deviceId,
- BiometricAuthenticator.Identifier biometric, int userId)
- throws RemoteException;
+ default void onAuthenticationSucceeded(long deviceId,
+ BiometricAuthenticator.Identifier biometric, int userId) throws RemoteException {
+ throw new UnsupportedOperationException("Stub!");
+ }
- void onAuthenticationFailed(long deviceId)
- throws RemoteException;
+ default void onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)
+ throws RemoteException {
+ throw new UnsupportedOperationException("Stub!");
+ }
- void onError(long deviceId, int error, int vendorCode)
- throws RemoteException;
+ default void onAuthenticationFailed(long deviceId) throws RemoteException {
+ throw new UnsupportedOperationException("Stub!");
+ }
+
+ default void onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)
+ throws RemoteException {
+ throw new UnsupportedOperationException("Stub!");
+ }
+
+ void onError(long deviceId, int error, int vendorCode, int cookie) throws RemoteException;
default void onRemoved(BiometricAuthenticator.Identifier identifier,
int remaining) throws RemoteException {};
@@ -366,6 +368,37 @@ public abstract class BiometricServiceBase extends SystemService
}
/**
+ * Wraps the callback interface from Service -> BiometricPrompt
+ */
+ protected abstract class BiometricServiceListener implements ServiceListener {
+ private IBiometricServiceReceiverInternal mWrapperReceiver;
+
+ public BiometricServiceListener(IBiometricServiceReceiverInternal wrapperReceiver) {
+ mWrapperReceiver = wrapperReceiver;
+ }
+
+ public IBiometricServiceReceiverInternal getWrapperReceiver() {
+ return mWrapperReceiver;
+ }
+
+ @Override
+ public void onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] token)
+ throws RemoteException {
+ if (getWrapperReceiver() != null) {
+ getWrapperReceiver().onAuthenticationSucceeded(requireConfirmation, token);
+ }
+ }
+
+ @Override
+ public void onAuthenticationFailedInternal(int cookie, boolean requireConfirmation)
+ throws RemoteException {
+ if (getWrapperReceiver() != null) {
+ getWrapperReceiver().onAuthenticationFailed(cookie, requireConfirmation);
+ }
+ }
+ }
+
+ /**
* Wraps a portion of the interface from Service -> Daemon that is used by the ClientMonitor
* subclasses.
*/
@@ -706,30 +739,6 @@ public abstract class BiometricServiceBase extends SystemService
}
mHandler.post(() -> {
- if (client.isBiometricPrompt()) {
- try {
- final List<ActivityManager.RunningAppProcessInfo> procs =
- ActivityManager.getService().getRunningAppProcesses();
- for (int i = 0; i < procs.size(); i++) {
- final ActivityManager.RunningAppProcessInfo info = procs.get(i);
- if (info.uid == callingUid && info.importance == IMPORTANCE_FOREGROUND) {
- PackageManager pm = getContext().getPackageManager();
- final CharSequence label = pm.getApplicationLabel(
- pm.getApplicationInfo(info.processName,
- PackageManager.GET_META_DATA));
- final String title = getContext()
- .getString(R.string.biometric_dialog_default_title, label);
- client.setTitleIfEmpty(title);
- break;
- }
- }
- } catch (RemoteException e) {
- Slog.e(getTag(), "Unable to get application name", e);
- } catch (PackageManager.NameNotFoundException e) {
- Slog.e(getTag(), "Unable to get application name", e);
- }
- }
-
mMetricsLogger.histogram(getMetrics().tagAuthToken(), opId != 0L ? 1 : 0);
// Get performance stats object for this user.
@@ -751,29 +760,37 @@ public abstract class BiometricServiceBase extends SystemService
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
- cancelAuthenticationInternal(token, opPackageName, callingUid, callingPid, callingUserId);
+ cancelAuthenticationInternal(token, opPackageName, callingUid, callingPid, callingUserId,
+ true /* fromClient */);
}
protected void cancelAuthenticationInternal(final IBinder token, final String opPackageName,
- int callingUid, int callingPid, int callingUserId) {
- if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
- callingUserId)) {
- if (DEBUG) Slog.v(getTag(), "cancelAuthentication(): reject " + opPackageName);
- return;
+ int callingUid, int callingPid, int callingUserId, boolean fromClient) {
+ if (fromClient) {
+ // Only check this if cancel was called from the client (app). If cancel was called
+ // from BiometricService, it means the dialog was dismissed due to user interaction.
+ if (!canUseBiometric(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
+ callingUserId)) {
+ if (DEBUG) Slog.v(getTag(), "cancelAuthentication(): reject " + opPackageName);
+ return;
+ }
}
mHandler.post(() -> {
ClientMonitor client = mCurrentClient;
if (client instanceof AuthenticationClient) {
- if (client.getToken() == token) {
- if (DEBUG) Slog.v(getTag(), "stop client " + client.getOwnerString());
+ if (client.getToken() == token || !fromClient) {
+ if (DEBUG) Slog.v(getTag(), "Stopping client " + client.getOwnerString()
+ + ", fromClient: " + fromClient);
+ // If cancel was from BiometricService, it means the dialog was dismissed
+ // and authentication should be canceled.
client.stop(client.getToken() == token);
} else {
- if (DEBUG) Slog.v(getTag(), "can't stop client "
- + client.getOwnerString() + " since tokens don't match");
+ if (DEBUG) Slog.v(getTag(), "Can't stop client " + client.getOwnerString()
+ + " since tokens don't match. fromClient: " + fromClient);
}
} else if (client != null) {
- if (DEBUG) Slog.v(getTag(), "can't cancel non-authenticating client "
+ if (DEBUG) Slog.v(getTag(), "Can't cancel non-authenticating client "
+ client.getOwnerString());
}
});
@@ -805,8 +822,7 @@ public abstract class BiometricServiceBase extends SystemService
int lockoutMode = getLockoutMode();
if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
- Slog.v(getTag(), "In lockout mode(" + lockoutMode +
- ") ; disallowing authentication");
+ Slog.v(getTag(), "In lockout mode(" + lockoutMode + ") ; disallowing authentication");
int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
BiometricConstants.BIOMETRIC_ERROR_LOCKOUT :
BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
@@ -919,7 +935,6 @@ public abstract class BiometricServiceBase extends SystemService
if (currentClient != null) {
if (DEBUG) Slog.v(getTag(), "request stop current client " +
currentClient.getOwnerString());
-
// This check only matters for FingerprintService, since enumerate may call back
// multiple times.
if (currentClient instanceof FingerprintService.EnumerateClientImpl ||
@@ -940,15 +955,49 @@ public abstract class BiometricServiceBase extends SystemService
mHandler.removeCallbacks(mResetClientState);
mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
} else if (newClient != null) {
+ // For BiometricPrompt clients, do not start until
+ // <Biometric>Service#startPreparedClient is called. BiometricService waits until all
+ // modalities are ready before initiating authentication.
+ if (newClient instanceof AuthenticationClient) {
+ AuthenticationClient client = (AuthenticationClient) newClient;
+ if (client.isBiometricPrompt()) {
+ if (DEBUG) Slog.v(getTag(), "Returning cookie: " + client.getCookie());
+ mCurrentClient = newClient;
+ if (mBiometricService == null) {
+ mBiometricService = IBiometricService.Stub.asInterface(
+ ServiceManager.getService(Context.BIOMETRIC_SERVICE));
+ }
+ try {
+ mBiometricService.onReadyForAuthentication(client.getCookie(),
+ client.getRequireConfirmation(), client.getTargetUserId());
+ } catch (RemoteException e) {
+ Slog.e(getTag(), "Remote exception", e);
+ }
+ return;
+ }
+ }
+
+ // We are not a BiometricPrompt client, start the client immediately
mCurrentClient = newClient;
- if (DEBUG) Slog.v(getTag(), "starting client "
- + newClient.getClass().getSuperclass().getSimpleName()
- + "(" + newClient.getOwnerString() + ")"
- + ", initiatedByClient = " + initiatedByClient);
- notifyClientActiveCallbacks(true);
+ startCurrentClient(mCurrentClient.getCookie());
+ }
+ }
- newClient.start();
+ protected void startCurrentClient(int cookie) {
+ if (mCurrentClient == null) {
+ Slog.e(getTag(), "Trying to start null client!");
+ return;
+ }
+ if (DEBUG) Slog.v(getTag(), "starting client "
+ + mCurrentClient.getClass().getSuperclass().getSimpleName()
+ + "(" + mCurrentClient.getOwnerString() + ")"
+ + " cookie: " + cookie + "/" + mCurrentClient.getCookie());
+ if (cookie != mCurrentClient.getCookie()) {
+ Slog.e(getTag(), "Mismatched cookie");
+ return;
}
+ notifyClientActiveCallbacks(true);
+ mCurrentClient.start();
}
protected void removeClient(ClientMonitor client) {
diff --git a/services/core/java/com/android/server/biometrics/ClientMonitor.java b/services/core/java/com/android/server/biometrics/ClientMonitor.java
index a7ada2f6556c..d19aff69b832 100644
--- a/services/core/java/com/android/server/biometrics/ClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/ClientMonitor.java
@@ -58,6 +58,9 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient {
private IBinder mToken;
private BiometricServiceBase.ServiceListener mListener;
+ // Currently only used for authentication client. The cookie generated by BiometricService
+ // is never 0.
+ private final int mCookie;
protected final MetricsLogger mMetricsLogger;
protected final Metrics mMetrics;
@@ -80,7 +83,7 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient {
public ClientMonitor(Context context, Metrics metrics,
BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token,
BiometricServiceBase.ServiceListener listener, int userId, int groupId,
- boolean restricted, String owner) {
+ boolean restricted, String owner, int cookie) {
mContext = context;
mMetrics = metrics;
mDaemon = daemon;
@@ -91,6 +94,7 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient {
mGroupId = groupId;
mIsRestricted = restricted;
mOwner = owner;
+ mCookie = cookie;
mSuccessVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
mErrorVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
mMetricsLogger = new MetricsLogger();
@@ -107,6 +111,10 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient {
return mMetrics.logTag();
}
+ public int getCookie() {
+ return mCookie;
+ }
+
/**
* Contacts the biometric's HAL to start the client.
* @return 0 on success, errno from driver on failure
@@ -174,7 +182,7 @@ public abstract class ClientMonitor implements IBinder.DeathRecipient {
public boolean onError(long deviceId, int error, int vendorCode) {
try {
if (mListener != null) {
- mListener.onError(deviceId, error, vendorCode);
+ mListener.onError(deviceId, error, vendorCode, getCookie());
}
} catch (RemoteException e) {
Slog.w(getLogTag(), "Failed to invoke sendError", e);
diff --git a/services/core/java/com/android/server/biometrics/EnrollClient.java b/services/core/java/com/android/server/biometrics/EnrollClient.java
index 76dc5a91bdbe..f858ef5ec6f8 100644
--- a/services/core/java/com/android/server/biometrics/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/EnrollClient.java
@@ -40,7 +40,7 @@ public abstract class EnrollClient extends ClientMonitor {
BiometricServiceBase.ServiceListener listener, int userId, int groupId,
byte[] cryptoToken, boolean restricted, String owner, BiometricUtils utils) {
super(context, metrics, daemon, halDeviceId, token, listener, userId, groupId, restricted,
- owner);
+ owner, 0 /* cookie */);
mBiometricUtils = utils;
mCryptoToken = Arrays.copyOf(cryptoToken, cryptoToken.length);
}
diff --git a/services/core/java/com/android/server/biometrics/EnumerateClient.java b/services/core/java/com/android/server/biometrics/EnumerateClient.java
index 47dc7ffda456..df6220cfd94b 100644
--- a/services/core/java/com/android/server/biometrics/EnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/EnumerateClient.java
@@ -34,7 +34,7 @@ public abstract class EnumerateClient extends ClientMonitor {
BiometricServiceBase.ServiceListener listener, int groupId, int userId,
boolean restricted, String owner) {
super(context, metrics, daemon, halDeviceId, token, listener, userId, groupId, restricted,
- owner);
+ owner, 0 /* cookie */);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/RemovalClient.java b/services/core/java/com/android/server/biometrics/RemovalClient.java
index 15b3773314bf..be233ec89342 100644
--- a/services/core/java/com/android/server/biometrics/RemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/RemovalClient.java
@@ -37,7 +37,7 @@ public abstract class RemovalClient extends ClientMonitor {
BiometricServiceBase.ServiceListener listener, int biometricId, int groupId, int userId,
boolean restricted, String owner, BiometricUtils utils) {
super(context, metrics, daemon, halDeviceId, token, listener, userId, groupId, restricted,
- owner);
+ owner, 0 /* cookie */);
mBiometricId = biometricId;
mBiometricUtils = utils;
}
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 7aa2e47300dd..557af0478b87 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -27,9 +27,8 @@ import android.content.Context;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.IBiometricPromptReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
-import android.hardware.biometrics.IBiometricServiceReceiver;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.biometrics.face.V1_0.Status;
@@ -38,7 +37,6 @@ import android.hardware.face.FaceManager;
import android.hardware.face.IFaceService;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
-import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
@@ -50,7 +48,6 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.biometrics.BiometricServiceBase;
@@ -89,27 +86,9 @@ public class FaceService extends BiometricServiceBase {
public FaceAuthClient(Context context,
DaemonWrapper daemon, long halDeviceId, IBinder token,
ServiceListener listener, int targetUserId, int groupId, long opId,
- boolean restricted, String owner, Bundle bundle,
- IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService,
- boolean requireConfirmation) {
+ boolean restricted, String owner, int cookie, boolean requireConfirmation) {
super(context, daemon, halDeviceId, token, listener, targetUserId, groupId, opId,
- restricted, owner, bundle, dialogReceiver, statusBarService,
- requireConfirmation);
- }
-
- @Override
- public String getErrorString(int error, int vendorCode) {
- return FaceManager.getErrorString(getContext(), error, vendorCode);
- }
-
- @Override
- public String getAcquiredString(int acquireInfo, int vendorCode) {
- return FaceManager.getAcquiredString(getContext(), acquireInfo, vendorCode);
- }
-
- @Override
- public int getBiometricType() {
- return BiometricAuthenticator.TYPE_FACE;
+ restricted, owner, cookie, requireConfirmation);
}
}
@@ -162,28 +141,33 @@ public class FaceService extends BiometricServiceBase {
final AuthenticationClientImpl client = new FaceAuthClient(getContext(),
mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
mCurrentUserId, 0 /* groupId */, opId, restricted, opPackageName,
- null /* bundle */, null /* dialogReceiver */, mStatusBarService,
- false /* requireConfirmation */);
+ 0 /* cookie */, false /* requireConfirmation */);
authenticateInternal(client, opId, opPackageName);
}
@Override // Binder call
- public void authenticateFromService(boolean requireConfirmation, IBinder token, long opId,
- int groupId, IBiometricServiceReceiver receiver, int flags,
- String opPackageName, Bundle bundle, IBiometricPromptReceiver dialogReceiver,
- int callingUid, int callingPid, int callingUserId) {
+ public void prepareForAuthentication(boolean requireConfirmation, IBinder token, long opId,
+ int groupId, IBiometricServiceReceiverInternal wrapperReceiver,
+ String opPackageName, int cookie, int callingUid, int callingPid,
+ int callingUserId) {
checkPermission(USE_BIOMETRIC_INTERNAL);
final boolean restricted = true; // BiometricPrompt is always restricted
final AuthenticationClientImpl client = new FaceAuthClient(getContext(),
mDaemonWrapper, mHalDeviceId, token,
- new BiometricPromptServiceListenerImpl(receiver),
- mCurrentUserId, 0 /* groupId */, opId, restricted, opPackageName,
- bundle, dialogReceiver, mStatusBarService, true /* requireConfirmation */);
+ new BiometricPromptServiceListenerImpl(wrapperReceiver),
+ mCurrentUserId, 0 /* groupId */, opId, restricted, opPackageName, cookie,
+ true /* requireConfirmation */);
authenticateInternal(client, opId, opPackageName, callingUid, callingPid,
callingUserId);
}
@Override // Binder call
+ public void startPreparedClient(int cookie) {
+ checkPermission(MANAGE_BIOMETRIC);
+ startCurrentClient(cookie);
+ }
+
+ @Override // Binder call
public void cancelAuthentication(final IBinder token, final String opPackageName) {
checkPermission(USE_BIOMETRIC_INTERNAL);
cancelAuthenticationInternal(token, opPackageName);
@@ -191,10 +175,10 @@ public class FaceService extends BiometricServiceBase {
@Override // Binder call
public void cancelAuthenticationFromService(final IBinder token, final String opPackageName,
- int callingUid, int callingPid, int callingUserId) {
+ int callingUid, int callingPid, int callingUserId, boolean fromClient) {
checkPermission(USE_BIOMETRIC_INTERNAL);
- cancelAuthenticationInternal(token, opPackageName,
- callingUid, callingPid, callingUserId);
+ cancelAuthenticationInternal(token, opPackageName, callingUid, callingPid,
+ callingUserId, fromClient);
}
@Override // Binder call
@@ -405,12 +389,9 @@ public class FaceService extends BiometricServiceBase {
* Receives callbacks from the ClientMonitor implementations. The results are forwarded to
* BiometricPrompt.
*/
- private class BiometricPromptServiceListenerImpl implements ServiceListener {
-
- private IBiometricServiceReceiver mBiometricServiceReceiver;
-
- public BiometricPromptServiceListenerImpl(IBiometricServiceReceiver receiver) {
- mBiometricServiceReceiver = receiver;
+ private class BiometricPromptServiceListenerImpl extends BiometricServiceListener {
+ BiometricPromptServiceListenerImpl(IBiometricServiceReceiverInternal wrapperReceiver) {
+ super(wrapperReceiver);
}
@Override
@@ -419,32 +400,18 @@ public class FaceService extends BiometricServiceBase {
/**
* Map the acquired codes onto existing {@link BiometricConstants} acquired codes.
*/
- if (mBiometricServiceReceiver != null) {
- mBiometricServiceReceiver.onAcquired(deviceId,
+ if (getWrapperReceiver() != null) {
+ getWrapperReceiver().onAcquired(
FaceManager.getMappedAcquiredInfo(acquiredInfo, vendorCode),
FaceManager.getAcquiredString(getContext(), acquiredInfo, vendorCode));
}
}
@Override
- public void onAuthenticationSucceeded(long deviceId,
- BiometricAuthenticator.Identifier biometric, int userId) throws RemoteException {
- if (mBiometricServiceReceiver != null) {
- mBiometricServiceReceiver.onAuthenticationSucceeded(deviceId);
- }
- }
-
- @Override
- public void onAuthenticationFailed(long deviceId) throws RemoteException {
- if (mBiometricServiceReceiver != null) {
- mBiometricServiceReceiver.onAuthenticationFailed(deviceId);
- }
- }
-
- @Override
- public void onError(long deviceId, int error, int vendorCode) throws RemoteException {
- if (mBiometricServiceReceiver != null) {
- mBiometricServiceReceiver.onError(deviceId, error,
+ public void onError(long deviceId, int error, int vendorCode, int cookie)
+ throws RemoteException {
+ if (getWrapperReceiver() != null) {
+ getWrapperReceiver().onError(cookie, error,
FaceManager.getErrorString(getContext(), error, vendorCode));
}
}
@@ -455,7 +422,6 @@ public class FaceService extends BiometricServiceBase {
* the FaceManager.
*/
private class ServiceListenerImpl implements ServiceListener {
-
private IFaceServiceReceiver mFaceServiceReceiver;
public ServiceListenerImpl(IFaceServiceReceiver receiver) {
@@ -501,7 +467,8 @@ public class FaceService extends BiometricServiceBase {
}
@Override
- public void onError(long deviceId, int error, int vendorCode) throws RemoteException {
+ public void onError(long deviceId, int error, int vendorCode, int cookie)
+ throws RemoteException {
if (mFaceServiceReceiver != null) {
mFaceServiceReceiver.onError(deviceId, error, vendorCode);
}
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index b0b788fbe589..6a5bc61f2eb6 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -30,9 +30,8 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.IBiometricPromptReceiver;
-import android.hardware.biometrics.IBiometricServiceReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback;
import android.hardware.fingerprint.Fingerprint;
@@ -42,7 +41,6 @@ import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.os.Binder;
import android.os.Build;
-import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.RemoteException;
@@ -55,7 +53,6 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemServerInitThreadPool;
import com.android.server.biometrics.AuthenticationClient;
@@ -109,27 +106,10 @@ public class FingerprintService extends BiometricServiceBase {
public FingerprintAuthClient(Context context,
DaemonWrapper daemon, long halDeviceId, IBinder token,
ServiceListener listener, int targetUserId, int groupId, long opId,
- boolean restricted, String owner, Bundle bundle,
- IBiometricPromptReceiver dialogReceiver, IStatusBarService statusBarService,
+ boolean restricted, String owner, int cookie,
boolean requireConfirmation) {
super(context, daemon, halDeviceId, token, listener, targetUserId, groupId, opId,
- restricted, owner, bundle, dialogReceiver, statusBarService,
- requireConfirmation);
- }
-
- @Override
- public String getErrorString(int error, int vendorCode) {
- return FingerprintManager.getErrorString(getContext(), error, vendorCode);
- }
-
- @Override
- public String getAcquiredString(int acquireInfo, int vendorCode) {
- return FingerprintManager.getAcquiredString(getContext(), acquireInfo, vendorCode);
- }
-
- @Override
- public int getBiometricType() {
- return BiometricAuthenticator.TYPE_FINGERPRINT;
+ restricted, owner, cookie, requireConfirmation);
}
}
@@ -182,38 +162,44 @@ public class FingerprintService extends BiometricServiceBase {
final boolean restricted = isRestricted();
final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(),
mDaemonWrapper, mHalDeviceId, token, new ServiceListenerImpl(receiver),
- mCurrentUserId, groupId, opId, restricted, opPackageName, null /* bundle */,
- null /* dialogReceiver */, mStatusBarService, false /* requireConfirmation */);
+ mCurrentUserId, groupId, opId, restricted, opPackageName,
+ 0 /* cookie */, false /* requireConfirmation */);
authenticateInternal(client, opId, opPackageName);
}
@Override // Binder call
- public void authenticateFromService(IBinder token, long opId, int groupId,
- IBiometricServiceReceiver receiver, int flags, String opPackageName,
- Bundle bundle, IBiometricPromptReceiver dialogReceiver,
- int callingUid, int callingPid, int callingUserId) {
+ public void prepareForAuthentication(IBinder token, long opId, int groupId,
+ IBiometricServiceReceiverInternal wrapperReceiver, String opPackageName,
+ int cookie, int callingUid, int callingPid, int callingUserId) {
checkPermission(MANAGE_BIOMETRIC);
final boolean restricted = true; // BiometricPrompt is always restricted
final AuthenticationClientImpl client = new FingerprintAuthClient(getContext(),
mDaemonWrapper, mHalDeviceId, token,
- new BiometricPromptServiceListenerImpl(receiver),
- mCurrentUserId, groupId, opId, restricted, opPackageName, bundle,
- dialogReceiver, mStatusBarService, false /* requireConfirmation */);
+ new BiometricPromptServiceListenerImpl(wrapperReceiver),
+ mCurrentUserId, groupId, opId, restricted, opPackageName, cookie,
+ false /* requireConfirmation */);
authenticateInternal(client, opId, opPackageName, callingUid, callingPid,
callingUserId);
}
@Override // Binder call
+ public void startPreparedClient(int cookie) {
+ checkPermission(MANAGE_BIOMETRIC);
+ startCurrentClient(cookie);
+ }
+
+
+ @Override // Binder call
public void cancelAuthentication(final IBinder token, final String opPackageName) {
cancelAuthenticationInternal(token, opPackageName);
}
@Override // Binder call
public void cancelAuthenticationFromService(final IBinder token, final String opPackageName,
- int callingUid, int callingPid, int callingUserId) {
+ int callingUid, int callingPid, int callingUserId, boolean fromClient) {
checkPermission(MANAGE_BIOMETRIC);
- cancelAuthenticationInternal(token, opPackageName,
- callingUid, callingPid, callingUserId);
+ cancelAuthenticationInternal(token, opPackageName, callingUid, callingPid,
+ callingUserId, fromClient);
}
@Override // Binder call
@@ -388,43 +374,25 @@ public class FingerprintService extends BiometricServiceBase {
* Receives callbacks from the ClientMonitor implementations. The results are forwarded to
* BiometricPrompt.
*/
- private class BiometricPromptServiceListenerImpl implements ServiceListener {
-
- private IBiometricServiceReceiver mBiometricServiceReceiver;
-
- public BiometricPromptServiceListenerImpl(IBiometricServiceReceiver receiver) {
- mBiometricServiceReceiver = receiver;
+ private class BiometricPromptServiceListenerImpl extends BiometricServiceListener {
+ BiometricPromptServiceListenerImpl(IBiometricServiceReceiverInternal wrapperReceiver) {
+ super(wrapperReceiver);
}
@Override
public void onAcquired(long deviceId, int acquiredInfo, int vendorCode)
throws RemoteException {
- if (mBiometricServiceReceiver != null) {
- mBiometricServiceReceiver.onAcquired(deviceId, acquiredInfo,
- FingerprintManager.getAcquiredString(
+ if (getWrapperReceiver() != null) {
+ getWrapperReceiver().onAcquired(acquiredInfo, FingerprintManager.getAcquiredString(
getContext(), acquiredInfo, vendorCode));
}
}
@Override
- public void onAuthenticationSucceeded(long deviceId,
- BiometricAuthenticator.Identifier biometric, int userId) throws RemoteException {
- if (mBiometricServiceReceiver != null) {
- mBiometricServiceReceiver.onAuthenticationSucceeded(deviceId);
- }
- }
-
- @Override
- public void onAuthenticationFailed(long deviceId) throws RemoteException {
- if (mBiometricServiceReceiver != null) {
- mBiometricServiceReceiver.onAuthenticationFailed(deviceId);
- }
- }
-
- @Override
- public void onError(long deviceId, int error, int vendorCode) throws RemoteException {
- if (mBiometricServiceReceiver != null) {
- mBiometricServiceReceiver.onError(deviceId, error,
+ public void onError(long deviceId, int error, int vendorCode, int cookie)
+ throws RemoteException {
+ if (getWrapperReceiver() != null) {
+ getWrapperReceiver().onError(cookie, error,
FingerprintManager.getErrorString(getContext(), error, vendorCode));
}
}
@@ -435,7 +403,6 @@ public class FingerprintService extends BiometricServiceBase {
* the FingerprintManager.
*/
private class ServiceListenerImpl implements ServiceListener {
-
private IFingerprintServiceReceiver mFingerprintServiceReceiver;
public ServiceListenerImpl(IFingerprintServiceReceiver receiver) {
@@ -483,7 +450,8 @@ public class FingerprintService extends BiometricServiceBase {
}
@Override
- public void onError(long deviceId, int error, int vendorCode) throws RemoteException {
+ public void onError(long deviceId, int error, int vendorCode, int cookie)
+ throws RemoteException {
if (mFingerprintServiceReceiver != null) {
mFingerprintServiceReceiver.onError(deviceId, error, vendorCode);
}
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 7bfe9ce7017c..6ee5665b9e42 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -225,6 +225,8 @@ abstract class DisplayDevice {
viewport.deviceHeight = isRotated ? info.width : info.height;
viewport.uniqueId = info.uniqueId;
+ // TODO(b/112898898) Use an actual port here.
+ viewport.physicalPort = null;
}
/**
diff --git a/services/core/java/com/android/server/input/ConfigurationProcessor.java b/services/core/java/com/android/server/input/ConfigurationProcessor.java
new file mode 100644
index 000000000000..970e86acf8b8
--- /dev/null
+++ b/services/core/java/com/android/server/input/ConfigurationProcessor.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input;
+
+import android.text.TextUtils;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+
+class ConfigurationProcessor {
+ private static final String TAG = "ConfigurationProcessor";
+
+ static List<String> processExcludedDeviceNames(InputStream xml) throws Exception {
+ List<String> names = new ArrayList<>();
+ try (InputStreamReader confReader = new InputStreamReader(xml)) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(confReader);
+ XmlUtils.beginDocument(parser, "devices");
+ while (true) {
+ XmlUtils.nextElement(parser);
+ if (!"device".equals(parser.getName())) {
+ break;
+ }
+ String name = parser.getAttributeValue(null, "name");
+ if (name != null) {
+ names.add(name);
+ }
+ }
+ }
+ return names;
+ }
+
+ /**
+ * Parse the configuration for input port associations.
+ *
+ * Configuration format:
+ * <code>
+ * &lt;ports>
+ * &lt;port display="0" input="usb-xhci-hcd.0.auto-1.4.3/input0" />
+ * &lt;port display="1" input="usb-xhci-hcd.0.auto-1.4.2/input0" />
+ * &lt;/ports>
+ * </code>
+ *
+ * In this example, any input device that has physical port of
+ * "usb-xhci-hcd.0.auto-1.4.3/input0" will be associated with a display
+ * that has the physical port "0". If such a display does not exist, the input device
+ * will be disabled and no input events will be dispatched from that input device until a
+ * matching display appears. Likewise, an input device that has port "..1.4.2.." will have
+ * its input events forwarded to a display that has physical port of "1".
+ *
+ * Note: display port must be a numeric value, and this is checked at runtime for validity.
+ * At the same time, it is specified as a string for simplicity.
+ *
+ * Note: do not confuse "display id" with "display port".
+ * The "display port" is the physical port on which the display is connected. This could
+ * be something like HDMI0, HDMI1, etc. For virtual displays, "display port" will be null.
+ * The "display id" is a way to identify a particular display, and is not a stable API.
+ * All displays, including virtual ones, will have a display id.
+ *
+ * Return the pairs of associations. The first item in the pair is the input port,
+ * the second item in the pair is the display port.
+ */
+ @VisibleForTesting
+ static List<Pair<String, String>> processInputPortAssociations(InputStream xml)
+ throws Exception {
+ List<Pair<String, String>> associations = new ArrayList<>();
+ try (InputStreamReader confReader = new InputStreamReader(xml)) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(confReader);
+ XmlUtils.beginDocument(parser, "ports");
+
+ while (true) {
+ XmlUtils.nextElement(parser);
+ String entryName = parser.getName();
+ if (!"port".equals(entryName)) {
+ break;
+ }
+ String inputPort = parser.getAttributeValue(null, "input");
+ String displayPort = parser.getAttributeValue(null, "display");
+ if (TextUtils.isEmpty(inputPort) || TextUtils.isEmpty(displayPort)) {
+ // This is likely an error by an OEM during device configuration
+ Slog.wtf(TAG, "Ignoring incomplete entry");
+ continue;
+ }
+ try {
+ Integer.parseUnsignedInt(displayPort);
+ } catch (NumberFormatException e) {
+ Slog.wtf(TAG, "Display port should be an integer");
+ continue;
+ }
+ associations.add(new Pair<>(inputPort, displayPort));
+ }
+ }
+ return associations;
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 3339a49c5ed0..d96b6cba119b 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -64,18 +64,18 @@ import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.Xml;
import android.view.Display;
import android.view.IInputFilter;
import android.view.IInputFilterHost;
import android.view.IWindow;
-import android.view.InputChannel;
import android.view.InputApplicationHandle;
-import android.view.InputWindowHandle;
+import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
+import android.view.InputWindowHandle;
import android.view.KeyEvent;
import android.view.PointerIcon;
import android.view.Surface;
@@ -97,14 +97,13 @@ import com.android.server.policy.WindowManagerPolicy;
import libcore.io.IoUtils;
import libcore.io.Streams;
-import org.xmlpull.v1.XmlPullParser;
-
import java.io.File;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -124,6 +123,7 @@ public class InputManagerService extends IInputManager.Stub
static final boolean DEBUG = false;
private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
+ private static final String PORT_ASSOCIATIONS_PATH = "etc/input-port-associations.xml";
private static final int MSG_DELIVER_INPUT_DEVICES_CHANGED = 1;
private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 2;
@@ -1852,11 +1852,9 @@ public class InputManagerService extends IInputManager.Stub
}
// Native callback.
- private String[] getExcludedDeviceNames() {
- ArrayList<String> names = new ArrayList<String>();
-
+ private static String[] getExcludedDeviceNames() {
+ List<String> names = new ArrayList<>();
// Read partner-provided list of excluded input devices
- XmlPullParser parser = null;
// Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
final File[] baseDirs = {
Environment.getRootDirectory(),
@@ -1864,33 +1862,52 @@ public class InputManagerService extends IInputManager.Stub
};
for (File baseDir: baseDirs) {
File confFile = new File(baseDir, EXCLUDED_DEVICES_PATH);
- FileReader confreader = null;
try {
- confreader = new FileReader(confFile);
- parser = Xml.newPullParser();
- parser.setInput(confreader);
- XmlUtils.beginDocument(parser, "devices");
-
- while (true) {
- XmlUtils.nextElement(parser);
- if (!"device".equals(parser.getName())) {
- break;
- }
- String name = parser.getAttributeValue(null, "name");
- if (name != null) {
- names.add(name);
- }
- }
+ InputStream stream = new FileInputStream(confFile);
+ names.addAll(ConfigurationProcessor.processExcludedDeviceNames(stream));
} catch (FileNotFoundException e) {
// It's ok if the file does not exist.
} catch (Exception e) {
- Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
- } finally {
- try { if (confreader != null) confreader.close(); } catch (IOException e) { }
+ Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e);
}
}
+ return names.toArray(new String[0]);
+ }
+
+ /**
+ * Flatten a list of pairs into a list, with value positioned directly next to the key
+ * @return Flattened list
+ */
+ private static <T> List<T> flatten(@NonNull List<Pair<T, T>> pairs) {
+ List<T> list = new ArrayList<>(pairs.size() * 2);
+ for (Pair<T, T> pair : pairs) {
+ list.add(pair.first);
+ list.add(pair.second);
+ }
+ return list;
+ }
+
+ /**
+ * Ports are highly platform-specific, so only allow these to be specified in the vendor
+ * directory.
+ */
+ // Native callback
+ private static String[] getInputPortAssociations() {
+ File baseDir = Environment.getVendorDirectory();
+ File confFile = new File(baseDir, PORT_ASSOCIATIONS_PATH);
- return names.toArray(new String[names.size()]);
+ try {
+ InputStream stream = new FileInputStream(confFile);
+ List<Pair<String, String>> associations =
+ ConfigurationProcessor.processInputPortAssociations(stream);
+ List<String> associationList = flatten(associations);
+ return associationList.toArray(new String[0]);
+ } catch (FileNotFoundException e) {
+ // Most of the time, file will not exist, which is expected.
+ } catch (Exception e) {
+ Slog.e(TAG, "Could not parse '" + confFile.getAbsolutePath() + "'", e);
+ }
+ return new String[0];
}
// Native callback.
diff --git a/services/core/java/com/android/server/locksettings/SP800Derive.java b/services/core/java/com/android/server/locksettings/SP800Derive.java
new file mode 100644
index 000000000000..77561fc30db9
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/SP800Derive.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.locksettings;
+
+import java.nio.ByteBuffer;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Implementation of NIST SP800-108
+ * "Recommendation for Key Derivation Using Pseudorandom Functions"
+ * Hardcoded:
+ * [PRF=HMAC_SHA256]
+ * [CTRLOCATION=BEFORE_FIXED]
+ * [RLEN=32_BITS]
+ * L = 256
+ * L suffix: 32 bits
+ */
+class SP800Derive {
+ private final byte[] mKeyBytes;
+
+ SP800Derive(byte[] keyBytes) {
+ mKeyBytes = keyBytes;
+ }
+
+ private Mac getMac() {
+ try {
+ final Mac m = Mac.getInstance("HmacSHA256");
+ m.init(new SecretKeySpec(mKeyBytes, m.getAlgorithm()));
+ return m;
+ } catch (InvalidKeyException | NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static void update32(Mac m, int v) {
+ m.update(ByteBuffer.allocate(Integer.BYTES).putInt(v).array());
+ }
+
+ /**
+ * Generate output from a single, fixed input.
+ */
+ public byte[] fixedInput(byte[] fixedInput) {
+ final Mac m = getMac();
+ update32(m, 1); // Hardwired counter value
+ m.update(fixedInput);
+ return m.doFinal();
+ }
+
+ /**
+ * Generate output from a label and context. We add a length field at the end of the context to
+ * disambiguate it from the length even in the presence of zero bytes.
+ */
+ public byte[] withContext(byte[] label, byte[] context) {
+ final Mac m = getMac();
+ // Hardwired counter value: 1
+ update32(m, 1); // Hardwired counter value
+ m.update(label);
+ m.update((byte) 0);
+ m.update(context);
+ update32(m, context.length * 8); // Disambiguate context
+ update32(m, 256); // Hardwired output length
+ return m.doFinal();
+ }
+}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 596daeb1427b..d32c299074a9 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -26,9 +26,9 @@ import android.hardware.weaver.V1_0.WeaverConfig;
import android.hardware.weaver.V1_0.WeaverReadResponse;
import android.hardware.weaver.V1_0.WeaverReadStatus;
import android.hardware.weaver.V1_0.WeaverStatus;
-import android.security.GateKeeper;
import android.os.RemoteException;
import android.os.UserManager;
+import android.security.GateKeeper;
import android.service.gatekeeper.GateKeeperResponse;
import android.service.gatekeeper.IGateKeeperService;
import android.util.ArrayMap;
@@ -102,7 +102,8 @@ public class SyntheticPasswordManager {
private static final int INVALID_WEAVER_SLOT = -1;
private static final byte SYNTHETIC_PASSWORD_VERSION_V1 = 1;
- private static final byte SYNTHETIC_PASSWORD_VERSION = 2;
+ private static final byte SYNTHETIC_PASSWORD_VERSION_V2 = 2;
+ private static final byte SYNTHETIC_PASSWORD_VERSION_V3 = 3;
private static final byte SYNTHETIC_PASSWORD_PASSWORD_BASED = 0;
private static final byte SYNTHETIC_PASSWORD_TOKEN_BASED = 1;
@@ -128,6 +129,8 @@ public class SyntheticPasswordManager {
private static final byte[] PERSONALISATION_WEAVER_PASSWORD = "weaver-pwd".getBytes();
private static final byte[] PERSONALISATION_WEAVER_KEY = "weaver-key".getBytes();
private static final byte[] PERSONALISATION_WEAVER_TOKEN = "weaver-token".getBytes();
+ private static final byte[] PERSONALISATION_CONTEXT =
+ "android-synthetic-password-personalization-context".getBytes();
static class AuthenticationResult {
public AuthenticationToken authToken;
@@ -136,6 +139,7 @@ public class SyntheticPasswordManager {
}
static class AuthenticationToken {
+ private final byte mVersion;
/*
* Here is the relationship between all three fields:
* P0 and P1 are two randomly-generated blocks. P1 is stored on disk but P0 is not.
@@ -146,29 +150,38 @@ public class SyntheticPasswordManager {
private @Nullable byte[] P1;
private @NonNull String syntheticPassword;
+ AuthenticationToken(byte version) {
+ mVersion = version;
+ }
+
+ private byte[] derivePassword(byte[] personalization) {
+ if (mVersion == SYNTHETIC_PASSWORD_VERSION_V3) {
+ return (new SP800Derive(syntheticPassword.getBytes()))
+ .withContext(personalization, PERSONALISATION_CONTEXT);
+ } else {
+ return SyntheticPasswordCrypto.personalisedHash(personalization,
+ syntheticPassword.getBytes());
+ }
+ }
+
public String deriveKeyStorePassword() {
- return bytesToHex(SyntheticPasswordCrypto.personalisedHash(
- PERSONALIZATION_KEY_STORE_PASSWORD, syntheticPassword.getBytes()));
+ return bytesToHex(derivePassword(PERSONALIZATION_KEY_STORE_PASSWORD));
}
public byte[] deriveGkPassword() {
- return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_SP_GK_AUTH,
- syntheticPassword.getBytes());
+ return derivePassword(PERSONALIZATION_SP_GK_AUTH);
}
public byte[] deriveDiskEncryptionKey() {
- return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_FBE_KEY,
- syntheticPassword.getBytes());
+ return derivePassword(PERSONALIZATION_FBE_KEY);
}
public byte[] deriveVendorAuthSecret() {
- return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_AUTHSECRET_KEY,
- syntheticPassword.getBytes());
+ return derivePassword(PERSONALIZATION_AUTHSECRET_KEY);
}
public byte[] derivePasswordHashFactor() {
- return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_PASSWORD_HASH,
- syntheticPassword.getBytes());
+ return derivePassword(PERSONALIZATION_PASSWORD_HASH);
}
private void initialize(byte[] P0, byte[] P1) {
@@ -185,7 +198,7 @@ public class SyntheticPasswordManager {
}
protected static AuthenticationToken create() {
- AuthenticationToken result = new AuthenticationToken();
+ AuthenticationToken result = new AuthenticationToken(SYNTHETIC_PASSWORD_VERSION_V3);
result.initialize(secureRandom(SYNTHETIC_PASSWORD_LENGTH),
secureRandom(SYNTHETIC_PASSWORD_LENGTH));
return result;
@@ -802,7 +815,16 @@ public class SyntheticPasswordManager {
}
byte[] content = createSPBlob(getHandleName(handle), secret, applicationId, sid);
byte[] blob = new byte[content.length + 1 + 1];
- blob[0] = SYNTHETIC_PASSWORD_VERSION;
+ /*
+ * We can upgrade from v1 to v2 because that's just a change in the way that
+ * the SP is stored. However, we can't upgrade to v3 because that is a change
+ * in the way that passwords are derived from the SP.
+ */
+ if (authToken.mVersion == SYNTHETIC_PASSWORD_VERSION_V3) {
+ blob[0] = SYNTHETIC_PASSWORD_VERSION_V3;
+ } else {
+ blob[0] = SYNTHETIC_PASSWORD_VERSION_V2;
+ }
blob[1] = type;
System.arraycopy(content, 0, blob, 2, content.length);
saveState(SP_BLOB_NAME, blob, handle, userId);
@@ -940,7 +962,9 @@ public class SyntheticPasswordManager {
return null;
}
final byte version = blob[0];
- if (version != SYNTHETIC_PASSWORD_VERSION && version != SYNTHETIC_PASSWORD_VERSION_V1) {
+ if (version != SYNTHETIC_PASSWORD_VERSION_V3
+ && version != SYNTHETIC_PASSWORD_VERSION_V2
+ && version != SYNTHETIC_PASSWORD_VERSION_V1) {
throw new RuntimeException("Unknown blob version");
}
if (blob[1] != type) {
@@ -958,7 +982,7 @@ public class SyntheticPasswordManager {
Log.e(TAG, "Fail to decrypt SP for user " + userId);
return null;
}
- AuthenticationToken result = new AuthenticationToken();
+ AuthenticationToken result = new AuthenticationToken(version);
if (type == SYNTHETIC_PASSWORD_TOKEN_BASED) {
if (!loadEscrowData(result, userId)) {
Log.e(TAG, "User is not escrowable: " + userId);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index c18a79fc183c..93b66208e752 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -923,7 +923,7 @@ public class MediaSessionService extends SystemService implements Monitor {
@Override
public void dispatchMediaKeyEvent(String packageName, boolean asSystemService,
KeyEvent keyEvent, boolean needWakeLock) {
- if (keyEvent == null || !KeyEvent.isMediaKey(keyEvent.getKeyCode())) {
+ if (keyEvent == null || !KeyEvent.isMediaSessionKey(keyEvent.getKeyCode())) {
Log.w(TAG, "Attempted to dispatch null or non-media key event.");
return;
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 7750c3781067..0d6dadfb1ad8 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -554,7 +554,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final Handler mHandler;
@VisibleForTesting
- public final Handler mUidEventHandler;
+ final Handler mUidEventHandler;
private final ServiceThread mUidEventThread;
@@ -1465,7 +1465,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@VisibleForTesting
- public void updateNetworks() throws InterruptedException {
+ void updateNetworks() throws InterruptedException {
updateNetworksInternal();
final CountDownLatch latch = new CountDownLatch(1);
mHandler.post(() -> {
@@ -1510,7 +1510,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* @return cycleDay to use in the mobile NetworkPolicy.
*/
@VisibleForTesting
- public int getCycleDayFromCarrierConfig(@Nullable PersistableBundle config,
+ int getCycleDayFromCarrierConfig(@Nullable PersistableBundle config,
int fallbackCycleDay) {
if (config == null) {
return fallbackCycleDay;
@@ -1542,7 +1542,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* @return warningBytes to use in the mobile NetworkPolicy.
*/
@VisibleForTesting
- public long getWarningBytesFromCarrierConfig(@Nullable PersistableBundle config,
+ long getWarningBytesFromCarrierConfig(@Nullable PersistableBundle config,
long fallbackWarningBytes) {
if (config == null) {
return fallbackWarningBytes;
@@ -1575,7 +1575,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* @return limitBytes to use in the mobile NetworkPolicy.
*/
@VisibleForTesting
- public long getLimitBytesFromCarrierConfig(@Nullable PersistableBundle config,
+ long getLimitBytesFromCarrierConfig(@Nullable PersistableBundle config,
long fallbackLimitBytes) {
if (config == null) {
return fallbackLimitBytes;
@@ -2039,7 +2039,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@VisibleForTesting
- public NetworkPolicy buildDefaultMobilePolicy(int subId, String subscriberId) {
+ NetworkPolicy buildDefaultMobilePolicy(int subId, String subscriberId) {
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
final RecurrenceRule cycleRule = NetworkPolicy
.buildRule(ZonedDateTime.now().getDayOfMonth(), ZoneId.systemDefault());
@@ -3489,7 +3489,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@VisibleForTesting
- public boolean isUidForeground(int uid) {
+ boolean isUidForeground(int uid) {
synchronized (mUidRulesFirstLock) {
return isUidStateForeground(
mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY));
@@ -3931,7 +3931,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* power saving restrictions may still apply.
*/
@VisibleForTesting
- public void setAppIdleWhitelist(int uid, boolean shouldWhitelist) {
+ void setAppIdleWhitelist(int uid, boolean shouldWhitelist) {
+ mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
+
synchronized (mUidRulesFirstLock) {
if (mAppIdleTempWhitelistAppIds.get(uid) == shouldWhitelist) {
// No change.
@@ -3956,7 +3958,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** Return the list of UIDs currently in the app idle whitelist. */
@VisibleForTesting
- public int[] getAppIdleWhitelist() {
+ int[] getAppIdleWhitelist() {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
synchronized (mUidRulesFirstLock) {
@@ -3971,7 +3973,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** Returns if the UID is currently considered idle. */
@VisibleForTesting
- public boolean isUidIdle(int uid) {
+ boolean isUidIdle(int uid) {
synchronized (mUidRulesFirstLock) {
if (mAppIdleTempWhitelistAppIds.get(uid)) {
// UID is temporarily whitelisted.
@@ -4844,13 +4846,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
@VisibleForTesting
- public void addIdleHandler(IdleHandler handler) {
+ void addIdleHandler(IdleHandler handler) {
mHandler.getLooper().getQueue().addIdleHandler(handler);
}
@GuardedBy("mUidRulesFirstLock")
@VisibleForTesting
- public void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
+ void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
mRestrictBackgroundPowerState = result;
boolean restrictBackground = result.batterySaverEnabled;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ae27d0c07ea8..6c2549e9b04d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -198,6 +198,7 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
@@ -206,6 +207,7 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.DeviceIdleController;
import com.android.server.EventLogTags;
+import com.android.server.IoThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.lights.Light;
@@ -264,11 +266,12 @@ public class NotificationManagerService extends SystemService {
// message codes
static final int MESSAGE_DURATION_REACHED = 2;
- static final int MESSAGE_SAVE_POLICY_FILE = 3;
+ // 3: removed to a different handler
static final int MESSAGE_SEND_RANKING_UPDATE = 4;
static final int MESSAGE_LISTENER_HINTS_CHANGED = 5;
static final int MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED = 6;
static final int MESSAGE_FINISH_TOKEN_TIMEOUT = 7;
+ static final int MESSAGE_ON_PACKAGE_CHANGED = 8;
// ranking thread messages
private static final int MESSAGE_RECONSIDER_RANKING = 1000;
@@ -570,7 +573,7 @@ public class NotificationManagerService extends SystemService {
mListeners.migrateToXml();
mAssistants.migrateToXml();
mConditionProviders.migrateToXml();
- savePolicyFile();
+ handleSavePolicyFile();
}
mAssistants.ensureAssistant();
@@ -600,31 +603,28 @@ public class NotificationManagerService extends SystemService {
}
}
- public void savePolicyFile() {
- mHandler.removeMessages(MESSAGE_SAVE_POLICY_FILE);
- mHandler.sendEmptyMessage(MESSAGE_SAVE_POLICY_FILE);
- }
-
private void handleSavePolicyFile() {
- if (DBG) Slog.d(TAG, "handleSavePolicyFile");
- synchronized (mPolicyFile) {
- final FileOutputStream stream;
- try {
- stream = mPolicyFile.startWrite();
- } catch (IOException e) {
- Slog.w(TAG, "Failed to save policy file", e);
- return;
- }
+ IoThread.getHandler().post(() -> {
+ if (DBG) Slog.d(TAG, "handleSavePolicyFile");
+ synchronized (mPolicyFile) {
+ final FileOutputStream stream;
+ try {
+ stream = mPolicyFile.startWrite();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to save policy file", e);
+ return;
+ }
- try {
- writePolicyXml(stream, false /*forBackup*/);
- mPolicyFile.finishWrite(stream);
- } catch (IOException e) {
- Slog.w(TAG, "Failed to save policy file, restoring backup", e);
- mPolicyFile.failWrite(stream);
+ try {
+ writePolicyXml(stream, false /*forBackup*/);
+ mPolicyFile.finishWrite(stream);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to save policy file, restoring backup", e);
+ mPolicyFile.failWrite(stream);
+ }
}
- }
- BackupManager.dataChanged(getContext().getPackageName());
+ BackupManager.dataChanged(getContext().getPackageName());
+ });
}
private void writePolicyXml(OutputStream stream, boolean forBackup) throws IOException {
@@ -1133,12 +1133,7 @@ public class NotificationManagerService extends SystemService {
}
}
- mListeners.onPackagesChanged(removingPackage, pkgList, uidList);
- mAssistants.onPackagesChanged(removingPackage, pkgList, uidList);
- mConditionProviders.onPackagesChanged(removingPackage, pkgList, uidList);
- mPreferencesHelper.onPackagesChanged(
- removingPackage, changeUserId, pkgList, uidList);
- savePolicyFile();
+ mHandler.scheduleOnPackageChanged(removingPackage, changeUserId, pkgList, uidList);
}
}
};
@@ -1205,7 +1200,7 @@ public class NotificationManagerService extends SystemService {
mListeners.onUserRemoved(userId);
mConditionProviders.onUserRemoved(userId);
mAssistants.onUserRemoved(userId);
- savePolicyFile();
+ handleSavePolicyFile();
} else if (action.equals(Intent.ACTION_USER_UNLOCKED)) {
final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
mUserProfiles.updateCache(context);
@@ -1456,7 +1451,7 @@ public class NotificationManagerService extends SystemService {
mZenModeHelper.addCallback(new ZenModeHelper.Callback() {
@Override
public void onConfigChanged() {
- savePolicyFile();
+ handleSavePolicyFile();
}
@Override
@@ -1755,7 +1750,7 @@ public class NotificationManagerService extends SystemService {
modifiedChannel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
}
- savePolicyFile();
+ handleSavePolicyFile();
}
private void maybeNotifyChannelOwner(String pkg, int uid, NotificationChannel preUpdate,
@@ -2223,7 +2218,7 @@ public class NotificationManagerService extends SystemService {
Slog.w(TAG, "Can't notify app about app block change", e);
}
- savePolicyFile();
+ handleSavePolicyFile();
}
/**
@@ -2280,7 +2275,7 @@ public class NotificationManagerService extends SystemService {
public void setShowBadge(String pkg, int uid, boolean showBadge) {
checkCallerIsSystem();
mPreferencesHelper.setShowBadge(pkg, uid, showBadge);
- savePolicyFile();
+ handleSavePolicyFile();
}
@Override
@@ -2296,7 +2291,7 @@ public class NotificationManagerService extends SystemService {
if (info != null) {
mPreferencesHelper.setNotificationDelegate(
callingPkg, callingUid, delegate, info.uid);
- savePolicyFile();
+ handleSavePolicyFile();
}
} catch (RemoteException e) {
// :(
@@ -2307,7 +2302,7 @@ public class NotificationManagerService extends SystemService {
public void revokeNotificationDelegate(String callingPkg) {
checkCallerIsSameApp(callingPkg);
mPreferencesHelper.revokeNotificationDelegate(callingPkg, Binder.getCallingUid());
- savePolicyFile();
+ handleSavePolicyFile();
}
@Override
@@ -2342,7 +2337,7 @@ public class NotificationManagerService extends SystemService {
NotificationChannelGroup group) throws RemoteException {
enforceSystemOrSystemUI("Caller not system or systemui");
createNotificationChannelGroup(pkg, uid, group, false, false);
- savePolicyFile();
+ handleSavePolicyFile();
}
@Override
@@ -2355,7 +2350,7 @@ public class NotificationManagerService extends SystemService {
final NotificationChannelGroup group = groups.get(i);
createNotificationChannelGroup(pkg, Binder.getCallingUid(), group, true, false);
}
- savePolicyFile();
+ handleSavePolicyFile();
}
private void createNotificationChannelsImpl(String pkg, int uid,
@@ -2373,7 +2368,7 @@ public class NotificationManagerService extends SystemService {
mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(), false),
NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
}
- savePolicyFile();
+ handleSavePolicyFile();
}
@Override
@@ -2418,7 +2413,7 @@ public class NotificationManagerService extends SystemService {
UserHandle.getUserHandleForUid(callingUid),
mPreferencesHelper.getNotificationChannel(pkg, callingUid, channelId, true),
NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
- savePolicyFile();
+ handleSavePolicyFile();
}
@Override
@@ -2460,7 +2455,7 @@ public class NotificationManagerService extends SystemService {
mListeners.notifyNotificationChannelGroupChanged(
pkg, UserHandle.getUserHandleForUid(callingUid), groupToDelete,
NOTIFICATION_CHANNEL_OR_GROUP_DELETED);
- savePolicyFile();
+ handleSavePolicyFile();
}
}
@@ -2593,7 +2588,7 @@ public class NotificationManagerService extends SystemService {
true, UserHandle.getCallingUserId(), packages, uids);
}
- savePolicyFile();
+ handleSavePolicyFile();
}
@@ -3381,7 +3376,7 @@ public class NotificationManagerService extends SystemService {
final ByteArrayInputStream bais = new ByteArrayInputStream(payload);
try {
readPolicyXml(bais, true /*forRestore*/);
- savePolicyFile();
+ handleSavePolicyFile();
} catch (NumberFormatException | XmlPullParserException | IOException e) {
Slog.w(TAG, "applyRestore: error reading payload", e);
}
@@ -3422,7 +3417,7 @@ public class NotificationManagerService extends SystemService {
.setPackage(pkg)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
UserHandle.of(userId), null);
- savePolicyFile();
+ handleSavePolicyFile();
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -3566,7 +3561,7 @@ public class NotificationManagerService extends SystemService {
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
UserHandle.of(userId), null);
- savePolicyFile();
+ handleSavePolicyFile();
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -3592,7 +3587,7 @@ public class NotificationManagerService extends SystemService {
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY),
UserHandle.of(userId), null);
- savePolicyFile();
+ handleSavePolicyFile();
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -3675,7 +3670,7 @@ public class NotificationManagerService extends SystemService {
verifyPrivilegedListener(token, user, false);
createNotificationChannelGroup(
pkg, getUidForPackageAndUser(pkg, user), group, false, true);
- savePolicyFile();
+ handleSavePolicyFile();
}
@Override
@@ -3724,7 +3719,7 @@ public class NotificationManagerService extends SystemService {
}
if (allow != mLockScreenAllowSecureNotifications) {
mLockScreenAllowSecureNotifications = allow;
- savePolicyFile();
+ handleSavePolicyFile();
}
}
@@ -4247,18 +4242,7 @@ public class NotificationManagerService extends SystemService {
// Fix the notification as best we can.
try {
- final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
- pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
- (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
- Notification.addFieldsFromContext(ai, notification);
-
- int canColorize = mPackageManagerClient.checkPermission(
- android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, pkg);
- if (canColorize == PERMISSION_GRANTED) {
- notification.flags |= Notification.FLAG_CAN_COLORIZE;
- } else {
- notification.flags &= ~Notification.FLAG_CAN_COLORIZE;
- }
+ fixNotification(notification, pkg, userId);
} catch (NameNotFoundException e) {
Slog.e(TAG, "Cannot create a context for sending app", e);
@@ -4359,6 +4343,33 @@ public class NotificationManagerService extends SystemService {
mHandler.post(new EnqueueNotificationRunnable(userId, r));
}
+ @VisibleForTesting
+ protected void fixNotification(Notification notification, String pkg, int userId)
+ throws NameNotFoundException {
+ final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
+ pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
+ Notification.addFieldsFromContext(ai, notification);
+
+ int canColorize = mPackageManagerClient.checkPermission(
+ android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, pkg);
+ if (canColorize == PERMISSION_GRANTED) {
+ notification.flags |= Notification.FLAG_CAN_COLORIZE;
+ } else {
+ notification.flags &= ~Notification.FLAG_CAN_COLORIZE;
+ }
+
+ if (ai.targetSdkVersion >= Build.VERSION_CODES.Q) {
+ int fullscreenIntentPermission = mPackageManagerClient.checkPermission(
+ android.Manifest.permission.USE_FULL_SCREEN_INTENT, pkg);
+ if (fullscreenIntentPermission != PERMISSION_GRANTED) {
+ notification.fullScreenIntent = null;
+ Log.w(TAG, "Package " + pkg +
+ ": Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission");
+ }
+ }
+ }
+
private void doChannelWarningToast(CharSequence toastText) {
Binder.withCleanCallingIdentity(() -> {
final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
@@ -4467,7 +4478,7 @@ public class NotificationManagerService extends SystemService {
Slog.d(TAG, "Ignored enqueue for snoozed notification " + r.getKey());
}
mSnoozeHelper.update(userId, r);
- savePolicyFile();
+ handleSavePolicyFile();
return false;
}
@@ -4598,7 +4609,7 @@ public class NotificationManagerService extends SystemService {
mSnoozeHelper.snooze(r, mDuration);
}
r.recordSnoozed();
- savePolicyFile();
+ handleSavePolicyFile();
}
}
@@ -4676,7 +4687,7 @@ public class NotificationManagerService extends SystemService {
if (mReason != REASON_SNOOZED) {
final boolean wasSnoozed = mSnoozeHelper.cancel(mUserId, mPkg, mTag, mId);
if (wasSnoozed) {
- savePolicyFile();
+ handleSavePolicyFile();
}
}
}
@@ -5691,6 +5702,16 @@ public class NotificationManagerService extends SystemService {
}
}
+ private void handleOnPackageChanged(boolean removingPackage, int changeUserId,
+ String[] pkgList, int[] uidList) {
+ mListeners.onPackagesChanged(removingPackage, pkgList, uidList);
+ mAssistants.onPackagesChanged(removingPackage, pkgList, uidList);
+ mConditionProviders.onPackagesChanged(removingPackage, pkgList, uidList);
+ mPreferencesHelper.onPackagesChanged(
+ removingPackage, changeUserId, pkgList, uidList);
+ handleSavePolicyFile();
+ }
+
protected class WorkerHandler extends Handler
{
public WorkerHandler(Looper looper) {
@@ -5703,13 +5724,10 @@ public class NotificationManagerService extends SystemService {
switch (msg.what)
{
case MESSAGE_DURATION_REACHED:
- handleDurationReached((ToastRecord)msg.obj);
+ handleDurationReached((ToastRecord) msg.obj);
break;
case MESSAGE_FINISH_TOKEN_TIMEOUT:
- handleKillTokenTimeout((ToastRecord)msg.obj);
- break;
- case MESSAGE_SAVE_POLICY_FILE:
- handleSavePolicyFile();
+ handleKillTokenTimeout((ToastRecord) msg.obj);
break;
case MESSAGE_SEND_RANKING_UPDATE:
handleSendRankingUpdate();
@@ -5720,6 +5738,12 @@ public class NotificationManagerService extends SystemService {
case MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED:
handleListenerInterruptionFilterChanged(msg.arg1);
break;
+ case MESSAGE_ON_PACKAGE_CHANGED:
+ SomeArgs args = (SomeArgs) msg.obj;
+ handleOnPackageChanged((boolean) args.arg1, args.argi1, (String[]) args.arg2,
+ (int[]) args.arg3);
+ args.recycle();
+ break;
}
}
@@ -5735,6 +5759,16 @@ public class NotificationManagerService extends SystemService {
sendMessage(Message.obtain(this, cancelRunnable));
}
}
+
+ protected void scheduleOnPackageChanged(boolean removingPackage, int changeUserId,
+ String[] pkgList, int[] uidList) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = removingPackage;
+ args.argi1 = changeUserId;
+ args.arg2 = pkgList;
+ args.arg3 = uidList;
+ sendMessage(Message.obtain(this, MESSAGE_ON_PACKAGE_CHANGED, args));
+ }
}
private final class RankingHandlerWorker extends Handler implements RankingHandler
@@ -6212,7 +6246,7 @@ public class NotificationManagerService extends SystemService {
Slog.d(TAG, String.format("unsnooze event(%s, %s)", key, listenerName));
}
mSnoozeHelper.repost(key);
- savePolicyFile();
+ handleSavePolicyFile();
}
@GuardedBy("mNotificationLock")
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index f279af03753e..94d276c8496d 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -309,6 +309,7 @@ public class ZenModeHelper {
newConfig = mConfig.copy();
ZenRule rule = new ZenRule();
populateZenRule(automaticZenRule, rule, true);
+ newConfig.automaticRules.put(rule.id, rule);
if (setConfigLocked(newConfig, reason, rule.component, true)) {
return rule.id;
} else {
diff --git a/services/core/java/com/android/server/oemlock/OemLock.java b/services/core/java/com/android/server/oemlock/OemLock.java
index ee70c29b7da4..352884b606a0 100644
--- a/services/core/java/com/android/server/oemlock/OemLock.java
+++ b/services/core/java/com/android/server/oemlock/OemLock.java
@@ -19,6 +19,9 @@ package com.android.server.oemlock;
import android.annotation.Nullable;
abstract class OemLock {
+ @Nullable
+ abstract String getLockName();
+
abstract void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature);
abstract boolean isOemUnlockAllowedByCarrier();
diff --git a/services/core/java/com/android/server/oemlock/OemLockService.java b/services/core/java/com/android/server/oemlock/OemLockService.java
index a6200bf433e4..6e82c24a6e9b 100644
--- a/services/core/java/com/android/server/oemlock/OemLockService.java
+++ b/services/core/java/com/android/server/oemlock/OemLockService.java
@@ -113,6 +113,19 @@ public class OemLockService extends SystemService {
*/
private final IBinder mService = new IOemLockService.Stub() {
@Override
+ @Nullable
+ public String getLockName() {
+ enforceManageCarrierOemUnlockPermission();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mOemLock.getLockName();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
enforceManageCarrierOemUnlockPermission();
enforceUserIsAdmin();
diff --git a/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java b/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java
index d9362d4b0f28..a1c27d6432f1 100644
--- a/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java
+++ b/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java
@@ -40,6 +40,12 @@ class PersistentDataBlockLock extends OemLock {
}
@Override
+ @Nullable
+ String getLockName() {
+ return "";
+ }
+
+ @Override
void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
// Note: this implementation does not require a signature
if (signature != null) {
diff --git a/services/core/java/com/android/server/oemlock/VendorLock.java b/services/core/java/com/android/server/oemlock/VendorLock.java
index 1b9de3612367..37540d039b9e 100644
--- a/services/core/java/com/android/server/oemlock/VendorLock.java
+++ b/services/core/java/com/android/server/oemlock/VendorLock.java
@@ -22,8 +22,6 @@ import android.hardware.oemlock.V1_0.IOemLock;
import android.hardware.oemlock.V1_0.OemLockSecureStatus;
import android.hardware.oemlock.V1_0.OemLockStatus;
import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.util.Slog;
import java.util.ArrayList;
@@ -55,14 +53,49 @@ class VendorLock extends OemLock {
}
@Override
+ @Nullable
+ String getLockName() {
+ final Integer[] requestStatus = new Integer[1];
+ final String[] lockName = new String[1];
+
+ try {
+ mOemLock.getName((status, name) -> {
+ requestStatus[0] = status;
+ lockName[0] = name;
+ });
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to get name from HAL", e);
+ throw e.rethrowFromSystemServer();
+ }
+
+ switch (requestStatus[0]) {
+ case OemLockStatus.OK:
+ // Success
+ return lockName[0];
+
+ case OemLockStatus.FAILED:
+ Slog.e(TAG, "Failed to get OEM lock name.");
+ return null;
+
+ default:
+ Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
+ return null;
+ }
+ }
+
+ @Override
void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
try {
- switch (mOemLock.setOemUnlockAllowedByCarrier(allowed, toByteArrayList(signature))) {
+ ArrayList<Byte> signatureBytes = toByteArrayList(signature);
+ switch (mOemLock.setOemUnlockAllowedByCarrier(allowed, signatureBytes)) {
case OemLockSecureStatus.OK:
Slog.i(TAG, "Updated carrier allows OEM lock state to: " + allowed);
return;
case OemLockSecureStatus.INVALID_SIGNATURE:
+ if (signatureBytes.isEmpty()) {
+ throw new IllegalArgumentException("Signature required for carrier unlock");
+ }
throw new SecurityException(
"Invalid signature used in attempt to carrier unlock");
@@ -154,9 +187,9 @@ class VendorLock extends OemLock {
}
}
- private ArrayList toByteArrayList(byte[] data) {
+ private ArrayList<Byte> toByteArrayList(byte[] data) {
if (data == null) {
- return null;
+ return new ArrayList<Byte>();
}
ArrayList<Byte> result = new ArrayList<Byte>(data.length);
for (final byte b : data) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1045289ca5c1..8abb5000d544 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -116,8 +116,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS;
-import static com.android.server.pm.permission.PermissionsState
- .PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
+import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
import android.Manifest;
import android.annotation.IntDef;
@@ -197,6 +196,7 @@ import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
import android.content.pm.SuspendDialogInfo;
import android.content.pm.UserInfo;
+import android.content.pm.UsesPermissionInfo;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierInfo;
import android.content.pm.VersionedPackage;
@@ -313,8 +313,7 @@ import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.dex.PackageDexUsage;
import com.android.server.pm.permission.BasePermission;
import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
-import com.android.server.pm.permission.DefaultPermissionGrantPolicy
- .DefaultPermissionGrantedCallback;
+import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
import com.android.server.pm.permission.PermissionManagerInternal;
import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
import com.android.server.pm.permission.PermissionManagerService;
@@ -373,6 +372,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import java.util.function.Predicate;
/**
@@ -11242,6 +11242,26 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
}
+
+ // Check permission usage info requirements.
+ if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
+ for (UsesPermissionInfo upi : pkg.usesPermissionInfos) {
+ if (!mPermissionManager.isPermissionUsageInfoRequired(upi.getPermission())) {
+ continue;
+ }
+ if (upi.getDataSentOffDevice() == UsesPermissionInfo.USAGE_UNDEFINED
+ || upi.getDataSharedWithThirdParty()
+ == UsesPermissionInfo.USAGE_UNDEFINED
+ || upi.getDataUsedForMonetization()
+ == UsesPermissionInfo.USAGE_UNDEFINED
+ || upi.getDataRetention() == UsesPermissionInfo.RETENTION_UNDEFINED) {
+ // STOPSHIP: Make this throw
+ Slog.wtf(TAG, "Package " + pkg.packageName + " does not provide usage "
+ + "information for permission " + upi.getPermission()
+ + ". This will be a fatal error in Q.");
+ }
+ }
+ }
}
}
@@ -15246,7 +15266,8 @@ public class PackageManagerService extends IPackageManager.Stub
"inputs not balanced; missing argument for " + installPackageName);
}
final DeletePackageAction deletePackageAction;
- if (prepareResult.replace) {
+ // we only want to try to delete for non system apps
+ if (prepareResult.replace && !prepareResult.system) {
deletePackageAction = mayDeletePackageLocked(res.removedInfo,
prepareResult.originalPs, prepareResult.disabledPs,
prepareResult.childPackageSettings);
@@ -17818,7 +17839,7 @@ public class PackageManagerService extends IPackageManager.Stub
return null;
}
if (isSystemApp(ps)) {
- if (ps.parentPackageName == null) {
+ if (ps.parentPackageName != null) {
Slog.w(TAG, "Attempt to delete child system package " + ps.pkg.packageName);
return null;
}
@@ -20114,7 +20135,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (Process.isIsolated(uid)) {
return Zygote.MOUNT_EXTERNAL_NONE;
}
- if (SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+ if (StorageManager.hasIsolatedStorage()) {
return checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED
? Zygote.MOUNT_EXTERNAL_FULL
: Zygote.MOUNT_EXTERNAL_WRITE;
@@ -23185,6 +23206,45 @@ public class PackageManagerService extends IPackageManager.Stub
throws IOException {
PackageManagerService.this.freeStorage(volumeUuid, bytes, storageFlags);
}
+
+ @Override
+ public void forEachPackage(Consumer<PackageParser.Package> actionLocked) {
+ PackageManagerService.this.forEachPackage(actionLocked);
+ }
+
+ @Override
+ public ArraySet<String> getEnabledComponents(String packageName, int userId) {
+ synchronized (mPackages) {
+ PackageSetting setting = mSettings.getPackageLPr(packageName);
+ if (setting == null) {
+ return new ArraySet<>();
+ }
+ return setting.getEnabledComponents(userId);
+ }
+ }
+
+ @Override
+ public ArraySet<String> getDisabledComponents(String packageName, int userId) {
+ synchronized (mPackages) {
+ PackageSetting setting = mSettings.getPackageLPr(packageName);
+ if (setting == null) {
+ return new ArraySet<>();
+ }
+ return setting.getDisabledComponents(userId);
+ }
+ }
+
+ @Override
+ public @PackageManager.EnabledState int getApplicationEnabledState(
+ String packageName, int userId) {
+ synchronized (mPackages) {
+ PackageSetting setting = mSettings.getPackageLPr(packageName);
+ if (setting == null) {
+ return COMPONENT_ENABLED_STATE_DEFAULT;
+ }
+ return setting.getEnabled(userId);
+ }
+ }
}
@GuardedBy("mPackages")
@@ -23307,6 +23367,15 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
+ void forEachPackage(Consumer<PackageParser.Package> actionLocked) {
+ synchronized (mPackages) {
+ int numPackages = mPackages.size();
+ for (int i = 0; i < numPackages; i++) {
+ actionLocked.accept(mPackages.valueAt(i));
+ }
+ }
+ }
+
private static void enforceSystemOrPhoneCaller(String tag) {
int callingUid = Binder.getCallingUid();
if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) {
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index e194d1541ea7..2d583ca39adb 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -105,6 +105,8 @@ public final class BasePermission {
*/
private boolean perUser;
+ boolean usageInfoRequired;
+
public BasePermission(String _name, String _sourcePackageName, @PermissionType int _type) {
name = _name;
sourcePackageName = _sourcePackageName;
@@ -351,6 +353,7 @@ public final class BasePermission {
}
if (bp.perm == p) {
bp.protectionLevel = p.info.protectionLevel;
+ bp.usageInfoRequired = p.info.usageInfoRequired;
}
if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
Log.d(TAG, " Permissions: " + r);
@@ -430,6 +433,7 @@ public final class BasePermission {
permissionInfo.packageName = sourcePackageName;
permissionInfo.nonLocalizedLabel = name;
permissionInfo.protectionLevel = protectionLevel;
+ permissionInfo.usageInfoRequired = usageInfoRequired;
return permissionInfo;
}
@@ -458,6 +462,7 @@ public final class BasePermission {
bp.protectionLevel = readInt(parser, null, "protection",
PermissionInfo.PROTECTION_NORMAL);
bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel);
+ bp.usageInfoRequired = readInt(parser, null, "usageInfoRequired", 0) != 0;
if (dynamic) {
final PermissionInfo pi = new PermissionInfo();
pi.packageName = sourcePackage.intern();
@@ -465,6 +470,7 @@ public final class BasePermission {
pi.icon = readInt(parser, null, "icon", 0);
pi.nonLocalizedLabel = parser.getAttributeValue(null, "label");
pi.protectionLevel = bp.protectionLevel;
+ pi.usageInfoRequired = bp.usageInfoRequired;
bp.pendingPermissionInfo = pi;
}
out.put(bp.name, bp);
@@ -497,6 +503,7 @@ public final class BasePermission {
if (protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
serializer.attribute(null, "protection", Integer.toString(protectionLevel));
}
+ serializer.attribute(null, "usageInfoRequired", usageInfoRequired ? "1" : "0");
if (type == BasePermission.TYPE_DYNAMIC) {
final PermissionInfo pi = perm != null ? perm.info : pendingPermissionInfo;
if (pi != null) {
@@ -533,6 +540,7 @@ public final class BasePermission {
if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
// We'll take care of setting this one.
if (!compareStrings(pi1.packageName, pi2.packageName)) return false;
+ if (pi1.usageInfoRequired != pi2.usageInfoRequired) return false;
// These are not currently stored in settings.
//if (!compareStrings(pi1.group, pi2.group)) return false;
//if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false;
@@ -580,6 +588,8 @@ public final class BasePermission {
pw.print(" enforced=");
pw.println(readEnforced);
}
+ pw.print(" usageInfoRequired=");
+ pw.println(usageInfoRequired);
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 21cc14e20bc7..68fe1d8a05f8 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -144,6 +144,11 @@ public final class DefaultPermissionGrantPolicy {
LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
}
+ private static final Set<String> ACTIVITY_RECOGNITION_PERMISSIONS = new ArraySet<>();
+ static {
+ ACTIVITY_RECOGNITION_PERMISSIONS.add(Manifest.permission.ACTIVITY_RECOGNITION);
+ }
+
private static final Set<String> COARSE_LOCATION_PERMISSIONS = new ArraySet<>();
static {
COARSE_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
@@ -184,7 +189,7 @@ public final class DefaultPermissionGrantPolicy {
private static final Set<String> STORAGE_PERMISSIONS = new ArraySet<>();
static {
// STOPSHIP(b/112545973): remove once feature enabled by default
- if (!SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+ if (!StorageManager.hasIsolatedStorage()) {
STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
@@ -193,7 +198,7 @@ public final class DefaultPermissionGrantPolicy {
private static final Set<String> MEDIA_AURAL_PERMISSIONS = new ArraySet<>();
static {
// STOPSHIP(b/112545973): remove once feature enabled by default
- if (SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+ if (StorageManager.hasIsolatedStorage()) {
MEDIA_AURAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_AUDIO);
}
}
@@ -201,7 +206,7 @@ public final class DefaultPermissionGrantPolicy {
private static final Set<String> MEDIA_VISUAL_PERMISSIONS = new ArraySet<>();
static {
// STOPSHIP(b/112545973): remove once feature enabled by default
- if (SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false)) {
+ if (StorageManager.hasIsolatedStorage()) {
MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VIDEO);
MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_IMAGES);
}
@@ -624,7 +629,7 @@ public final class DefaultPermissionGrantPolicy {
PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
SENSORS_PERMISSIONS, STORAGE_PERMISSIONS);
grantSystemFixedPermissionsToSystemPackage(packageName, userId,
- LOCATION_PERMISSIONS);
+ LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
}
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
index ec15c16981a8..189d0f476a8c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerInternal.java
@@ -181,4 +181,9 @@ public abstract class PermissionManagerInternal {
/** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
-} \ No newline at end of file
+
+ /**
+ * Returns {@code true} if {@code permName} has {@code usageInfoRequired} set.
+ */
+ public abstract boolean isPermissionUsageInfoRequired(@NonNull String permName);
+}
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 c5d38db2c469..4406fdde6454 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2644,5 +2644,12 @@ public class PermissionManagerService {
return mSettings.getPermissionLocked(permName);
}
}
+ @Override
+ public boolean isPermissionUsageInfoRequired(String permName) {
+ synchronized (PermissionManagerService.this.mLock) {
+ BasePermission bp = mSettings.getPermissionLocked(permName);
+ return bp != null && bp.usageInfoRequired;
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index b390eebf3d7e..b065470fe98c 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -30,20 +30,27 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.Signature;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.PackageUtils;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.BitUtils;
+import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.FunctionalUtils;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Collections;
@@ -117,13 +124,18 @@ public class RoleManagerService extends SystemService {
@Override
public void onStartUser(@UserIdInt int userId) {
+ RoleUserState userState;
synchronized (mLock) {
- //TODO only call into PermissionController if it or system upgreaded (for boot time)
- getUserStateLocked(userId);
+ userState = getUserStateLocked(userId);
}
- //TODO consider calling grants only when certain conditions are met
- // such as OS or PermissionController upgrade
- if (RemoteRoleControllerService.DEBUG) {
+ String packagesHash = computeComponentStateHash(userId);
+ boolean needGrant;
+ synchronized (mLock) {
+ needGrant = !packagesHash.equals(userState.getLastGrantPackagesHashLocked());
+ }
+ if (needGrant) {
+ // Some vital packages state has changed since last role grant
+ // Run grants again
Slog.i(LOG_TAG, "Granting default permissions...");
CompletableFuture<Void> result = new CompletableFuture<>();
getControllerService(userId).onGrantDefaultRoles(
@@ -140,12 +152,47 @@ public class RoleManagerService extends SystemService {
});
try {
result.get(5, TimeUnit.SECONDS);
+ synchronized (mLock) {
+ userState.setLastGrantPackagesHashLocked(packagesHash);
+ }
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
}
+ } else if (RemoteRoleControllerService.DEBUG) {
+ Slog.i(LOG_TAG, "Already ran grants for package state " + packagesHash);
}
}
+ private String computeComponentStateHash(int userId) {
+ PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ pm.forEachPackage(FunctionalUtils.uncheckExceptions(pkg -> {
+ out.write(pkg.packageName.getBytes());
+ out.write(BitUtils.toBytes(pkg.getLongVersionCode()));
+ out.write(pm.getApplicationEnabledState(pkg.packageName, userId));
+
+ ArraySet<String> enabledComponents =
+ pm.getEnabledComponents(pkg.packageName, userId);
+ int numComponents = CollectionUtils.size(enabledComponents);
+ for (int i = 0; i < numComponents; i++) {
+ out.write(enabledComponents.valueAt(i).getBytes());
+ }
+
+ ArraySet<String> disabledComponents =
+ pm.getDisabledComponents(pkg.packageName, userId);
+ numComponents = CollectionUtils.size(disabledComponents);
+ for (int i = 0; i < numComponents; i++) {
+ out.write(disabledComponents.valueAt(i).getBytes());
+ }
+ for (Signature signature : pkg.mSigningDetails.signatures) {
+ out.write(signature.toByteArray());
+ }
+ }));
+
+ return PackageUtils.computeSha256Digest(out.toByteArray());
+ }
+
@GuardedBy("mLock")
@NonNull
private RoleUserState getUserStateLocked(@UserIdInt int userId) {
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index 9c43f4d02ad0..f218d3a5834b 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -31,6 +31,7 @@ import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.CollectionUtils;
import com.android.internal.util.function.pooled.PooledLambda;
import libcore.io.IoUtils;
@@ -63,6 +64,7 @@ public class RoleUserState {
private static final String TAG_HOLDER = "holder";
private static final String ATTRIBUTE_VERSION = "version";
private static final String ATTRIBUTE_NAME = "name";
+ private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash";
@UserIdInt
private final int mUserId;
@@ -70,11 +72,15 @@ public class RoleUserState {
@GuardedBy("RoleManagerService.mLock")
private int mVersion;
+ @GuardedBy("RoleManagerService.mLock")
+ private String mLastGrantPackagesHash = null;
+
/**
* Maps role names to its holders' package names. The values should never be null.
*/
@GuardedBy("RoleManagerService.mLock")
- private ArrayMap<String, ArraySet<String>> mRoles;
+ @Nullable
+ private ArrayMap<String, ArraySet<String>> mRoles = null;
@GuardedBy("RoleManagerService.mLock")
private boolean mDestroyed;
@@ -110,6 +116,23 @@ public class RoleUserState {
}
/**
+ * Get the hash representing the state of packages during the last time initial grants was run
+ */
+ @GuardedBy("RoleManagerService.mLock")
+ public String getLastGrantPackagesHashLocked() {
+ return mLastGrantPackagesHash;
+ }
+
+ /**
+ * Set the hash representing the state of packages during the last time initial grants was run
+ */
+ @GuardedBy("RoleManagerService.mLock")
+ public void setLastGrantPackagesHashLocked(String lastGrantPackagesHash) {
+ mLastGrantPackagesHash = lastGrantPackagesHash;
+ writeAsyncLocked();
+ }
+
+ /**
* Get whether the role is available.
*
* @param roleName the name of the role to get the holders for
@@ -227,11 +250,11 @@ public class RoleUserState {
* Schedule writing the state to file.
*/
@GuardedBy("RoleManagerService.mLock")
- private void writeAsyncLocked() {
+ void writeAsyncLocked() {
throwIfDestroyedLocked();
int version = mVersion;
ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>();
- for (int i = 0, size = mRoles.size(); i < size; ++i) {
+ for (int i = 0, size = CollectionUtils.size(mRoles); i < size; ++i) {
String roleName = mRoles.keyAt(i);
ArraySet<String> roleHolders = mRoles.valueAt(i);
roleHolders = new ArraySet<>(roleHolders);
@@ -240,11 +263,12 @@ public class RoleUserState {
mWriteHandler.removeCallbacksAndMessages(null);
// TODO: Throttle writes.
mWriteHandler.sendMessage(PooledLambda.obtainMessage(
- RoleUserState::writeSync, this, version, roles));
+ RoleUserState::writeSync, this, version, roles, mLastGrantPackagesHash));
}
@WorkerThread
- private void writeSync(int version, @NonNull ArrayMap<String, ArraySet<String>> roles) {
+ private void writeSync(int version, @NonNull ArrayMap<String, ArraySet<String>> roles,
+ String packagesHash) {
AtomicFile atomicFile = new AtomicFile(getFile(mUserId), "roles-" + mUserId);
FileOutputStream out = null;
try {
@@ -256,7 +280,7 @@ public class RoleUserState {
"http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startDocument(null, true);
- serializeRoles(serializer, version, roles);
+ serializeRoles(serializer, version, roles, packagesHash);
serializer.endDocument();
atomicFile.finishWrite(out);
@@ -272,9 +296,11 @@ public class RoleUserState {
@WorkerThread
private void serializeRoles(@NonNull XmlSerializer serializer, int version,
- @NonNull ArrayMap<String, ArraySet<String>> roles) throws IOException {
+ @NonNull ArrayMap<String, ArraySet<String>> roles, String packagesHash)
+ throws IOException {
serializer.startTag(null, TAG_ROLES);
serializer.attribute(null, ATTRIBUTE_VERSION, Integer.toString(version));
+ serializer.attribute(null, ATTRIBUTE_PACKAGES_HASH, packagesHash);
for (int i = 0, size = roles.size(); i < size; ++i) {
String roleName = roles.keyAt(i);
ArraySet<String> roleHolders = roles.valueAt(i);
@@ -341,6 +367,7 @@ public class RoleUserState {
private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
XmlPullParserException {
mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
+ mLastGrantPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
mRoles = new ArrayMap<>();
int type;
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index aa11e1e3285c..f0ebb7512015 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -195,12 +195,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
"/system/bin/traced", // Perfetto.
"/system/bin/traced_probes", // Perfetto.
"webview_zygote",
- // Temporarily excluded zygote to investigate its forking consequences in
- // NativeProcessMemoryState.
- // "zygote",
- // "zygote64",
+ "zygote",
+ "zygote64",
};
+ private static final int CPU_TIME_PER_THREAD_FREQ_NUM_FREQUENCIES = 8;
static final class CompanionHandler extends Handler {
CompanionHandler(Looper looper) {
@@ -1080,7 +1079,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
e.writeLong(processMemoryState.rssInBytes);
e.writeLong(processMemoryState.cacheInBytes);
e.writeLong(processMemoryState.swapInBytes);
- e.writeLong(processMemoryState.rssHighWatermarkInBytes);
+ e.writeLong(0); // unused
e.writeLong(processMemoryState.startTimeNanos);
pulledData.add(e);
}
@@ -1089,6 +1088,7 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private void pullNativeProcessMemoryState(
int tagId, long elapsedNanos, long wallClockNanos,
List<StatsLogEventWrapper> pulledData) {
+ final List<String> processNames = Arrays.asList(MEMORY_INTERESTING_NATIVE_PROCESSES);
int[] pids = getPidsForCommands(MEMORY_INTERESTING_NATIVE_PROCESSES);
for (int i = 0; i < pids.length; i++) {
int pid = pids[i];
@@ -1098,13 +1098,19 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
int uid = getUidForPid(pid);
String processName = readCmdlineFromProcfs(pid);
+ // Sometimes we get here processName that is not included in the whitelist. It comes
+ // from forking the zygote for an app. We can ignore that sample because this process
+ // is collected by ProcessMemoryState.
+ if (!processNames.contains(processName)) {
+ continue;
+ }
StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
e.writeInt(uid);
e.writeString(processName);
e.writeLong(memoryStat.pgfault);
e.writeLong(memoryStat.pgmajfault);
e.writeLong(memoryStat.rssInBytes);
- e.writeLong(memoryStat.rssHighWatermarkInBytes);
+ e.writeLong(0); // unused
e.writeLong(memoryStat.startTimeNanos);
pulledData.add(e);
}
@@ -1654,6 +1660,11 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
return;
}
int[] cpuFrequencies = mKernelCpuThreadReader.getCpuFrequenciesKhz();
+ if (cpuFrequencies.length != CPU_TIME_PER_THREAD_FREQ_NUM_FREQUENCIES) {
+ Slog.w(TAG, "Expected " + CPU_TIME_PER_THREAD_FREQ_NUM_FREQUENCIES
+ + " frequencies, but got " + cpuFrequencies.length);
+ return;
+ }
for (int i = 0; i < processCpuUsages.size(); i++) {
KernelCpuThreadReader.ProcessCpuUsage processCpuUsage = processCpuUsages.get(i);
ArrayList<KernelCpuThreadReader.ThreadCpuUsage> threadCpuUsages =
@@ -1667,23 +1678,18 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
continue;
}
- for (int k = 0; k < threadCpuUsage.usageTimesMillis.length; k++) {
- // Do not report CPU usage at a frequency when it's zero
- if (threadCpuUsage.usageTimesMillis[k] == 0) {
- continue;
- }
-
- StatsLogEventWrapper e =
- new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
- e.writeInt(processCpuUsage.uid);
- e.writeInt(processCpuUsage.processId);
- e.writeInt(threadCpuUsage.threadId);
- e.writeString(processCpuUsage.processName);
- e.writeString(threadCpuUsage.threadName);
+ StatsLogEventWrapper e =
+ new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+ e.writeInt(processCpuUsage.uid);
+ e.writeInt(processCpuUsage.processId);
+ e.writeInt(threadCpuUsage.threadId);
+ e.writeString(processCpuUsage.processName);
+ e.writeString(threadCpuUsage.threadName);
+ for (int k = 0; k < CPU_TIME_PER_THREAD_FREQ_NUM_FREQUENCIES; k++) {
e.writeInt(cpuFrequencies[k]);
e.writeInt(threadCpuUsage.usageTimesMillis[k]);
- pulledData.add(e);
}
+ pulledData.add(e);
}
}
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 0d66a2c8b442..e645b84e83a0 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -24,7 +24,7 @@ import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Rect;
-import android.hardware.biometrics.IBiometricPromptReceiver;
+import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -598,8 +598,8 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
@Override
- public void showBiometricDialog(Bundle bundle, IBiometricPromptReceiver receiver, int type,
- boolean requireConfirmation, int userId) {
+ public void showBiometricDialog(Bundle bundle, IBiometricServiceReceiverInternal receiver,
+ int type, boolean requireConfirmation, int userId) {
enforceBiometricDialog();
if (mBar != null) {
try {
@@ -654,6 +654,17 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
@Override
+ public void showBiometricTryAgain() {
+ enforceBiometricDialog();
+ if (mBar != null) {
+ try {
+ mBar.showBiometricTryAgain();
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
public void disable(int what, IBinder token, String pkg) {
disableForUser(what, token, pkg, mCurrentUserId);
}
diff --git a/services/core/java/com/android/server/storage/AppFuseBridge.java b/services/core/java/com/android/server/storage/AppFuseBridge.java
index 6a0b6489f470..9d6a64701e85 100644
--- a/services/core/java/com/android/server/storage/AppFuseBridge.java
+++ b/services/core/java/com/android/server/storage/AppFuseBridge.java
@@ -16,6 +16,7 @@
package com.android.server.storage;
+import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.system.ErrnoException;
import android.system.Os;
@@ -25,8 +26,6 @@ import com.android.internal.os.FuseUnavailableMountException;
import com.android.internal.util.Preconditions;
import com.android.server.NativeDaemonConnectorException;
import libcore.io.IoUtils;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.util.concurrent.CountDownLatch;
/**
@@ -87,7 +86,7 @@ public class AppFuseBridge implements Runnable {
}
}
- public ParcelFileDescriptor openFile(int pid, int mountId, int fileId, int mode)
+ public ParcelFileDescriptor openFile(int mountId, int fileId, int mode)
throws FuseUnavailableMountException, InterruptedException {
final MountScope scope;
synchronized (this) {
@@ -96,17 +95,14 @@ public class AppFuseBridge implements Runnable {
throw new FuseUnavailableMountException(mountId);
}
}
- if (scope.pid != pid) {
- throw new SecurityException("PID does not match");
- }
final boolean result = scope.waitForMount();
if (result == false) {
throw new FuseUnavailableMountException(mountId);
}
try {
- return ParcelFileDescriptor.open(
- new File(scope.mountPoint, String.valueOf(fileId)), mode);
- } catch (FileNotFoundException error) {
+ int flags = FileUtils.translateModePfdToPosix(mode);
+ return scope.openFile(mountId, fileId, flags);
+ } catch (NativeDaemonConnectorException error) {
throw new FuseUnavailableMountException(mountId);
}
}
@@ -131,17 +127,13 @@ public class AppFuseBridge implements Runnable {
public static abstract class MountScope implements AutoCloseable {
public final int uid;
- public final int pid;
public final int mountId;
- public final File mountPoint;
private final CountDownLatch mMounted = new CountDownLatch(1);
private boolean mMountResult = false;
- public MountScope(int uid, int pid, int mountId) {
+ public MountScope(int uid, int mountId) {
this.uid = uid;
- this.pid = pid;
this.mountId = mountId;
- this.mountPoint = new File(String.format(APPFUSE_MOUNT_NAME_TEMPLATE, uid, mountId));
}
@GuardedBy("AppFuseBridge.this")
@@ -159,6 +151,8 @@ public class AppFuseBridge implements Runnable {
}
public abstract ParcelFileDescriptor open() throws NativeDaemonConnectorException;
+ public abstract ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
+ throws NativeDaemonConnectorException;
}
private native long native_new();
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 8d27d1e043a7..c8a68b44c796 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -402,7 +402,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
throws RemoteException {
try {
final int uid = context.getPackageManager()
- .getPackageUid(packageName, 0);
+ .getPackageUidAsUser(packageName, UserHandle.getCallingUserId());
Preconditions.checkArgument(Binder.getCallingUid() == uid);
} catch (IllegalArgumentException | NullPointerException |
PackageManager.NameNotFoundException e) {
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index d5e59c8dfd6a..1163d3916cb1 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -626,7 +626,7 @@ public final class TvInputManagerService extends SystemService {
updateServiceConnectionLocked(serviceState.component, userId);
}
- private void createSessionInternalLocked(ITvInputService service, IBinder sessionToken,
+ private boolean createSessionInternalLocked(ITvInputService service, IBinder sessionToken,
int userId) {
UserState userState = getOrCreateUserStateLocked(userId);
SessionState sessionState = userState.sessionStateMap.get(sessionToken);
@@ -638,6 +638,7 @@ public final class TvInputManagerService extends SystemService {
// Set up a callback to send the session token.
ITvInputSessionCallback callback = new SessionCallback(sessionState, channels);
+ boolean created = true;
// Create a session. When failed, send a null token immediately.
try {
if (sessionState.isRecordingSession) {
@@ -647,11 +648,12 @@ public final class TvInputManagerService extends SystemService {
}
} catch (RemoteException e) {
Slog.e(TAG, "error in createSession", e);
- removeSessionStateLocked(sessionToken, userId);
sendSessionTokenToClientLocked(sessionState.client, sessionState.inputId, null,
null, sessionState.seq);
+ created = false;
}
channels[1].dispose();
+ return created;
}
private void sendSessionTokenToClientLocked(ITvInputClient client, String inputId,
@@ -1193,8 +1195,10 @@ public final class TvInputManagerService extends SystemService {
serviceState.sessionTokens.add(sessionToken);
if (serviceState.service != null) {
- createSessionInternalLocked(serviceState.service, sessionToken,
- resolvedUserId);
+ if (!createSessionInternalLocked(serviceState.service, sessionToken,
+ resolvedUserId)) {
+ removeSessionStateLocked(sessionToken, resolvedUserId);
+ }
} else {
updateServiceConnectionLocked(info.getComponent(), resolvedUserId);
}
@@ -2282,9 +2286,17 @@ public final class TvInputManagerService extends SystemService {
}
}
+ List<IBinder> tokensToBeRemoved = new ArrayList<>();
+
// And create sessions, if any.
for (IBinder sessionToken : serviceState.sessionTokens) {
- createSessionInternalLocked(serviceState.service, sessionToken, mUserId);
+ if (!createSessionInternalLocked(serviceState.service, sessionToken, mUserId)) {
+ tokensToBeRemoved.add(sessionToken);
+ }
+ }
+
+ for (IBinder sessionToken : tokensToBeRemoved) {
+ removeSessionStateLocked(sessionToken, mUserId);
}
for (TvInputState inputState : userState.inputMap.values()) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 6ede423f63c8..cfec8effeede 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1181,7 +1181,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// TODO(multi-display) TBD.
if (mInfo != null && mInfo.supportsAmbientMode() && displayId == DEFAULT_DISPLAY) {
try {
- connector.mEngine.setInAmbientMode(mInAmbientMode, false /* animated */);
+ connector.mEngine.setInAmbientMode(mInAmbientMode, 0L /* duration */);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to set ambient mode state", e);
}
@@ -2023,11 +2023,17 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
- // TODO(b/115486823) Extends this method with specific display.
- public void setInAmbientMode(boolean inAmbienMode, boolean animated) {
+ /**
+ * TODO(b/115486823) Extends this method with specific display.
+ * Propagate ambient state to wallpaper engine.
+ *
+ * @param inAmbientMode {@code true} when in ambient mode, {@code false} otherwise.
+ * @param animationDuration Duration of the animation, or 0 when immediate.
+ */
+ public void setInAmbientMode(boolean inAmbientMode, long animationDuration) {
final IWallpaperEngine engine;
synchronized (mLock) {
- mInAmbientMode = inAmbienMode;
+ mInAmbientMode = inAmbientMode;
final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
if (data != null && data.connection != null && data.connection.mInfo != null
&& data.connection.mInfo.supportsAmbientMode()) {
@@ -2040,7 +2046,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (engine != null) {
try {
- engine.setInAmbientMode(inAmbienMode, animated);
+ engine.setInAmbientMode(inAmbientMode, animationDuration);
} catch (RemoteException e) {
// Cannot talk to wallpaper engine.
}
@@ -2344,7 +2350,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
return false;
}
if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
- String msg = "Selected service does not require "
+ String msg = "Selected service does not have "
+ android.Manifest.permission.BIND_WALLPAPER
+ ": " + componentName;
if (fromUser) {
@@ -2396,6 +2402,22 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
+ if (wi != null && wi.supportsAmbientMode()) {
+ final int hasPrivilege = mIPackageManager.checkPermission(
+ android.Manifest.permission.AMBIENT_WALLPAPER, wi.getPackageName(),
+ serviceUserId);
+ if (hasPrivilege != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Selected service does not have "
+ + android.Manifest.permission.AMBIENT_WALLPAPER
+ + ": " + componentName;
+ if (fromUser) {
+ throw new SecurityException(msg);
+ }
+ Slog.w(TAG, msg);
+ return false;
+ }
+ }
+
// Bind the service!
if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
final int componentUid = mIPackageManager.getPackageUid(componentName.getPackageName(),
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 84750b385d97..7bf2c9401294 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -1242,7 +1242,7 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = activities.get(activityNdx);
if (r.isActivityTypeHome()
- && ((userId == UserHandle.USER_ALL) || (r.userId == userId))) {
+ && ((userId == UserHandle.USER_ALL) || (r.mUserId == userId))) {
return r;
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
index e3133efb890c..eff0f75466d9 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserver.java
@@ -42,7 +42,7 @@ import java.lang.annotation.RetentionPolicy;
* It must then transition to either {@code CANCELLED} with {@link #onActivityLaunchCancelled}
* or into {@code FINISHED} with {@link #onActivityLaunchFinished}. These are terminal states.
*
- * Note that the {@link ActivityRecord} provided as a parameter to some state transitions isn't
+ * Note that the {@code ActivityRecordProto} provided as a parameter to some state transitions isn't
* necessarily the same within a single launch sequence: it is only the top-most activity at the
* time (if any). Trampoline activities coalesce several activity starts into a single launch
* sequence.
@@ -94,6 +94,14 @@ public interface ActivityMetricsLaunchObserver {
public static final int TEMPERATURE_HOT = 3;
/**
+ * Typedef marker that a {@code byte[]} actually contains an
+ * <a href="proto/android/server/activitymanagerservice.proto">ActivityRecordProto</a>
+ * in the protobuf format.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ActivityRecordProto {}
+
+ /**
* Notifies the observer that a new launch sequence has begun as a result of a new intent.
*
* Once a launch sequence begins, the resolved activity will either subsequently start with
@@ -135,7 +143,7 @@ public interface ActivityMetricsLaunchObserver {
* Multiple calls to this method cannot occur without first terminating the current
* launch sequence.
*/
- public void onActivityLaunched(@NonNull ActivityRecord activity,
+ public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity,
@Temperature int temperature);
/**
@@ -157,7 +165,7 @@ public interface ActivityMetricsLaunchObserver {
* in the case of a trampoline, multiple activities could've been started
* and only the latest activity is reported here.
*/
- public void onActivityLaunchCancelled(@Nullable ActivityRecord abortingActivity);
+ public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] abortingActivity);
/**
* Notifies the observer that the current launch sequence has been successfully finished.
@@ -178,5 +186,5 @@ public interface ActivityMetricsLaunchObserver {
* and only the latest activity that was top-most during first-frame drawn
* is reported here.
*/
- public void onActivityLaunchFinished(@NonNull ActivityRecord finalActivity);
+ public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] finalActivity);
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserverRegistry.java b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserverRegistry.java
new file mode 100644
index 000000000000..fa90dc5b83f4
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLaunchObserverRegistry.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.annotation.NonNull;
+
+/**
+ * Multi-cast delegate implementation for {@link ActivityMetricsLaunchObserver}.
+ *
+ * <br/><br/>
+ * This enables multiple launch observers to subscribe to {@link ActivityMetricsLogger}
+ * independently of each other.
+ *
+ * <br/><br/>
+ * Some callbacks in {@link ActivityMetricsLaunchObserver} have a {@code byte[]}
+ * parameter; this array is reused by all the registered observers, so it must not be written to
+ * (i.e. all observers must treat any array parameters as immutable).
+ *
+ * <br /><br />
+ * Multi-cast invocations occurs sequentially in-order of registered observers.
+ */
+public interface ActivityMetricsLaunchObserverRegistry {
+ /**
+ * Register an extra launch observer to receive the multi-cast.
+ *
+ * <br /><br />
+ * Multi-cast invocation happens in the same order the observers were registered. For example,
+ * <pre>
+ * registerLaunchObserver(A)
+ * registerLaunchObserver(B)
+ *
+ * obs.onIntentFailed() ->
+ * A.onIntentFailed()
+ * B.onIntentFailed()
+ * </pre>
+ */
+ void registerLaunchObserver(@NonNull ActivityMetricsLaunchObserver launchObserver);
+
+ /**
+ * Unregister an existing launch observer. It will not receive the multi-cast in the future.
+ *
+ * <br /><br />
+ * This does nothing if this observer was not already registered.
+ */
+ void unregisterLaunchObserver(@NonNull ActivityMetricsLaunchObserver launchObserver);
+}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 416e133ea14a..12690a99062e 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -99,10 +99,12 @@ import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.StatsLog;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.SomeArgs;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
/**
@@ -168,7 +170,8 @@ class ActivityMetricsLogger {
* Due to the global single concurrent launch sequence, all calls to this observer must be made
* in-order on the same thread to fulfill the "happens-before" guarantee in LaunchObserver.
*/
- private final ActivityMetricsLaunchObserver mLaunchObserver = null;
+ private final LaunchObserverRegistryImpl mLaunchObserver;
+ @VisibleForTesting static final int LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE = 512;
private final class H extends Handler {
@@ -251,7 +254,7 @@ class ActivityMetricsLogger {
type = getTransitionType(info);
processRecord = findProcessForActivity(launchedActivity);
processName = launchedActivity.processName;
- userId = launchedActivity.userId;
+ userId = launchedActivity.mUserId;
launchedActivityShortComponentName = launchedActivity.shortComponentName;
activityRecordIdHashCode = System.identityHashCode(launchedActivity);
this.windowsFullyDrawnDelayMs = windowsFullyDrawnDelayMs;
@@ -263,6 +266,7 @@ class ActivityMetricsLogger {
mSupervisor = supervisor;
mContext = context;
mHandler = new H(looper);
+ mLaunchObserver = new LaunchObserverRegistryImpl(looper);
}
void logWindowState() {
@@ -516,7 +520,7 @@ class ActivityMetricsLogger {
if (info.launchedActivity != activityRecord) {
return;
}
- final TaskRecord t = activityRecord.getTask();
+ final TaskRecord t = activityRecord.getTaskRecord();
final SomeArgs args = SomeArgs.obtain();
args.arg1 = t;
args.arg2 = activityRecord;
@@ -889,7 +893,7 @@ class ActivityMetricsLogger {
builder.addTaggedData(FIELD_ACTIVITY_RECORD_TARGET_ACTIVITY, r.info.targetActivity);
builder.addTaggedData(FIELD_ACTIVITY_RECORD_FLAGS, r.info.flags);
builder.addTaggedData(FIELD_ACTIVITY_RECORD_REAL_ACTIVITY,
- r.realActivity.toShortString());
+ r.mActivityComponent.toShortString());
builder.addTaggedData(FIELD_ACTIVITY_RECORD_SHORT_COMPONENT_NAME, r.shortComponentName);
builder.addTaggedData(FIELD_ACTIVITY_RECORD_PROCESS_NAME, r.processName);
builder.addTaggedData(FIELD_ACTIVITY_RECORD_IS_FULLSCREEN, r.fullscreen ? 1 : 0);
@@ -1000,12 +1004,19 @@ class ActivityMetricsLogger {
}
}
+ public ActivityMetricsLaunchObserverRegistry getLaunchObserverRegistry() {
+ return mLaunchObserver;
+ }
+
/** Notify the {@link ActivityMetricsLaunchObserver} that a new launch sequence has begun. */
private void launchObserverNotifyIntentStarted(Intent intent) {
- if (mLaunchObserver != null) {
- // Beginning a launch is timing sensitive and so should be observed as soon as possible.
- mLaunchObserver.onIntentStarted(intent);
- }
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "MetricsLogger:launchObserverNotifyIntentStarted");
+
+ // Beginning a launch is timing sensitive and so should be observed as soon as possible.
+ mLaunchObserver.onIntentStarted(intent);
+
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
/**
@@ -1014,9 +1025,12 @@ class ActivityMetricsLogger {
* intent being delivered to the top running activity.
*/
private void launchObserverNotifyIntentFailed() {
- if (mLaunchObserver != null) {
- mLaunchObserver.onIntentFailed();
- }
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "MetricsLogger:launchObserverNotifyIntentFailed");
+
+ mLaunchObserver.onIntentFailed();
+
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
/**
@@ -1024,14 +1038,17 @@ class ActivityMetricsLogger {
* has started.
*/
private void launchObserverNotifyActivityLaunched(WindowingModeTransitionInfo info) {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "MetricsLogger:launchObserverNotifyActivityLaunched");
+
@ActivityMetricsLaunchObserver.Temperature int temperature =
convertTransitionTypeToLaunchObserverTemperature(getTransitionType(info));
- if (mLaunchObserver != null) {
- // Beginning a launch is timing sensitive and so should be observed as soon as possible.
- mLaunchObserver.onActivityLaunched(info.launchedActivity,
- temperature);
- }
+ // Beginning a launch is timing sensitive and so should be observed as soon as possible.
+ mLaunchObserver.onActivityLaunched(convertActivityRecordToProto(info.launchedActivity),
+ temperature);
+
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
/**
@@ -1039,11 +1056,15 @@ class ActivityMetricsLogger {
* cancelled.
*/
private void launchObserverNotifyActivityLaunchCancelled(WindowingModeTransitionInfo info) {
- final ActivityRecord launchedActivity = info != null ? info.launchedActivity : null;
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "MetricsLogger:launchObserverNotifyActivityLaunchCancelled");
- if (mLaunchObserver != null) {
- mLaunchObserver.onActivityLaunchCancelled(launchedActivity);
- }
+ final @ActivityMetricsLaunchObserver.ActivityRecordProto byte[] activityRecordProto =
+ info != null ? convertActivityRecordToProto(info.launchedActivity) : null;
+
+ mLaunchObserver.onActivityLaunchCancelled(activityRecordProto);
+
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
/**
@@ -1051,11 +1072,34 @@ class ActivityMetricsLogger {
* has fully finished (successfully).
*/
private void launchObserverNotifyActivityLaunchFinished(WindowingModeTransitionInfo info) {
- final ActivityRecord launchedActivity = info.launchedActivity;
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "MetricsLogger:launchObserverNotifyActivityLaunchFinished");
- if (mLaunchObserver != null) {
- mLaunchObserver.onActivityLaunchFinished(launchedActivity);
- }
+ mLaunchObserver.onActivityLaunchFinished(
+ convertActivityRecordToProto(info.launchedActivity));
+
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+
+ @VisibleForTesting
+ static @ActivityMetricsLaunchObserver.ActivityRecordProto byte[]
+ convertActivityRecordToProto(ActivityRecord record) {
+ // May take non-negligible amount of time to convert ActivityRecord into a proto,
+ // so track the time.
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "MetricsLogger:convertActivityRecordToProto");
+
+ // There does not appear to be a way to 'reset' a ProtoOutputBuffer stream,
+ // so create a new one every time.
+ final ProtoOutputStream protoOutputStream =
+ new ProtoOutputStream(LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
+ // Write this data out as the top-most ActivityRecordProto (i.e. it is not a sub-object).
+ record.writeToProto(protoOutputStream);
+ final byte[] bytes = protoOutputStream.getBytes();
+
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+
+ return bytes;
}
private static @ActivityMetricsLaunchObserver.Temperature int
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b4aec35d9d6e..25399ef165a5 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -244,7 +244,7 @@ final class ActivityRecord extends ConfigurationContainer {
private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
- final ActivityTaskManagerService service; // owner
+ final ActivityTaskManagerService mAtmService; // owner
final IApplicationToken.Stub appToken; // window manager token
// TODO: Remove after unification
AppWindowToken mAppWindowToken;
@@ -255,9 +255,9 @@ final class ActivityRecord extends ConfigurationContainer {
final int launchedFromPid; // always the pid who started the activity.
final int launchedFromUid; // always the uid who started the activity.
final String launchedFromPackage; // always the package who started the activity.
- final int userId; // Which user is this running for?
+ final int mUserId; // Which user is this running for?
final Intent intent; // the original intent that generated us
- final ComponentName realActivity; // the intent component, or target of an alias.
+ final ComponentName mActivityComponent; // the intent component, or target of an alias.
final String shortComponentName; // the short component name of the intent
final String resolvedType; // as per original caller;
final String packageName; // the package implementing intent's component
@@ -407,14 +407,14 @@ final class ActivityRecord extends ConfigurationContainer {
pw.print(" processName="); pw.println(processName);
pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
- pw.print(" userId="); pw.println(userId);
+ pw.print(" userId="); pw.println(mUserId);
pw.print(prefix); pw.print("app="); pw.println(app);
pw.print(prefix); pw.println(intent.toInsecureStringWithClip());
pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
pw.print(" task="); pw.println(task);
pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
- pw.print(prefix); pw.print("realActivity=");
- pw.println(realActivity.flattenToShortString());
+ pw.print(prefix); pw.print("mActivityComponent=");
+ pw.println(mActivityComponent.flattenToShortString());
if (appInfo != null) {
pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
@@ -644,7 +644,7 @@ final class ActivityRecord extends ConfigurationContainer {
"Reporting activity moved to display" + ", activityRecord=" + this
+ ", displayId=" + displayId + ", config=" + config);
- service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
+ mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
MoveToDisplayItem.obtain(displayId, config));
} catch (RemoteException e) {
// If process died, whatever.
@@ -662,7 +662,7 @@ final class ActivityRecord extends ConfigurationContainer {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
+ config);
- service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
+ mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
ActivityConfigurationChangeItem.obtain(config));
} catch (RemoteException e) {
// If process died, whatever.
@@ -689,7 +689,7 @@ final class ActivityRecord extends ConfigurationContainer {
private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
try {
- service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
+ mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
MultiWindowModeChangeItem.obtain(mLastReportedMultiWindowMode, overrideConfig));
} catch (Exception e) {
// If process died, I don't care.
@@ -720,7 +720,7 @@ final class ActivityRecord extends ConfigurationContainer {
private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
try {
- service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
+ mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
PipModeChangeItem.obtain(mLastReportedPictureInPictureMode,
overrideConfig));
} catch (Exception e) {
@@ -741,10 +741,10 @@ final class ActivityRecord extends ConfigurationContainer {
@Override
protected ConfigurationContainer getParent() {
- return getTask();
+ return getTaskRecord();
}
- TaskRecord getTask() {
+ TaskRecord getTaskRecord() {
return task;
}
@@ -765,12 +765,12 @@ final class ActivityRecord extends ConfigurationContainer {
* @param reparenting Whether we're in the middle of reparenting.
*/
void setTask(TaskRecord task, boolean reparenting) {
- // Do nothing if the {@link TaskRecord} is the same as the current {@link getTask}.
- if (task != null && task == getTask()) {
+ // Do nothing if the {@link TaskRecord} is the same as the current {@link getTaskRecord}.
+ if (task != null && task == getTaskRecord()) {
return;
}
- final ActivityStack oldStack = getStack();
+ final ActivityStack oldStack = getActivityStack();
final ActivityStack newStack = task != null ? task.getStack() : null;
// Inform old stack (if present) of activity removal and new stack (if set) of activity
@@ -819,7 +819,7 @@ final class ActivityRecord extends ConfigurationContainer {
return null;
}
ActivityRecord r = token.weakActivity.get();
- if (r == null || r.getStack() == null) {
+ if (r == null || r.getActivityStack() == null) {
return null;
}
return r;
@@ -852,7 +852,7 @@ final class ActivityRecord extends ConfigurationContainer {
}
boolean isResolverActivity() {
- return ResolverActivity.class.getName().equals(realActivity.getClassName());
+ return ResolverActivity.class.getName().equals(mActivityComponent.getClassName());
}
boolean isResolverOrChildActivity() {
@@ -861,7 +861,7 @@ final class ActivityRecord extends ConfigurationContainer {
}
try {
return ResolverActivity.class.isAssignableFrom(
- Object.class.getClassLoader().loadClass(realActivity.getClassName()));
+ Object.class.getClassLoader().loadClass(mActivityComponent.getClassName()));
} catch (ClassNotFoundException e) {
return false;
}
@@ -873,14 +873,14 @@ final class ActivityRecord extends ConfigurationContainer {
ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
ActivityOptions options, ActivityRecord sourceRecord) {
- service = _service;
+ mAtmService = _service;
mRootActivityContainer = _service.mRootActivityContainer;
appToken = new Token(this, _intent);
info = aInfo;
launchedFromPid = _launchedFromPid;
launchedFromUid = _launchedFromUid;
launchedFromPackage = _launchedFromPackage;
- userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
+ mUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
intent = _intent;
shortComponentName = _intent.getComponent().flattenToShortString();
resolvedType = _resolvedType;
@@ -917,9 +917,9 @@ final class ActivityRecord extends ConfigurationContainer {
|| (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
&& (aInfo.launchMode == LAUNCH_MULTIPLE
|| aInfo.launchMode == LAUNCH_SINGLE_TOP))) {
- realActivity = _intent.getComponent();
+ mActivityComponent = _intent.getComponent();
} else {
- realActivity = new ComponentName(aInfo.packageName, aInfo.targetActivity);
+ mActivityComponent = new ComponentName(aInfo.packageName, aInfo.targetActivity);
}
taskAffinity = aInfo.taskAffinity;
stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
@@ -958,7 +958,7 @@ final class ActivityRecord extends ConfigurationContainer {
launchMode = aInfo.launchMode;
Entry ent = AttributeCache.instance().get(packageName,
- realTheme, com.android.internal.R.styleable.Window, userId);
+ realTheme, com.android.internal.R.styleable.Window, mUserId);
if (ent != null) {
fullscreen = !ActivityInfo.isTranslucentOrFloating(ent.array);
@@ -1038,7 +1038,7 @@ final class ActivityRecord extends ConfigurationContainer {
updateOverrideConfiguration();
// TODO: remove after unification
- mAppWindowToken = service.mWindowManager.mRoot.getAppWindowToken(appToken.asBinder());
+ mAppWindowToken = mAtmService.mWindowManager.mRoot.getAppWindowToken(appToken.asBinder());
if (mAppWindowToken != null) {
// TODO: Should this throw an exception instead?
Slog.w(TAG, "Attempted to add existing app token: " + appToken);
@@ -1048,7 +1048,7 @@ final class ActivityRecord extends ConfigurationContainer {
throw new IllegalArgumentException("AppWindowContainerController: invalid "
+ " controller=" + taskController);
}
- mAppWindowToken = createAppWindow(service.mWindowManager, appToken,
+ mAppWindowToken = createAppWindow(mAtmService.mWindowManager, appToken,
task.voiceSession != null, container.getDisplayContent(),
ActivityTaskManagerService.getInputDispatchingTimeoutLocked(this)
* 1000000L, fullscreen,
@@ -1098,16 +1098,16 @@ final class ActivityRecord extends ConfigurationContainer {
boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
int rotationAnimationHint, int configChanges, boolean launchTaskBehind,
boolean alwaysFocusable) {
- return new AppWindowToken(service, token, realActivity, voiceInteraction, dc,
+ return new AppWindowToken(service, token, mActivityComponent, voiceInteraction, dc,
inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
rotationAnimationHint, configChanges, launchTaskBehind, alwaysFocusable,
this);
}
void removeWindowContainer() {
- if (service.mWindowManager.mRoot == null) return;
+ if (mAtmService.mWindowManager.mRoot == null) return;
- final DisplayContent dc = service.mWindowManager.mRoot.getDisplayContent(
+ final DisplayContent dc = mAtmService.mWindowManager.mRoot.getDisplayContent(
getDisplayId());
if (dc == null) {
Slog.w(TAG, "removeWindowContainer: Attempted to remove token: "
@@ -1193,7 +1193,7 @@ final class ActivityRecord extends ConfigurationContainer {
*/
private boolean canLaunchAssistActivity(String packageName) {
final ComponentName assistComponent =
- service.mActiveVoiceInteractionServiceComponent;
+ mAtmService.mActiveVoiceInteractionServiceComponent;
if (assistComponent != null) {
return assistComponent.getPackageName().equals(packageName);
}
@@ -1213,8 +1213,8 @@ final class ActivityRecord extends ConfigurationContainer {
// We only allow home activities to be resizeable if they explicitly requested it.
info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
}
- } else if (realActivity.getClassName().contains(LEGACY_RECENTS_PACKAGE_NAME)
- || service.getRecentTasks().isRecentsComponent(realActivity, appInfo.uid)) {
+ } else if (mActivityComponent.getClassName().contains(LEGACY_RECENTS_PACKAGE_NAME)
+ || mAtmService.getRecentTasks().isRecentsComponent(mActivityComponent, appInfo.uid)) {
activityType = ACTIVITY_TYPE_RECENTS;
} else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
&& canLaunchAssistActivity(launchedFromPackage)) {
@@ -1232,16 +1232,16 @@ final class ActivityRecord extends ConfigurationContainer {
/**
* @return Stack value from current task, null if there is no task.
*/
- <T extends ActivityStack> T getStack() {
+ <T extends ActivityStack> T getActivityStack() {
return task != null ? (T) task.getStack() : null;
}
int getStackId() {
- return getStack() != null ? getStack().mStackId : INVALID_STACK_ID;
+ return getActivityStack() != null ? getActivityStack().mStackId : INVALID_STACK_ID;
}
ActivityDisplay getDisplay() {
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
return stack != null ? stack.getDisplay() : null;
}
@@ -1272,7 +1272,7 @@ final class ActivityRecord extends ConfigurationContainer {
}
boolean isInStackLocked() {
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
return stack != null && stack.isInStackLocked(this) != null;
}
@@ -1302,7 +1302,7 @@ final class ActivityRecord extends ConfigurationContainer {
* @return whether this activity supports PiP multi-window and can be put in the pinned stack.
*/
boolean supportsPictureInPicture() {
- return service.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined()
+ return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined()
&& info.supportsPictureInPicture();
}
@@ -1315,7 +1315,7 @@ final class ActivityRecord extends ConfigurationContainer {
// An activity can not be docked even if it is considered resizeable because it only
// supports picture-in-picture mode but has a non-resizeable resizeMode
return super.supportsSplitScreenWindowingMode()
- && service.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
+ && mAtmService.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
}
/**
@@ -1323,16 +1323,16 @@ final class ActivityRecord extends ConfigurationContainer {
* stack.
*/
boolean supportsFreeform() {
- return service.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
+ return mAtmService.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
}
/**
* @return whether this activity supports non-PiP multi-window.
*/
private boolean supportsResizeableMultiWindow() {
- return service.mSupportsMultiWindow && !isActivityTypeHome()
+ return mAtmService.mSupportsMultiWindow && !isActivityTypeHome()
&& (ActivityInfo.isResizeableMode(info.resizeMode)
- || service.mForceResizableActivities);
+ || mAtmService.mForceResizableActivities);
}
/**
@@ -1343,7 +1343,7 @@ final class ActivityRecord extends ConfigurationContainer {
* secondary screen.
*/
boolean canBeLaunchedOnDisplay(int displayId) {
- return service.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
+ return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
launchedFromUid, info);
}
@@ -1364,13 +1364,13 @@ final class ActivityRecord extends ConfigurationContainer {
}
// Check to see if we are in VR mode, and disallow PiP if so
- if (service.shouldDisableNonVrUiLocked()) {
+ if (mAtmService.shouldDisableNonVrUiLocked()) {
return false;
}
- boolean isKeyguardLocked = service.isKeyguardLocked();
+ boolean isKeyguardLocked = mAtmService.isKeyguardLocked();
boolean isCurrentAppLocked =
- service.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
+ mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
final ActivityDisplay display = getDisplay();
boolean hasPinnedStack = display != null && display.hasPinnedStack();
// Don't return early if !isNotLocked, since we want to throw an exception if the activity
@@ -1411,7 +1411,7 @@ final class ActivityRecord extends ConfigurationContainer {
* @return Whether AppOps allows this package to enter picture-in-picture.
*/
private boolean checkEnterPictureInPictureAppOpsState() {
- return service.getAppOpsService().checkOperation(
+ return mAtmService.getAppOpsService().checkOperation(
OP_PICTURE_IN_PICTURE, appInfo.uid, packageName) == MODE_ALLOWED;
}
@@ -1428,8 +1428,8 @@ final class ActivityRecord extends ConfigurationContainer {
return false;
}
- final TaskRecord task = getTask();
- final ActivityStack stack = getStack();
+ final TaskRecord task = getTaskRecord();
+ final ActivityStack stack = getActivityStack();
if (stack == null) {
Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
+ this + " task=" + task);
@@ -1451,7 +1451,7 @@ final class ActivityRecord extends ConfigurationContainer {
// Report top activity change to tracking services and WM
if (mRootActivityContainer.getTopResumedActivity() == this) {
// TODO(b/111361570): Support multiple focused apps in WM
- service.setResumedActivityUncheckLocked(this, reason);
+ mAtmService.setResumedActivityUncheckLocked(this, reason);
}
return true;
}
@@ -1461,7 +1461,7 @@ final class ActivityRecord extends ConfigurationContainer {
* {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set
*/
boolean hasDismissKeyguardWindows() {
- return service.mWindowManager.containsDismissKeyguardWindow(appToken);
+ return mAtmService.mWindowManager.containsDismissKeyguardWindow(appToken);
}
void makeFinishingLocked() {
@@ -1473,14 +1473,14 @@ final class ActivityRecord extends ConfigurationContainer {
clearOptionsLocked();
}
- if (service != null) {
- service.getTaskChangeNotificationController().notifyTaskStackChanged();
+ if (mAtmService != null) {
+ mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
}
}
UriPermissionOwner getUriPermissionsLocked() {
if (uriPermissions == null) {
- uriPermissions = new UriPermissionOwner(service.mUgmInternal, this);
+ uriPermissions = new UriPermissionOwner(mAtmService.mUgmInternal, this);
}
return uriPermissions;
}
@@ -1522,8 +1522,8 @@ final class ActivityRecord extends ConfigurationContainer {
}
final boolean isSleeping() {
- final ActivityStack stack = getStack();
- return stack != null ? stack.shouldSleepActivities() : service.isSleepingLocked();
+ final ActivityStack stack = getActivityStack();
+ return stack != null ? stack.shouldSleepActivities() : mAtmService.isSleepingLocked();
}
/**
@@ -1532,8 +1532,8 @@ final class ActivityRecord extends ConfigurationContainer {
*/
final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
// The activity now gets access to the data associated with this Intent.
- service.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
- intent, getUriPermissionsLocked(), userId);
+ mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
+ intent, getUriPermissionsLocked(), mUserId);
final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
boolean unsent = true;
final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
@@ -1547,7 +1547,7 @@ final class ActivityRecord extends ConfigurationContainer {
try {
ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
ar.add(rintent);
- service.getLifecycleManager().scheduleTransaction(
+ mAtmService.getLifecycleManager().scheduleTransaction(
app.getThread(), appToken, NewIntentItem.obtain(ar, mState == PAUSED));
unsent = false;
} catch (RemoteException e) {
@@ -1781,7 +1781,7 @@ final class ActivityRecord extends ConfigurationContainer {
mState = state;
- final TaskRecord parent = getTask();
+ final TaskRecord parent = getTaskRecord();
if (parent != null) {
parent.onActivityStateChanged(this, state, reason);
@@ -1879,7 +1879,7 @@ final class ActivityRecord extends ConfigurationContainer {
// If this activity is paused, tell it to now show its window.
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
"Making visible and scheduling visibility: " + this);
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
try {
if (stack.mTranslucentActivityWaiting != null) {
updateOptionsLocked(returningOptions);
@@ -1907,13 +1907,13 @@ final class ActivityRecord extends ConfigurationContainer {
void makeClientVisible() {
mClientVisibilityDeferred = false;
try {
- service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
+ mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
WindowVisibilityItem.obtain(true /* showWindow */));
if (shouldPauseWhenBecomingVisible()) {
// An activity must be in the {@link PAUSING} state for the system to validate
// the move to {@link PAUSED}.
setState(PAUSING, "makeVisibleIfNeeded");
- service.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
+ mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
PauseActivityItem.obtain(finishing, false /* userLeaving */,
configChangeFlags, false /* dontReport */));
}
@@ -1931,7 +1931,7 @@ final class ActivityRecord extends ConfigurationContainer {
// paused state. We also avoid doing this for the activity the stack supervisor
// considers the resumed activity, as normal means will bring the activity from STOPPED
// to RESUMED. Adding PAUSING in this scenario will lead to double lifecycles.
- if (!isState(STOPPED, STOPPING) || getStack().mTranslucentActivityWaiting != null
+ if (!isState(STOPPED, STOPPING) || getActivityStack().mTranslucentActivityWaiting != null
|| isResumedActivityOnDisplay()) {
return false;
}
@@ -1994,8 +1994,8 @@ final class ActivityRecord extends ConfigurationContainer {
if (isActivityTypeHome()) {
WindowProcessController app = task.mActivities.get(0).app;
- if (hasProcess() && app != service.mHomeProcess) {
- service.mHomeProcess = app;
+ if (hasProcess() && app != mAtmService.mHomeProcess) {
+ mAtmService.mHomeProcess = app;
}
}
@@ -2010,7 +2010,7 @@ final class ActivityRecord extends ConfigurationContainer {
mStackSupervisor.reportResumedActivityLocked(this);
resumeKeyDispatchingLocked();
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
mStackSupervisor.mNoAnimActivities.clear();
// Mark the point when the activity is resuming
@@ -2036,7 +2036,7 @@ final class ActivityRecord extends ConfigurationContainer {
final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
CharSequence description) {
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
if (mState != STOPPING) {
Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
@@ -2044,7 +2044,7 @@ final class ActivityRecord extends ConfigurationContainer {
}
if (newPersistentState != null) {
persistentState = newPersistentState;
- service.notifyTaskPersisterLocked(task, false);
+ mAtmService.notifyTaskPersisterLocked(task, false);
}
if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + icicle);
@@ -2094,7 +2094,7 @@ final class ActivityRecord extends ConfigurationContainer {
return false;
}
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
if (stack == null) {
return false;
}
@@ -2107,7 +2107,7 @@ final class ActivityRecord extends ConfigurationContainer {
void finishLaunchTickingLocked() {
launchTickTime = 0;
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
if (stack != null) {
stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
}
@@ -2168,7 +2168,7 @@ final class ActivityRecord extends ConfigurationContainer {
* Called when the starting window for this container is drawn.
*/
public void onStartingWindowDrawn(long timestamp) {
- synchronized (service.mGlobalLock) {
+ synchronized (mAtmService.mGlobalLock) {
mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
getWindowingMode(), timestamp);
}
@@ -2176,7 +2176,7 @@ final class ActivityRecord extends ConfigurationContainer {
/** Called when the windows associated app window container are drawn. */
public void onWindowsDrawn(boolean drawn, long timestamp) {
- synchronized (service.mGlobalLock) {
+ synchronized (mAtmService.mGlobalLock) {
mDrawn = drawn;
if (!drawn) {
return;
@@ -2196,7 +2196,7 @@ final class ActivityRecord extends ConfigurationContainer {
/** Called when the windows associated app window container are visible. */
public void onWindowsVisible() {
- synchronized (service.mGlobalLock) {
+ synchronized (mAtmService.mGlobalLock) {
mStackSupervisor.reportActivityVisibleLocked(this);
if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
if (!nowVisible) {
@@ -2223,14 +2223,14 @@ final class ActivityRecord extends ConfigurationContainer {
mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
false /* remove */, true /* processPausingActivities */);
}
- service.scheduleAppGcsLocked();
+ mAtmService.scheduleAppGcsLocked();
}
}
}
/** Called when the windows associated app window container are no longer visible. */
public void onWindowsGone() {
- synchronized (service.mGlobalLock) {
+ synchronized (mAtmService.mGlobalLock) {
if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
nowVisible = false;
}
@@ -2248,7 +2248,7 @@ final class ActivityRecord extends ConfigurationContainer {
ActivityRecord anrActivity;
WindowProcessController anrApp;
boolean windowFromSameProcessAsActivity;
- synchronized (service.mGlobalLock) {
+ synchronized (mAtmService.mGlobalLock) {
anrActivity = getWaitingHistoryRecordLocked();
anrApp = app;
windowFromSameProcessAsActivity =
@@ -2256,13 +2256,13 @@ final class ActivityRecord extends ConfigurationContainer {
}
if (windowFromSameProcessAsActivity) {
- return service.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
+ return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
anrActivity.shortComponentName, anrActivity.appInfo, shortComponentName,
app, false, reason);
} else {
// In this case another process added windows using this activity token. So, we call the
// generic service input dispatch timed out method so that the right process is blamed.
- return service.mAmInternal.inputDispatchingTimedOut(
+ return mAtmService.mAmInternal.inputDispatchingTimedOut(
windowPid, false /* aboveSystem */, reason) < 0;
}
}
@@ -2289,14 +2289,14 @@ final class ActivityRecord extends ConfigurationContainer {
public boolean okToShowLocked() {
// We cannot show activities when the device is locked and the application is not
// encryption aware.
- if (!StorageManager.isUserKeyUnlocked(userId)
+ if (!StorageManager.isUserKeyUnlocked(mUserId)
&& !info.applicationInfo.isEncryptionAware()) {
return false;
}
return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
- || (mStackSupervisor.isCurrentProfileLocked(userId)
- && service.mAmInternal.isUserRunning(userId, 0 /* flags */));
+ || (mStackSupervisor.isCurrentProfileLocked(mUserId)
+ && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
}
/**
@@ -2343,13 +2343,13 @@ final class ActivityRecord extends ConfigurationContainer {
static ActivityRecord isInStackLocked(IBinder token) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
- return (r != null) ? r.getStack().isInStackLocked(r) : null;
+ return (r != null) ? r.getActivityStack().isInStackLocked(r) : null;
}
static ActivityStack getStackLocked(IBinder token) {
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
- return r.getStack();
+ return r.getActivityStack();
}
return null;
}
@@ -2359,7 +2359,7 @@ final class ActivityRecord extends ConfigurationContainer {
* {@link android.view.Display#INVALID_DISPLAY} if not attached.
*/
int getDisplayId() {
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
if (stack == null) {
return INVALID_DISPLAY;
}
@@ -2371,7 +2371,7 @@ final class ActivityRecord extends ConfigurationContainer {
// This would be redundant.
return false;
}
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
if (stack == null || this == stack.getResumedActivity() || this == stack.mPausingActivity
|| !haveState || !stopped) {
// We're not ready for this kind of thing.
@@ -2397,7 +2397,7 @@ final class ActivityRecord extends ConfigurationContainer {
final File iconFile = new File(TaskPersister.getUserImagesDir(task.userId),
iconFilename);
final String iconFilePath = iconFile.getAbsolutePath();
- service.getRecentTasks().saveImage(icon, iconFilePath);
+ mAtmService.getRecentTasks().saveImage(icon, iconFilePath);
_taskDescription.setIconFilename(iconFilePath);
}
taskDescription = _taskDescription;
@@ -2433,7 +2433,7 @@ final class ActivityRecord extends ConfigurationContainer {
}
final CompatibilityInfo compatInfo =
- service.compatibilityInfoForPackageLocked(info.applicationInfo);
+ mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
final boolean shown = addStartingWindow(packageName, theme,
compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
@@ -2466,12 +2466,12 @@ final class ActivityRecord extends ConfigurationContainer {
displayId, displayConfig, mayFreezeScreenLocked(app));
if (config != null) {
frozenBeforeDestroy = true;
- if (!service.updateDisplayOverrideConfigurationLocked(config, this,
+ if (!mAtmService.updateDisplayOverrideConfigurationLocked(config, this,
false /* deferResume */, displayId)) {
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
}
- service.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
+ mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
task.taskId, requestedOrientation);
}
@@ -2486,7 +2486,7 @@ final class ActivityRecord extends ConfigurationContainer {
mAppWindowToken.setOrientation(requestedOrientation);
final IBinder binder = freezeScreenIfNeeded ? appToken.asBinder() : null;
- return service.mWindowManager.updateOrientationFromAppTokens(displayConfig, binder,
+ return mAtmService.mWindowManager.updateOrientationFromAppTokens(displayConfig, binder,
displayId);
}
@@ -2572,7 +2572,7 @@ final class ActivityRecord extends ConfigurationContainer {
private void computeBounds(Rect outBounds) {
outBounds.setEmpty();
final float maxAspectRatio = info.maxAspectRatio;
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
if (task == null || stack == null || task.inMultiWindowMode() || maxAspectRatio == 0
|| isInVrUiMode(getConfiguration())) {
// We don't set override configuration if that activity task isn't fullscreen. I.e. the
@@ -2618,7 +2618,7 @@ final class ActivityRecord extends ConfigurationContainer {
// bounds would end up too small.
outBounds.set(0, 0, maxActivityWidth + appBounds.left, maxActivityHeight + appBounds.top);
- if (service.mWindowManager.getNavBarPosition(getDisplayId()) == NAV_BAR_LEFT) {
+ if (mAtmService.mWindowManager.getNavBarPosition(getDisplayId()) == NAV_BAR_LEFT) {
// Position the activity frame on the opposite side of the nav bar.
outBounds.left = appBounds.right - maxActivityWidth;
outBounds.right = appBounds.right;
@@ -2654,7 +2654,7 @@ final class ActivityRecord extends ConfigurationContainer {
*/
boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
boolean ignoreStopState) {
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
if (stack.mConfigWillChange) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Skipping config check (will change): " + this);
@@ -2717,7 +2717,7 @@ final class ActivityRecord extends ConfigurationContainer {
// Update last reported values.
final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
- setLastReportedConfiguration(service.getGlobalConfiguration(), newMergedOverrideConfig);
+ setLastReportedConfiguration(mAtmService.getGlobalConfiguration(), newMergedOverrideConfig);
if (mState == INITIALIZING) {
// No need to relaunch or schedule new config for activity that hasn't been launched
@@ -2771,7 +2771,7 @@ final class ActivityRecord extends ConfigurationContainer {
final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
if (hasResizeChange) {
final boolean isDragResizing =
- getTask().getWindowContainerController().isDragResizing();
+ getTaskRecord().getWindowContainerController().isDragResizing();
mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
: RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
} else {
@@ -2904,7 +2904,7 @@ final class ActivityRecord extends ConfigurationContainer {
}
void relaunchActivityLocked(boolean andResume, boolean preserveWindow) {
- if (service.mSuppressResizeConfigChanges && preserveWindow) {
+ if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
configChangeFlags = 0;
return;
}
@@ -2920,7 +2920,7 @@ final class ActivityRecord extends ConfigurationContainer {
+ " newIntents=" + pendingNewIntents + " andResume=" + andResume
+ " preserveWindow=" + preserveWindow);
EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
- : AM_RELAUNCH_ACTIVITY, userId, System.identityHashCode(this),
+ : AM_RELAUNCH_ACTIVITY, mUserId, System.identityHashCode(this),
task.taskId, shortComponentName);
startFreezingScreenLocked(app, 0);
@@ -2933,7 +2933,7 @@ final class ActivityRecord extends ConfigurationContainer {
mStackSupervisor.activityRelaunchingLocked(this);
final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
pendingNewIntents, configChangeFlags,
- new MergedConfiguration(service.getGlobalConfiguration(),
+ new MergedConfiguration(mAtmService.getGlobalConfiguration(),
getMergedOverrideConfiguration()),
preserveWindow);
final ActivityLifecycleItem lifecycleItem;
@@ -2946,7 +2946,7 @@ final class ActivityRecord extends ConfigurationContainer {
final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
transaction.addCallback(callbackItem);
transaction.setLifecycleStateRequest(lifecycleItem);
- service.getLifecycleManager().scheduleTransaction(transaction);
+ mAtmService.getLifecycleManager().scheduleTransaction(transaction);
// Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
// request resume if this activity is currently resumed, which implies we aren't
// sleeping.
@@ -2960,9 +2960,9 @@ final class ActivityRecord extends ConfigurationContainer {
}
results = null;
newIntents = null;
- service.getAppWarningsLocked().onResumeActivity(this);
+ mAtmService.getAppWarningsLocked().onResumeActivity(this);
} else {
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
if (stack != null) {
stack.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this);
}
@@ -2977,7 +2977,7 @@ final class ActivityRecord extends ConfigurationContainer {
private boolean isProcessRunning() {
WindowProcessController proc = app;
if (proc == null) {
- proc = service.mProcessNames.get(processName, info.applicationInfo.uid);
+ proc = mAtmService.mProcessNames.get(processName, info.applicationInfo.uid);
}
return proc != null && proc.hasThread();
}
@@ -3021,7 +3021,7 @@ final class ActivityRecord extends ConfigurationContainer {
out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
}
out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
- out.attribute(null, ATTR_USERID, String.valueOf(userId));
+ out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
if (taskDescription != null) {
taskDescription.saveToXml(out);
@@ -3144,7 +3144,7 @@ final class ActivityRecord extends ConfigurationContainer {
*/
boolean canShowWhenLocked() {
return !inPinnedWindowingMode() && (mShowWhenLocked
- || service.mWindowManager.containsShowWhenLockedWindow(appToken));
+ || mAtmService.mWindowManager.containsShowWhenLockedWindow(appToken));
}
void setTurnScreenOn(boolean turnScreenOn) {
@@ -3159,7 +3159,7 @@ final class ActivityRecord extends ConfigurationContainer {
* @return true if the screen can be turned on, false otherwise.
*/
boolean canTurnScreenOn() {
- final ActivityStack stack = getStack();
+ final ActivityStack stack = getActivityStack();
return mTurnScreenOn && stack != null &&
stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
}
@@ -3200,7 +3200,7 @@ final class ActivityRecord extends ConfigurationContainer {
sb.append("ActivityRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" u");
- sb.append(userId);
+ sb.append(mUserId);
sb.append(' ');
sb.append(intent.getComponent().flattenToShortString());
stringName = sb.toString();
@@ -3210,13 +3210,16 @@ final class ActivityRecord extends ConfigurationContainer {
void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
proto.write(HASH_CODE, System.identityHashCode(this));
- proto.write(USER_ID, userId);
+ proto.write(USER_ID, mUserId);
proto.write(TITLE, intent.getComponent().flattenToShortString());
proto.end(token);
}
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- final long token = proto.start(fieldId);
+ /**
+ * Write all fields to an {@code ActivityRecordProto}. This assumes the
+ * {@code ActivityRecordProto} is the outer-most proto data.
+ */
+ void writeToProto(ProtoOutputStream proto) {
super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
writeIdentifierToProto(proto, IDENTIFIER);
proto.write(STATE, mState.toString());
@@ -3226,6 +3229,11 @@ final class ActivityRecord extends ConfigurationContainer {
proto.write(PROC_ID, app.getPid());
}
proto.write(TRANSLUCENT, !fullscreen);
+ }
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ writeToProto(proto);
proto.end(token);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 9fbeaf8cd7bf..d40a4faf9d21 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -538,7 +538,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// TODO(b/111361570): Support multiple focused apps in WM
mService.setResumedActivityUncheckLocked(record, reason);
}
- mStackSupervisor.mRecentTasks.add(record.getTask());
+ mStackSupervisor.mRecentTasks.add(record.getTaskRecord());
}
}
@@ -1106,8 +1106,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (r == null) {
return null;
}
- final TaskRecord task = r.getTask();
- final ActivityStack stack = r.getStack();
+ final TaskRecord task = r.getTaskRecord();
+ final ActivityStack stack = r.getActivityStack();
if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
if (stack != this) Slog.w(TAG,
"Illegal state! task does not point to stack it is in.");
@@ -1282,7 +1282,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Overlays should not be considered as the task's logical top activity.
final ActivityRecord r = task.getTopActivity(false /* includeOverlays */);
- if (r == null || r.finishing || r.userId != userId ||
+ if (r == null || r.finishing || r.mUserId != userId ||
r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r);
continue;
@@ -1309,7 +1309,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
+ taskIntent.getComponent().flattenToShortString()
- + "/aff=" + r.getTask().rootAffinity + " to new cls="
+ + "/aff=" + r.getTaskRecord().rootAffinity + " to new cls="
+ intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
// TODO Refactor to remove duplications. Check if logic can be simplified.
if (taskIntent != null && taskIntent.getComponent() != null &&
@@ -1368,7 +1368,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (!r.okToShowLocked()) {
continue;
}
- if (!r.finishing && r.userId == userId) {
+ if (!r.finishing && r.mUserId == userId) {
if (compareIntentFilters) {
if (r.intent.filterEquals(intent)) {
return r;
@@ -1452,7 +1452,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord ar = activities.get(activityNdx);
- if ((userId == ar.userId) && packageName.equals(ar.packageName)) {
+ if ((userId == ar.mUserId) && packageName.equals(ar.packageName)) {
ar.updateApplicationInfo(aInfo);
}
}
@@ -1538,7 +1538,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private boolean containsActivityFromStack(List<ActivityRecord> rs) {
for (ActivityRecord r : rs) {
- if (r.getStack() == this) {
+ if (r.getActivityStack() == this) {
return true;
}
}
@@ -1606,7 +1606,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
prev.setState(PAUSING, "startPausingLocked");
- prev.getTask().touchActiveTime();
+ prev.getTaskRecord().touchActiveTime();
clearLaunchTime(prev);
mService.updateCpuStats();
@@ -1614,7 +1614,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (prev.attachedToProcess()) {
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
try {
- EventLogTags.writeAmPauseActivity(prev.userId, System.identityHashCode(prev),
+ EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving);
mService.updateUsageStats(prev, false);
@@ -1692,7 +1692,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return;
} else {
EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
- r.userId, System.identityHashCode(r), r.shortComponentName,
+ r.mUserId, System.identityHashCode(r), r.shortComponentName,
mPausingActivity != null
? mPausingActivity.shortComponentName : "(none)");
if (r.isState(PAUSING)) {
@@ -2573,9 +2573,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Make sure that the user who owns this activity is started. If not,
// we will just leave it as is because someone should be bringing
// another user's activities to the top of the stack.
- if (!mService.mAmInternal.hasStartedUserState(next.userId)) {
+ if (!mService.mAmInternal.hasStartedUserState(next.mUserId)) {
Slog.w(TAG, "Skipping resume of top activity " + next
- + ": user " + next.userId + " is stopped");
+ + ": user " + next.mUserId + " is stopped");
return false;
}
@@ -2702,7 +2702,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// considered stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
- next.packageName, false, next.userId); /* TODO: Verify if correct userid */
+ next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */
} catch (RemoteException e1) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
@@ -2723,7 +2723,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
dwc.prepareAppTransition(TRANSIT_NONE, false);
} else {
dwc.prepareAppTransition(
- prev.getTask() == next.getTask() ? TRANSIT_ACTIVITY_CLOSE
+ prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_CLOSE
: TRANSIT_TASK_CLOSE, false);
}
prev.setVisibility(false);
@@ -2735,7 +2735,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
dwc.prepareAppTransition(TRANSIT_NONE, false);
} else {
dwc.prepareAppTransition(
- prev.getTask() == next.getTask() ? TRANSIT_ACTIVITY_OPEN
+ prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_OPEN
: next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND
: TRANSIT_TASK_OPEN, false);
}
@@ -2858,8 +2858,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Clear app token stopped state in window manager if needed.
next.notifyAppResumed(next.stopped);
- EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
- System.identityHashCode(next), next.getTask().taskId,
+ EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.mUserId,
+ System.identityHashCode(next), next.getTaskRecord().taskId,
next.shortComponentName);
next.sleeping = false;
@@ -3008,7 +3008,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
- TaskRecord rTask = r.getTask();
+ TaskRecord rTask = r.getTaskRecord();
final int taskId = rTask.taskId;
// mLaunchTaskBehind tasks get placed at the back of the task stack.
if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
@@ -3049,7 +3049,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// If we are not placing the new activity frontmost, we do not want to deliver the
// onUserLeaving callback to the actual frontmost activity
- final TaskRecord activityTask = r.getTask();
+ final TaskRecord activityTask = r.getTaskRecord();
if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
@@ -3122,12 +3122,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// "has the same starting icon" as the next one. This allows the
// window manager to keep the previous window it had previously
// created, if it still had one.
- TaskRecord prevTask = r.getTask();
+ TaskRecord prevTask = r.getTaskRecord();
ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked();
if (prev != null) {
// We don't want to reuse the previous starting preview if:
// (1) The current activity is in a different task.
- if (prev.getTask() != prevTask) {
+ if (prev.getTaskRecord() != prevTask) {
prev = null;
}
// (2) The current activity is already displayed.
@@ -3160,7 +3160,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
final ActivityStack targetStack = toFrontTask != null
- ? toFrontTask.getStack() : toFrontActivity.getStack();
+ ? toFrontTask.getStack() : toFrontActivity.getActivityStack();
if (targetStack != null && targetStack.isActivityTypeAssistant()) {
// Ensure the task/activity being brought forward is not the assistant
return false;
@@ -3170,7 +3170,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private boolean isTaskSwitch(ActivityRecord r,
ActivityRecord topFocusedActivity) {
- return topFocusedActivity != null && r.getTask() != topFocusedActivity.getTask();
+ return topFocusedActivity != null && r.getTaskRecord() != topFocusedActivity.getTaskRecord();
}
/**
@@ -3237,16 +3237,16 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
!mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
mTaskHistory.get(0).mActivities.get(0) : null;
if (bottom != null && target.taskAffinity != null
- && target.taskAffinity.equals(bottom.getTask().affinity)) {
+ && target.taskAffinity.equals(bottom.getTaskRecord().affinity)) {
// If the activity currently at the bottom has the
// same task affinity as the one we are moving,
// then merge it into the same task.
- targetTask = bottom.getTask();
+ targetTask = bottom.getTaskRecord();
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
+ " out to bottom task " + targetTask);
} else {
targetTask = createTaskRecord(
- mStackSupervisor.getNextTaskIdForUserLocked(target.userId),
+ mStackSupervisor.getNextTaskIdForUserLocked(target.mUserId),
target.info, null, null, null, false);
targetTask.affinityIntent = target.intent;
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target
@@ -3440,7 +3440,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
ActivityRecord newActivity) {
final boolean forceReset =
(newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
- final TaskRecord task = taskTop.getTask();
+ final TaskRecord task = taskTop.getTaskRecord();
/** False until we evaluate the TaskRecord associated with taskTop. Switches to true
* for remaining tasks. Used for later tasks to reparent to task. */
@@ -3489,7 +3489,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (callingUid > 0) {
mService.mUgmInternal.grantUriPermissionFromIntent(callingUid, r.packageName,
- data, r.getUriPermissionsLocked(), r.userId);
+ data, r.getUriPermissionsLocked(), r.mUserId);
}
if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
@@ -3551,7 +3551,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Task is not guaranteed to be non-null. For example, destroying the
// {@link ActivityRecord} will disassociate the task from the activity.
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
if (task == null) {
throw new IllegalStateException("activity no longer associated with task:" + r);
@@ -3643,7 +3643,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
r.setVisible(false);
}
EventLogTags.writeAmStopActivity(
- r.userId, System.identityHashCode(r), r.shortComponentName);
+ r.mUserId, System.identityHashCode(r), r.shortComponentName);
mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken,
StopActivityItem.obtain(r.visible, r.configChangeFlags));
if (shouldSleepOrShutDownActivities()) {
@@ -3719,7 +3719,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
- finishedTask = r.getTask();
+ finishedTask = r.getTaskRecord();
int taskNdx = mTaskHistory.indexOf(finishedTask);
final TaskRecord task = finishedTask;
int activityNdx = task.mActivities.indexOf(r);
@@ -3793,7 +3793,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
final boolean finishActivityAffinityLocked(ActivityRecord r) {
- ArrayList<ActivityRecord> activities = r.getTask().mActivities;
+ ArrayList<ActivityRecord> activities = r.getTaskRecord().mActivities;
for (int index = activities.indexOf(r); index >= 0; --index) {
ActivityRecord cur = activities.get(index);
if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) {
@@ -3811,15 +3811,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo
+ " who=" + r.resultWho + " req=" + r.requestCode
+ " res=" + resultCode + " data=" + resultData);
- if (resultTo.userId != r.userId) {
+ if (resultTo.mUserId != r.mUserId) {
if (resultData != null) {
- resultData.prepareToLeaveUser(r.userId);
+ resultData.prepareToLeaveUser(r.mUserId);
}
}
if (r.info.applicationInfo.uid > 0) {
mService.mUgmInternal.grantUriPermissionFromIntent(r.info.applicationInfo.uid,
resultTo.packageName, resultData,
- resultTo.getUriPermissionsLocked(), resultTo.userId);
+ resultTo.getUriPermissionsLocked(), resultTo.mUserId);
}
resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData);
r.resultTo = null;
@@ -3857,9 +3857,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mWindowManager.deferSurfaceLayout();
try {
r.makeFinishingLocked();
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
- r.userId, System.identityHashCode(r),
+ r.mUserId, System.identityHashCode(r),
task.taskId, r.shortComponentName, reason);
final ArrayList<ActivityRecord> activities = task.mActivities;
final int index = activities.indexOf(r);
@@ -3992,7 +3992,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
r.setState(FINISHING, "finishCurrentActivityLocked");
final boolean finishingInNonFocusedStackOrNoRunning = mode == FINISH_AFTER_VISIBLE
- && prevState == PAUSED && (r.getStack() != display.getFocusedStack()
+ && prevState == PAUSED && (r.getActivityStack() != display.getFocusedStack()
|| (next == null && display.topRunningActivity() == null));
if (mode == FINISH_IMMEDIATELY
@@ -4068,15 +4068,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
// Basic case: for simple app-centric recents, we need to recreate
// the task if the affinity has changed.
- if (srec == null || srec.getTask().affinity == null ||
- !srec.getTask().affinity.equals(destAffinity)) {
+ if (srec == null || srec.getTaskRecord().affinity == null ||
+ !srec.getTaskRecord().affinity.equals(destAffinity)) {
return true;
}
// Document-centric case: an app may be split in to multiple documents;
// they need to re-create their task if this current activity is the root
// of a document, unless simply finishing it will return them to the the
// correct app behind.
- final TaskRecord task = srec.getTask();
+ final TaskRecord task = srec.getTaskRecord();
if (srec.frontOfTask && task.getBaseIntent() != null && task.getBaseIntent().isDocument()) {
// Okay, this activity is at the root of its task. What to do, what to do...
if (!inFrontOfStandardStack()) {
@@ -4100,7 +4100,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
Intent resultData) {
- final TaskRecord task = srec.getTask();
+ final TaskRecord task = srec.getTaskRecord();
final ArrayList<ActivityRecord> activities = task.mActivities;
final int start = activities.indexOf(srec);
if (!mTaskHistory.contains(task) || (start < 0)) {
@@ -4165,7 +4165,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
try {
ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS,
- srec.userId);
+ srec.mUserId);
// TODO(b/64750076): Check if calling pid should really be -1.
final int res = mService.getActivityStartController()
.obtainStarter(destIntent, "navigateUpTo")
@@ -4282,7 +4282,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r);
r.app = null;
r.removeWindowContainer();
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
final boolean lastActivity = task != null ? task.removeActivity(r) : false;
// If we are removing the last activity in the task, not including task overlay activities,
// then fall through into the block below to remove the entire task itself
@@ -4446,8 +4446,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
- r.userId, System.identityHashCode(r),
- r.getTask().taskId, r.shortComponentName, reason);
+ r.mUserId, System.identityHashCode(r),
+ r.getTaskRecord().taskId, r.shortComponentName, reason);
boolean removedFromHistory = false;
@@ -4646,8 +4646,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (!r.finishing) {
Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
- r.userId, System.identityHashCode(r),
- r.getTask().taskId, r.shortComponentName,
+ r.mUserId, System.identityHashCode(r),
+ r.getTaskRecord().taskId, r.shortComponentName,
"proc died without state saved");
if (r.getState() == RESUMED) {
mService.updateUsageStats(r, false);
@@ -4746,7 +4746,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final ActivityRecord top = tr.getTopActivity();
if (top == null || !top.okToShowLocked()) {
if (top != null) {
- mStackSupervisor.mRecentTasks.add(top.getTask());
+ mStackSupervisor.mRecentTasks.add(top.getTaskRecord());
}
ActivityOptions.abort(options);
return;
@@ -4861,7 +4861,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final String strData = data != null ? data.toSafeString() : null;
EventLog.writeEvent(tag,
- r.userId, System.identityHashCode(r), task.taskId,
+ r.mUserId, System.identityHashCode(r), task.taskId,
r.shortComponentName, r.intent.getAction(),
r.intent.getType(), strData, r.intent.getFlags());
}
@@ -4874,15 +4874,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return;
}
- final TaskRecord startTask = start.getTask();
+ final TaskRecord startTask = start.getTaskRecord();
boolean behindFullscreen = false;
boolean updatedConfig = false;
for (int taskIndex = mTaskHistory.indexOf(startTask); taskIndex >= 0; --taskIndex) {
final TaskRecord task = mTaskHistory.get(taskIndex);
final ArrayList<ActivityRecord> activities = task.mActivities;
- int activityIndex =
- (start.getTask() == task) ? activities.indexOf(start) : activities.size() - 1;
+ int activityIndex = (start.getTaskRecord() == task)
+ ? activities.indexOf(start) : activities.size() - 1;
for (; activityIndex >= 0; --activityIndex) {
final ActivityRecord r = activities.get(activityIndex);
updatedConfig |= r.ensureActivityConfiguration(0 /* globalChanges */,
@@ -5046,10 +5046,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
ActivityRecord r = mTmpActivities.remove(0);
final boolean sameComponent =
(r.packageName.equals(packageName) && (filterByClasses == null
- || filterByClasses.contains(r.realActivity.getClassName())))
- || (packageName == null && r.userId == userId);
- if ((userId == UserHandle.USER_ALL || r.userId == userId)
- && (sameComponent || r.getTask() == lastTask)
+ || filterByClasses.contains(r.mActivityComponent.getClassName())))
+ || (packageName == null && r.mUserId == userId);
+ if ((userId == UserHandle.USER_ALL || r.mUserId == userId)
+ && (sameComponent || r.getTaskRecord() == lastTask)
&& (r.app == null || evenPersistent || !r.app.isPersistent())) {
if (!doit) {
if (r.finishing) {
@@ -5060,11 +5060,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return true;
}
if (r.isActivityTypeHome()) {
- if (homeActivity != null && homeActivity.equals(r.realActivity)) {
+ if (homeActivity != null && homeActivity.equals(r.mActivityComponent)) {
Slog.i(TAG, "Skip force-stop again " + r);
continue;
} else {
- homeActivity = r.realActivity;
+ homeActivity = r.mActivityComponent;
}
}
didSomething = true;
@@ -5075,7 +5075,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
r.app = null;
}
- lastTask = r.getTask();
+ lastTask = r.getTaskRecord();
finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
true);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 3162ee37276e..f3c5630b53f0 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -91,9 +91,6 @@ import android.app.AppOpsManager;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
import android.app.WaitResult;
-import android.app.WindowConfiguration;
-import android.app.WindowConfiguration.ActivityType;
-import android.app.WindowConfiguration.WindowingMode;
import android.app.servertransaction.ActivityLifecycleItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.LaunchActivityItem;
@@ -111,7 +108,6 @@ import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
@@ -434,7 +430,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
mInitialized = true;
mRunningTasks = createRunningTasks();
- mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext, mHandler.getLooper());
+
+ mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext,
+ mHandler.getLooper());
mKeyguardController = new KeyguardController(mService, this);
mPersisterQueue = new PersisterQueue();
@@ -542,7 +540,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
mActivitiesWaitingForVisibleActivity.remove(r);
for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) {
- if (mWaitingForActivityVisible.get(i).matches(r.realActivity)) {
+ if (mWaitingForActivityVisible.get(i).matches(r.mActivityComponent)) {
mWaitingForActivityVisible.remove(i);
}
}
@@ -556,7 +554,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
boolean changed = false;
for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) {
final WaitInfo w = mWaitingForActivityVisible.get(i);
- if (w.matches(r.realActivity)) {
+ if (w.matches(r.mActivityComponent)) {
final WaitResult result = w.getResult();
changed = true;
result.timeout = false;
@@ -590,7 +588,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// Unlike START_TASK_TO_FRONT, When an intent is delivered to top, there
// will be no followup launch signals. Assign the result and launched component.
if (result == START_DELIVERED_TO_TOP) {
- w.who = r.realActivity;
+ w.who = r.mActivityComponent;
}
}
}
@@ -664,31 +662,29 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags,
int filterCallingUid) {
- synchronized (mService.mGlobalLock) {
- try {
- Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
- int modifiedFlags = flags
- | PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS;
- if (intent.isWebIntent()
- || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
- modifiedFlags |= PackageManager.MATCH_INSTANT;
- }
+ try {
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "resolveIntent");
+ int modifiedFlags = flags
+ | PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS;
+ if (intent.isWebIntent()
+ || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
+ modifiedFlags |= PackageManager.MATCH_INSTANT;
+ }
- // In order to allow cross-profile lookup, we clear the calling identity here.
- // Note the binder identity won't affect the result, but filterCallingUid will.
+ // In order to allow cross-profile lookup, we clear the calling identity here.
+ // Note the binder identity won't affect the result, but filterCallingUid will.
- // Cross-user/profile call check are done at the entry points
- // (e.g. AMS.startActivityAsUser).
- final long token = Binder.clearCallingIdentity();
- try {
- return mService.getPackageManagerInternalLocked().resolveIntent(
- intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ // Cross-user/profile call check are done at the entry points
+ // (e.g. AMS.startActivityAsUser).
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mService.getPackageManagerInternalLocked().resolveIntent(
+ intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
} finally {
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ Binder.restoreCallingIdentity(token);
}
+ } finally {
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
@@ -711,7 +707,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
return false;
}
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
final ActivityStack stack = task.getStack();
beginDeferResume();
@@ -740,7 +736,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
- if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,
+ if (r.getActivityStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,
true /* isTop */)) {
// We only set the visibility to true if the activity is allowed to be visible
// based on
@@ -752,7 +748,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
final int applicationInfoUid =
(r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
- if ((r.userId != proc.mUserId) || (r.appInfo.uid != applicationInfoUid)) {
+ if ((r.mUserId != proc.mUserId) || (r.appInfo.uid != applicationInfoUid)) {
Slog.wtf(TAG,
"User ID for activity changing for " + r
+ " appInfo.uid=" + r.appInfo.uid
@@ -793,7 +789,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
"Launching: " + r + " icicle=" + r.icicle + " with results=" + results
+ " newIntents=" + newIntents + " andResume=" + andResume);
- EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId,
+ EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.mUserId,
System.identityHashCode(r), task.taskId, r.shortComponentName);
if (r.isActivityTypeHome()) {
// Home process is the root process of the task.
@@ -1310,7 +1306,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// waiting for the next one to start.
for (int i = 0; i < NS; i++) {
r = stops.get(i);
- final ActivityStack stack = r.getStack();
+ final ActivityStack stack = r.getActivityStack();
if (stack != null) {
if (r.finishing) {
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false,
@@ -1325,7 +1321,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// waiting for the next one to start.
for (int i = 0; i < NF; i++) {
r = finishes.get(i);
- final ActivityStack stack = r.getStack();
+ final ActivityStack stack = r.getActivityStack();
if (stack != null) {
activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
}
@@ -2007,7 +2003,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
void activitySleptLocked(ActivityRecord r) {
mGoingToSleepActivities.remove(r);
- final ActivityStack s = r.getStack();
+ final ActivityStack s = r.getActivityStack();
if (s != null) {
s.checkReadyForSleep();
} else {
@@ -2043,7 +2039,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// A resumed activity cannot be stopping. remove from list
mStoppingActivities.remove(r);
- final ActivityStack stack = r.getStack();
+ final ActivityStack stack = r.getActivityStack();
if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) {
mService.updateUsageStats(r, true);
}
@@ -2059,7 +2055,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// Called when WindowManager has finished animating the launchingBehind activity to the back.
private void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
final ActivityStack stack = task.getStack();
r.mLaunchTaskBehind = false;
@@ -2071,7 +2067,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
// task has been shown briefly
final ActivityRecord top = stack.getTopActivity();
if (top != null) {
- top.getTask().touchActiveTime();
+ top.getTaskRecord().touchActiveTime();
}
}
@@ -2126,7 +2122,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
}
}
if (remove) {
- final ActivityStack stack = s.getStack();
+ final ActivityStack stack = s.getActivityStack();
final boolean shouldSleepOrShutDown = stack != null
? stack.shouldSleepOrShutDownActivities()
: mService.isSleepingOrShuttingDownLocked();
@@ -2216,8 +2212,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
pw.println(header);
header = null;
}
- if (lastTask != r.getTask()) {
- lastTask = r.getTask();
+ if (lastTask != r.getTaskRecord()) {
+ lastTask = r.getTaskRecord();
pw.print(prefix);
pw.print(full ? "* " : " ");
pw.println(lastTask);
@@ -2374,7 +2370,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
mWindowManager.notifyAppRelaunchingFinished(token);
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
- if (r.getStack().shouldSleepOrShutDownActivities()) {
+ if (r.getActivityStack().shouldSleepOrShutDownActivities()) {
r.setSleeping(true, true);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 54a63a168588..b8442a887dac 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -282,10 +282,10 @@ class ActivityStartInterceptor {
}
ActivityRecord homeActivityRecord = mRootActivityContainer.getDefaultDisplayHomeActivity();
- if (homeActivityRecord != null && homeActivityRecord.getTask() != null) {
- // Showing credential confirmation activity in home task to avoid stopping multi-windowed
- // mode after showing the full-screen credential confirmation activity.
- mActivityOptions.setLaunchTaskId(homeActivityRecord.getTask().taskId);
+ if (homeActivityRecord != null && homeActivityRecord.getTaskRecord() != null) {
+ // Showing credential confirmation activity in home task to avoid stopping
+ // multi-windowed mode after showing the full-screen credential confirmation activity.
+ mActivityOptions.setLaunchTaskId(homeActivityRecord.getTaskRecord().taskId);
}
final UserInfo parent = mUserManager.getProfileParent(mUserId);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index cba104401b49..bc2136ebcf15 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -678,7 +678,7 @@ class ActivityStarter {
}
if (err == ActivityManager.START_SUCCESS && sourceRecord != null
- && sourceRecord.getTask().voiceSession != null) {
+ && sourceRecord.getTaskRecord().voiceSession != null) {
// If this activity is being launched as part of a voice session, we need
// to ensure that it is safe to do so. If the upcoming activity will also
// be part of the voice session, we can only launch it if it has explicitly
@@ -718,7 +718,8 @@ class ActivityStarter {
}
}
- final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
+ final ActivityStack resultStack = resultRecord == null
+ ? null : resultRecord.getActivityStack();
if (err != START_SUCCESS) {
if (resultRecord != null) {
@@ -738,7 +739,8 @@ class ActivityStarter {
// not sure if we need to create START_ABORTED_BACKGROUND so for now piggybacking
// on START_ABORTED
if (!abort) {
- abort |= shouldAbortBackgroundActivityStart(callingUid, callingPackage, callerApp);
+ abort |= shouldAbortBackgroundActivityStart(callingUid, callingPackage, realCallingUid,
+ callerApp);
}
// Merge the two options bundles, while realCallerOptions takes precedence.
@@ -886,7 +888,7 @@ class ActivityStarter {
}
private boolean shouldAbortBackgroundActivityStart(int callingUid, final String callingPackage,
- WindowProcessController callerApp) {
+ int realCallingUid, WindowProcessController callerApp) {
if (mService.isBackgroundActivityStartsEnabled()) {
return false;
}
@@ -898,12 +900,12 @@ class ActivityStarter {
if (callerApp != null && callerApp.hasForegroundActivities()) {
return false;
}
- // don't abort if the callingUid's process is important enough
- if (mService.getUidStateLocked(callingUid) <= ActivityManager.PROCESS_STATE_TOP) {
+ // don't abort if the callingUid is in the foreground
+ if (isUidForeground(callingUid)) {
return false;
}
- // don't abort if the callingUid has any visible window
- if (mService.mWindowManager.isAnyWindowVisibleForUid(callingUid)) {
+ // don't abort if the realCallingUid is in the foreground and callingUid isn't
+ if ((realCallingUid != callingUid) && isUidForeground(realCallingUid)) {
return false;
}
// don't abort if the caller has the same uid as the recents component
@@ -920,6 +922,12 @@ class ActivityStarter {
return true;
}
+ /** Returns true if uid has a visible window or its process is in top or persistent state. */
+ private boolean isUidForeground(int uid) {
+ return (mService.getUidStateLocked(uid) <= ActivityManager.PROCESS_STATE_TOP)
+ || mService.mWindowManager.isAnyWindowVisibleForUid(uid);
+ }
+
private void maybeLogActivityStart(int callingUid, String callingPackage, int realCallingUid,
Intent intent, WindowProcessController callerApp, ActivityRecord r,
PendingIntentRecord originatingPendingIntent, boolean abortedStart) {
@@ -1227,7 +1235,7 @@ class ActivityStarter {
}
case START_DELIVERED_TO_TOP: {
outResult.timeout = false;
- outResult.who = r.realActivity;
+ outResult.who = r.mActivityComponent;
outResult.totalTime = 0;
break;
}
@@ -1236,11 +1244,12 @@ class ActivityStarter {
// in the resumed state.
if (r.nowVisible && r.isState(RESUMED)) {
outResult.timeout = false;
- outResult.who = r.realActivity;
+ outResult.who = r.mActivityComponent;
outResult.totalTime = 0;
} else {
final long startTimeMs = SystemClock.uptimeMillis();
- mSupervisor.waitActivityVisible(r.realActivity, outResult, startTimeMs);
+ mSupervisor.waitActivityVisible(
+ r.mActivityComponent, outResult, startTimeMs);
// Note: the timeout variable is not currently not ever set.
do {
try {
@@ -1286,7 +1295,7 @@ class ActivityStarter {
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
} finally {
- final ActivityStack currentStack = r.getStack();
+ final ActivityStack currentStack = r.getActivityStack();
startedActivityStack = currentStack != null ? currentStack : mTargetStack;
if (ActivityManager.isStartResultSuccessful(result)) {
@@ -1306,7 +1315,7 @@ class ActivityStarter {
// If we are not able to proceed, disassociate the activity from the task.
// Leaving an activity in an incomplete state can lead to issues, such as
// performing operations without a window container.
- final ActivityStack stack = mStartActivity.getStack();
+ final ActivityStack stack = mStartActivity.getActivityStack();
if (stack != null) {
stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
null /* intentResultData */, "startActivity", true /* oomAdj */);
@@ -1351,7 +1360,8 @@ class ActivityStarter {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
- if (mService.getLockTaskController().isLockTaskModeViolation(reusedActivity.getTask(),
+ if (mService.getLockTaskController().isLockTaskModeViolation(
+ reusedActivity.getTaskRecord(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
@@ -1368,14 +1378,14 @@ class ActivityStarter {
// If mStartActivity does not have a task associated with it, associate it with the
// reused activity's task. Do not do so if we're clearing top and resetting for a
// standard launchMode activity.
- if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
- mStartActivity.setTask(reusedActivity.getTask());
+ if (mStartActivity.getTaskRecord() == null && !clearTopAndResetStandardLaunchMode) {
+ mStartActivity.setTask(reusedActivity.getTaskRecord());
}
- if (reusedActivity.getTask().intent == null) {
+ if (reusedActivity.getTaskRecord().intent == null) {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
- reusedActivity.getTask().setIntent(mStartActivity);
+ reusedActivity.getTaskRecord().setIntent(mStartActivity);
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
@@ -1384,7 +1394,7 @@ class ActivityStarter {
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
- final TaskRecord task = reusedActivity.getTask();
+ final TaskRecord task = reusedActivity.getTaskRecord();
// In this situation we want to remove all activities from the task up to the one
// being started. In most cases this means we are resetting the task to its initial
@@ -1396,7 +1406,7 @@ class ActivityStarter {
// the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
// task reference is needed in the call below to
// {@link setTargetStackAndMoveToFrontIfNeeded}.
- if (reusedActivity.getTask() == null) {
+ if (reusedActivity.getTaskRecord() == null) {
reusedActivity.setTask(task);
}
@@ -1404,7 +1414,7 @@ class ActivityStarter {
if (top.frontOfTask) {
// Activity aliases may mean we use different intents for the top activity,
// so make sure the task now has the identity of the new intent.
- top.getTask().setIntent(mStartActivity);
+ top.getTaskRecord().setIntent(mStartActivity);
}
deliverNewIntent(top);
}
@@ -1451,7 +1461,7 @@ class ActivityStarter {
if (mStartActivity.packageName == null) {
final ActivityStack sourceStack = mStartActivity.resultTo != null
- ? mStartActivity.resultTo.getStack() : null;
+ ? mStartActivity.resultTo.getActivityStack() : null;
if (sourceStack != null) {
sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,
mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,
@@ -1467,8 +1477,8 @@ class ActivityStarter {
final ActivityRecord topFocused = topStack.getTopActivity();
final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);
final boolean dontStart = top != null && mStartActivity.resultTo == null
- && top.realActivity.equals(mStartActivity.realActivity)
- && top.userId == mStartActivity.userId
+ && top.mActivityComponent.equals(mStartActivity.mActivityComponent)
+ && top.mUserId == mStartActivity.mUserId
&& top.attachedToProcess()
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK))
@@ -1493,7 +1503,7 @@ class ActivityStarter {
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
- mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
+ mSupervisor.handleNonResizableTaskIfNeeded(top.getTaskRecord(), preferredWindowingMode,
mPreferredDisplayId, topStack);
return START_DELIVERED_TO_TOP;
@@ -1501,7 +1511,7 @@ class ActivityStarter {
boolean newTask = false;
final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
- ? mSourceRecord.getTask() : null;
+ ? mSourceRecord.getTaskRecord() : null;
// Should this be considered a new task?
int result = START_SUCCESS;
@@ -1523,16 +1533,16 @@ class ActivityStarter {
}
mService.mUgmInternal.grantUriPermissionFromIntent(mCallingUid, mStartActivity.packageName,
- mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);
+ mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.mUserId);
mService.getPackageManagerInternalLocked().grantEphemeralAccess(
- mStartActivity.userId, mIntent, UserHandle.getAppId(mStartActivity.appInfo.uid),
+ mStartActivity.mUserId, mIntent, UserHandle.getAppId(mStartActivity.appInfo.uid),
UserHandle.getAppId(mCallingUid));
if (newTask) {
- EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.userId,
- mStartActivity.getTask().taskId);
+ EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, mStartActivity.mUserId,
+ mStartActivity.getTaskRecord().taskId);
}
ActivityStack.logStartActivity(
- EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());
+ EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTaskRecord());
mTargetStack.mLastPausedActivity = null;
mRootActivityContainer.sendPowerHintForLaunchStartIfNeeded(
@@ -1542,7 +1552,7 @@ class ActivityStarter {
mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
- mStartActivity.getTask().topRunningActivityLocked();
+ mStartActivity.getTaskRecord().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
@@ -1570,12 +1580,12 @@ class ActivityStarter {
mTargetStack, mStartActivity, mOptions);
}
} else if (mStartActivity != null) {
- mSupervisor.mRecentTasks.add(mStartActivity.getTask());
+ mSupervisor.mRecentTasks.add(mStartActivity.getTaskRecord());
}
- mRootActivityContainer.updateUserStack(mStartActivity.userId, mTargetStack);
+ mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
- mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
- mPreferredDisplayId, mTargetStack);
+ mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTaskRecord(),
+ preferredWindowingMode, mPreferredDisplayId, mTargetStack);
return START_SUCCESS;
}
@@ -1732,7 +1742,7 @@ class ActivityStarter {
checkedCaller = mRootActivityContainer.getTopDisplayFocusedStack()
.topRunningNonDelayedActivityLocked(mNotTop);
}
- if (!checkedCaller.realActivity.equals(r.realActivity)) {
+ if (!checkedCaller.mActivityComponent.equals(r.mActivityComponent)) {
// Caller is not the same as launcher, so always needed.
mStartFlags &= ~START_FLAG_ONLY_IF_NEEDED;
}
@@ -1743,7 +1753,7 @@ class ActivityStarter {
private void sendNewTaskResultRequestIfNeeded() {
final ActivityStack sourceStack = mStartActivity.resultTo != null
- ? mStartActivity.resultTo.getStack() : null;
+ ? mStartActivity.resultTo.getActivityStack() : null;
if (sourceStack != null && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
// For whatever reason this activity is being launched into a new task...
// yet the caller has requested a result back. Well, that is pretty messed up,
@@ -1847,7 +1857,7 @@ class ActivityStarter {
return;
}
if (!mSourceRecord.finishing) {
- mSourceStack = mSourceRecord.getStack();
+ mSourceStack = mSourceRecord.getActivityStack();
return;
}
@@ -1865,7 +1875,7 @@ class ActivityStarter {
// example, if this method is being called for processing a pending activity launch, it
// is possible that the activity has been removed from the task after the launch was
// enqueued.
- final TaskRecord sourceTask = mSourceRecord.getTask();
+ final TaskRecord sourceTask = mSourceRecord.getTaskRecord();
mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
}
mSourceRecord = null;
@@ -1928,7 +1938,7 @@ class ActivityStarter {
* @return {@link ActivityRecord} brought to front.
*/
private ActivityRecord setTargetStackAndMoveToFrontIfNeeded(ActivityRecord intentActivity) {
- mTargetStack = intentActivity.getStack();
+ mTargetStack = intentActivity.getActivityStack();
mTargetStack.mLastPausedActivity = null;
// If the target task is not in the front, then we need to bring it to the front...
// except... well, with SINGLE_TASK_LAUNCH it's not entirely clear. We'd like to have
@@ -1939,9 +1949,9 @@ class ActivityStarter {
final ActivityStack focusStack = mTargetStack.getDisplay().getFocusedStack();
final ActivityRecord curTop = (focusStack == null)
? null : focusStack.topRunningNonDelayedActivityLocked(mNotTop);
- final TaskRecord topTask = curTop != null ? curTop.getTask() : null;
+ final TaskRecord topTask = curTop != null ? curTop.getTaskRecord() : null;
differentTopTask = topTask != null
- && (topTask != intentActivity.getTask() || topTask != focusStack.topTask());
+ && (topTask != intentActivity.getTaskRecord() || topTask != focusStack.topTask());
} else {
// The existing task should always be different from those in other displays.
differentTopTask = true;
@@ -1950,10 +1960,11 @@ class ActivityStarter {
if (differentTopTask && !mAvoidMoveToFront) {
mStartActivity.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
if (mSourceRecord == null || (mSourceStack.getTopActivity() != null &&
- mSourceStack.getTopActivity().getTask() == mSourceRecord.getTask())) {
+ mSourceStack.getTopActivity().getTaskRecord()
+ == mSourceRecord.getTaskRecord())) {
// We really do want to push this one into the user's face, right now.
if (mLaunchTaskBehind && mSourceRecord != null) {
- intentActivity.setTaskToAffiliateWith(mSourceRecord.getTask());
+ intentActivity.setTaskToAffiliateWith(mSourceRecord.getTaskRecord());
}
// If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
@@ -1967,8 +1978,8 @@ class ActivityStarter {
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
if (!willClearTask) {
final ActivityStack launchStack = getLaunchStack(
- mStartActivity, mLaunchFlags, mStartActivity.getTask(), mOptions);
- final TaskRecord intentTask = intentActivity.getTask();
+ mStartActivity, mLaunchFlags, mStartActivity.getTaskRecord(), mOptions);
+ final TaskRecord intentTask = intentActivity.getTaskRecord();
if (launchStack == null || launchStack == mTargetStack) {
// We only want to move to the front, if we aren't going to launch on a
// different stack. If we launch on a different stack, we will put the
@@ -1998,7 +2009,7 @@ class ActivityStarter {
// Target and computed stacks are on different displays and we've
// found a matching task - move the existing instance to that display and
// move it to front.
- intentActivity.getTask().reparent(launchStack, ON_TOP,
+ intentActivity.getTaskRecord().reparent(launchStack, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"reparentToDisplay");
mMovedToFront = true;
@@ -2008,7 +2019,7 @@ class ActivityStarter {
// For example, the activity may have been initially started with an intent
// which placed it in the fullscreen stack. To ensure the proper handling of
// the activity based on home stack assumptions, we must move it over.
- intentActivity.getTask().reparent(launchStack, ON_TOP,
+ intentActivity.getTaskRecord().reparent(launchStack, ON_TOP,
REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
"reparentingHome");
mMovedToFront = true;
@@ -2024,14 +2035,14 @@ class ActivityStarter {
}
// Need to update mTargetStack because if task was moved out of it, the original stack may
// be destroyed.
- mTargetStack = intentActivity.getStack();
+ mTargetStack = intentActivity.getActivityStack();
if (!mMovedToFront && mDoResume) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Bring to front target: " + mTargetStack
+ " from " + intentActivity);
mTargetStack.moveToFront("intentActivityFound");
}
- mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
+ mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTaskRecord(),
WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
// If the caller has requested that the target task be reset, then do so.
@@ -2053,14 +2064,14 @@ class ActivityStarter {
// launching another activity.
// TODO(b/36119896): We shouldn't trigger activity launches in this path since we are
// already launching one.
- final TaskRecord task = intentActivity.getTask();
+ final TaskRecord task = intentActivity.getTaskRecord();
task.performClearTaskLocked();
mReuseTask = task;
mReuseTask.setIntent(mStartActivity);
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
- ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
- mLaunchFlags);
+ final ActivityRecord top = intentActivity.getTaskRecord().performClearTaskLocked(
+ mStartActivity, mLaunchFlags);
if (top == null) {
// A special case: we need to start the activity because it is not currently
// running, and the caller has asked to clear the current task to have this
@@ -2072,7 +2083,7 @@ class ActivityStarter {
// Now pretend like this activity is being started by the top of its task, so it
// is put in the right place.
mSourceRecord = intentActivity;
- final TaskRecord task = mSourceRecord.getTask();
+ final TaskRecord task = mSourceRecord.getTaskRecord();
if (task != null && task.getStack() == null) {
// Target stack got cleared when we all activities were removed above.
// Go ahead and reset it.
@@ -2082,19 +2093,21 @@ class ActivityStarter {
!mLaunchTaskBehind /* toTop */, "startActivityUnchecked");
}
}
- } else if (mStartActivity.realActivity.equals(intentActivity.getTask().realActivity)) {
+ } else if (mStartActivity.mActivityComponent.equals(
+ intentActivity.getTaskRecord().realActivity)) {
// In this case the top activity on the task is the same as the one being launched,
// so we take that as a request to bring the task to the foreground. If the top
// activity in the task is the root activity, deliver this new intent to it if it
// desires.
if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| LAUNCH_SINGLE_TOP == mLaunchMode)
- && intentActivity.realActivity.equals(mStartActivity.realActivity)) {
+ && intentActivity.mActivityComponent.equals(
+ mStartActivity.mActivityComponent)) {
if (intentActivity.frontOfTask) {
- intentActivity.getTask().setIntent(mStartActivity);
+ intentActivity.getTaskRecord().setIntent(mStartActivity);
}
deliverNewIntent(intentActivity);
- } else if (!intentActivity.getTask().isSameIntentFilter(mStartActivity)) {
+ } else if (!intentActivity.getTaskRecord().isSameIntentFilter(mStartActivity)) {
// In this case we are launching the root activity of the task, but with a
// different intent. We should start a new instance on top.
mAddingToTask = true;
@@ -2107,13 +2120,13 @@ class ActivityStarter {
// current task.
mAddingToTask = true;
mSourceRecord = intentActivity;
- } else if (!intentActivity.getTask().rootWasReset) {
+ } else if (!intentActivity.getTaskRecord().rootWasReset) {
// In this case we are launching into an existing task that has not yet been started
// from its front door. The current task has been brought to the front. Ideally,
// we'd probably like to place this new task at the bottom of its stack, but that's
// a little hard to do with the current organization of the code so for now we'll
// just drop it.
- intentActivity.getTask().setIntent(mStartActivity);
+ intentActivity.getTaskRecord().setIntent(mStartActivity);
}
}
@@ -2123,7 +2136,7 @@ class ActivityStarter {
} else {
ActivityOptions.abort(mOptions);
}
- mRootActivityContainer.updateUserStack(mStartActivity.userId, mTargetStack);
+ mRootActivityContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
}
private int setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) {
@@ -2134,16 +2147,16 @@ class ActivityStarter {
if (mReuseTask == null) {
final TaskRecord task = mTargetStack.createTaskRecord(
- mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId),
+ mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId),
mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
mVoiceInteractor, !mLaunchTaskBehind /* toTop */, mStartActivity, mSourceRecord,
mOptions);
addOrReparentStartingActivity(task, "setTaskFromReuseOrCreateNewTask - mReuseTask");
- updateBounds(mStartActivity.getTask(), mLaunchParams.mBounds);
+ updateBounds(mStartActivity.getTaskRecord(), mLaunchParams.mBounds);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in new task " + mStartActivity.getTask());
+ + " in new task " + mStartActivity.getTaskRecord());
} else {
addOrReparentStartingActivity(mReuseTask, "setTaskFromReuseOrCreateNewTask");
}
@@ -2152,7 +2165,8 @@ class ActivityStarter {
mStartActivity.setTaskToAffiliateWith(taskToAffiliate);
}
- if (mService.getLockTaskController().isLockTaskModeViolation(mStartActivity.getTask())) {
+ if (mService.getLockTaskController().isLockTaskModeViolation(
+ mStartActivity.getTaskRecord())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
@@ -2168,20 +2182,21 @@ class ActivityStarter {
return;
}
- ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTask());
+ ActivityStack.logStartActivity(AM_NEW_INTENT, activity, activity.getTaskRecord());
activity.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
mIntentDelivered = true;
}
private int setTaskFromSourceRecord() {
- if (mService.getLockTaskController().isLockTaskModeViolation(mSourceRecord.getTask())) {
+ if (mService.getLockTaskController().isLockTaskModeViolation(
+ mSourceRecord.getTaskRecord())) {
Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
- final TaskRecord sourceTask = mSourceRecord.getTask();
- final ActivityStack sourceStack = mSourceRecord.getStack();
+ final TaskRecord sourceTask = mSourceRecord.getTaskRecord();
+ final ActivityStack sourceStack = mSourceRecord.getActivityStack();
// We only want to allow changing stack in two cases:
// 1. If the target task is not the top one. Otherwise we would move the launching task to
// the other side, rather than show two side by side.
@@ -2191,8 +2206,8 @@ class ActivityStarter {
final boolean moveStackAllowed = sourceStack.topTask() != sourceTask
|| !mStartActivity.canBeLaunchedOnDisplay(targetDisplayId);
if (moveStackAllowed) {
- mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, mStartActivity.getTask(),
- mOptions);
+ mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags,
+ mStartActivity.getTaskRecord(), mOptions);
// If target stack is not found now - we can't just rely on the source stack, as it may
// be not suitable. Let's check other displays.
if (mTargetStack == null && targetDisplayId != sourceStack.mDisplayId) {
@@ -2229,7 +2244,7 @@ class ActivityStarter {
ActivityRecord top = sourceTask.performClearTaskLocked(mStartActivity, mLaunchFlags);
mKeepCurTransition = true;
if (top != null) {
- ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
+ ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTaskRecord());
deliverNewIntent(top);
// For paranoia, make sure we have correctly resumed the top activity.
mTargetStack.mLastPausedActivity = null;
@@ -2245,7 +2260,7 @@ class ActivityStarter {
// stack if so.
final ActivityRecord top = sourceTask.findActivityInHistoryLocked(mStartActivity);
if (top != null) {
- final TaskRecord task = top.getTask();
+ final TaskRecord task = top.getTaskRecord();
task.moveActivityToFrontLocked(top);
top.updateOptionsLocked(mOptions);
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, task);
@@ -2262,7 +2277,8 @@ class ActivityStarter {
// the same task as the one that is starting it.
addOrReparentStartingActivity(sourceTask, "setTaskFromSourceRecord");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in existing task " + mStartActivity.getTask() + " from source " + mSourceRecord);
+ + " in existing task " + mStartActivity.getTaskRecord()
+ + " from source " + mSourceRecord);
return START_SUCCESS;
}
@@ -2279,8 +2295,8 @@ class ActivityStarter {
// Check whether we should actually launch the new activity in to the task,
// or just reuse the current activity on top.
ActivityRecord top = mInTask.getTopActivity();
- if (top != null && top.realActivity.equals(mStartActivity.realActivity)
- && top.userId == mStartActivity.userId) {
+ if (top != null && top.mActivityComponent.equals(mStartActivity.mActivityComponent)
+ && top.mUserId == mStartActivity.mUserId) {
if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
@@ -2322,7 +2338,7 @@ class ActivityStarter {
addOrReparentStartingActivity(mInTask, "setTaskFromInTask");
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in explicit task " + mStartActivity.getTask());
+ + " in explicit task " + mStartActivity.getTaskRecord());
return START_SUCCESS;
}
@@ -2348,17 +2364,18 @@ class ActivityStarter {
mTargetStack.moveToFront("addingToTopTask");
}
final ActivityRecord prev = mTargetStack.getTopActivity();
- final TaskRecord task = (prev != null) ? prev.getTask() : mTargetStack.createTaskRecord(
- mSupervisor.getNextTaskIdForUserLocked(mStartActivity.userId), mStartActivity.info,
+ final TaskRecord task = (prev != null)
+ ? prev.getTaskRecord() : mTargetStack.createTaskRecord(
+ mSupervisor.getNextTaskIdForUserLocked(mStartActivity.mUserId), mStartActivity.info,
mIntent, null, null, true, mStartActivity, mSourceRecord, mOptions);
addOrReparentStartingActivity(task, "setTaskToCurrentTopOrCreateNewTask");
mTargetStack.positionChildWindowContainerAtTop(task);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Starting new activity " + mStartActivity
- + " in new guessed " + mStartActivity.getTask());
+ + " in new guessed " + mStartActivity.getTaskRecord());
}
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
- if (mStartActivity.getTask() == null || mStartActivity.getTask() == parent) {
+ if (mStartActivity.getTaskRecord() == null || mStartActivity.getTaskRecord() == parent) {
parent.addActivityToTop(mStartActivity);
} else {
mStartActivity.reparent(parent, parent.mActivities.size() /* top */, reason);
@@ -2394,7 +2411,7 @@ class ActivityStarter {
private ActivityStack computeStackFocus(ActivityRecord r, boolean newTask, int launchFlags,
ActivityOptions aOptions) {
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
ActivityStack stack = getLaunchStack(r, launchFlags, task, aOptions);
if (stack != null) {
return stack;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index d6655928105e..0cdbedba7318 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -473,4 +473,6 @@ public abstract class ActivityTaskManagerInternal {
public abstract void setProfileApp(String profileApp);
public abstract void setProfileProc(WindowProcessController wpc);
public abstract void setProfilerInfo(ProfilerInfo profilerInfo);
+
+ public abstract ActivityMetricsLaunchObserverRegistry getLaunchObserverRegistry();
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 8f99dae89316..0967afda6d2d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -190,6 +190,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IUserManager;
import android.os.LocaleList;
+import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
@@ -246,7 +247,6 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
-import com.android.server.DisplayThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
@@ -753,9 +753,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return mGlobalLock;
}
- public void setActivityManagerService(IntentFirewall intentFirewall,
- PendingIntentController intentController) {
- mH = new H();
+ public void initialize(IntentFirewall intentFirewall, PendingIntentController intentController,
+ Looper looper) {
+ mH = new H(looper);
mUiHandler = new UiHandler();
mIntentFirewall = intentFirewall;
final File systemDir = SystemServiceManager.ensureSystemDir();
@@ -1442,7 +1442,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return true;
}
// Keep track of the root activity of the task before we finish it
- TaskRecord tr = r.getTask();
+ final TaskRecord tr = r.getTaskRecord();
ActivityRecord rootR = tr.getRootActivity();
if (rootR == null) {
Slog.w(TAG, "Finishing task with all activities already finished");
@@ -1457,7 +1457,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// We should consolidate.
if (mController != null) {
// Find the first activity that is not finishing.
- ActivityRecord next = r.getStack().topRunningActivityLocked(token, 0);
+ final ActivityRecord next = r.getActivityStack().topRunningActivityLocked(token, 0);
if (next != null) {
// ask watcher if this is allowed
boolean resumeOK = true;
@@ -1519,7 +1519,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
// can finish.
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
if (getLockTaskController().activityBlockedFromFinish(r)) {
return false;
}
@@ -1822,7 +1822,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (r == null) {
return false;
}
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
int index = task.mActivities.lastIndexOf(r);
if (index > 0) {
ActivityRecord under = task.mActivities.get(index - 1);
@@ -1830,7 +1830,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
final boolean translucentChanged = r.changeWindowTranslucency(false);
if (translucentChanged) {
- r.getStack().convertActivityToTranslucent(r);
+ r.getActivityStack().convertActivityToTranslucent(r);
}
mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mWindowManager.setAppFullscreen(token, false);
@@ -1847,7 +1847,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
ActivityRecord r = mRootActivityContainer.isInAnyStack(token);
if (r != null) {
- r.getStack().notifyActivityDrawnLocked(r);
+ r.getActivityStack().notifyActivityDrawnLocked(r);
}
}
}
@@ -1967,7 +1967,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final ActivityRecord srec = ActivityRecord.forTokenLocked(token);
if (srec != null) {
- return srec.getStack().shouldUpRecreateTaskLocked(srec, destAffinity);
+ return srec.getActivityStack().shouldUpRecreateTaskLocked(srec, destAffinity);
}
}
return false;
@@ -1980,7 +1980,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r != null) {
- return r.getStack().navigateUpToLocked(r, destIntent, resultCode, resultData);
+ return r.getActivityStack().navigateUpToLocked(
+ r, destIntent, resultCode, resultData);
}
return false;
}
@@ -2300,7 +2301,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final long origId = Binder.clearCallingIdentity();
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
- r.getStack().finishSubActivityLocked(r, resultWho, requestCode);
+ r.getActivityStack().finishSubActivityLocked(r, resultWho, requestCode);
}
Binder.restoreCallingIdentity(origId);
}
@@ -2545,7 +2546,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (r == null) {
return;
}
- startLockTaskModeLocked(r.getTask(), false /* isSystemCaller */);
+ startLockTaskModeLocked(r.getTaskRecord(), false /* isSystemCaller */);
}
}
@@ -2578,7 +2579,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (r == null) {
return;
}
- stopLockTaskModeInternal(r.getTask(), false /* isSystemCaller */);
+ stopLockTaskModeInternal(r.getTaskRecord(), false /* isSystemCaller */);
}
}
@@ -2671,7 +2672,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
r.setTaskDescription(td);
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
task.updateTaskDescription();
mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.taskId, td);
}
@@ -2727,7 +2728,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public boolean isTopOfTask(IBinder token) {
synchronized (mGlobalLock) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
- return r != null && r.getTask().getTopActivity() == r;
+ return r != null && r.getTaskRecord().getTopActivity() == r;
}
}
@@ -2766,8 +2767,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
if (structure != null) {
// Pre-fill the task/activity component for all assist data receivers
- structure.setTaskId(pae.activity.getTask().taskId);
- structure.setActivityComponent(pae.activity.realActivity);
+ structure.setTaskId(pae.activity.getTaskRecord().taskId);
+ structure.setActivityComponent(pae.activity.mActivityComponent);
structure.setHomeActivity(pae.isHome);
}
pae.haveResult = true;
@@ -2875,9 +2876,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
+ ainfo.applicationInfo.uid + ", calling uid=" + callingUid);
}
- final ActivityStack stack = r.getStack();
+ final ActivityStack stack = r.getActivityStack();
final TaskRecord task = stack.createTaskRecord(
- mStackSupervisor.getNextTaskIdForUserLocked(r.userId), ainfo, intent,
+ mStackSupervisor.getNextTaskIdForUserLocked(r.mUserId), ainfo, intent,
null /* voiceSession */, null /* voiceInteractor */, !ON_TOP);
if (!mRecentTasks.addToBottom(task)) {
// The app has too many tasks already and we can't add any more
@@ -2973,7 +2974,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (r == null) {
return false;
}
- return r.getStack().safelyDestroyActivityLocked(r, "app-req");
+ return r.getActivityStack().safelyDestroyActivityLocked(r, "app-req");
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -3123,7 +3124,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
"exitFreeformMode: No activity record matching token=" + token);
}
- final ActivityStack stack = r.getStack();
+ final ActivityStack stack = r.getActivityStack();
if (stack == null || !stack.inFreeformWindowingMode()) {
throw new IllegalStateException(
"exitFreeformMode: You can only go fullscreen from freeform.");
@@ -3409,7 +3410,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (activity == null) {
return false;
}
- userId = activity.userId;
+ userId = activity.mUserId;
}
return !DevicePolicyCache.getInstance().getScreenCaptureDisabled(userId);
}
@@ -3783,14 +3784,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
private boolean isInPictureInPictureMode(ActivityRecord r) {
- if (r == null || r.getStack() == null || !r.inPinnedWindowingMode()
- || r.getStack().isInStackLocked(r) == null) {
+ if (r == null || r.getActivityStack() == null || !r.inPinnedWindowingMode()
+ || r.getActivityStack().isInStackLocked(r) == null) {
return false;
}
// If we are animating to fullscreen then we have already dispatched the PIP mode
// changed, so we should reflect that check here as well.
- final PinnedActivityStack stack = r.getStack();
+ final PinnedActivityStack stack = r.getActivityStack();
final PinnedStackWindowController windowController = stack.getWindowContainerController();
return !windowController.isAnimatingBoundsToFullscreen();
}
@@ -3826,7 +3827,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
r.pictureInPictureArgs.getSourceRectHint());
mRootActivityContainer.moveActivityToPinnedStack(
r, sourceBounds, aspectRatio, "enterPictureInPictureMode");
- final PinnedActivityStack stack = r.getStack();
+ final PinnedActivityStack stack = r.getActivityStack();
stack.setPictureInPictureAspectRatio(aspectRatio);
stack.setPictureInPictureActions(actions);
MetricsLoggerWrapper.logPictureInPictureEnter(mContext, r.appInfo.uid,
@@ -3870,7 +3871,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// If the activity is already in picture-in-picture, update the pinned stack now
// if it is not already expanding to fullscreen. Otherwise, the arguments will
// be used the next time the activity enters PiP
- final PinnedActivityStack stack = r.getStack();
+ final PinnedActivityStack stack = r.getActivityStack();
if (!stack.isAnimatingBoundsToFullscreen()) {
stack.setPictureInPictureAspectRatio(
r.pictureInPictureArgs.getAspectRatio());
@@ -3928,8 +3929,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
if (params.hasSetAspectRatio()
- && !mWindowManager.isValidPictureInPictureAspectRatio(r.getStack().mDisplayId,
- params.getAspectRatio())) {
+ && !mWindowManager.isValidPictureInPictureAspectRatio(
+ r.getActivityStack().mDisplayId, params.getAspectRatio())) {
final float minAspectRatio = mContext.getResources().getFloat(
com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
final float maxAspectRatio = mContext.getResources().getFloat(
@@ -4015,7 +4016,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
int err;
- if ((err = vrService.hasVrPackage(packageName, r.userId)) !=
+ if ((err = vrService.hasVrPackage(packageName, r.mUserId)) !=
VrManagerInternal.NO_ERROR) {
return err;
}
@@ -4045,7 +4046,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
throw new SecurityException("Only focused activity can call startVoiceInteraction");
}
- if (mRunningVoice != null || activity.getTask().voiceSession != null
+ if (mRunningVoice != null || activity.getTaskRecord().voiceSession != null
|| activity.voiceSession != null) {
Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
return;
@@ -4255,7 +4256,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (mLastResumedActivity == null) {
return getCurrentUserId();
}
- return mLastResumedActivity.userId;
+ return mLastResumedActivity.mUserId;
}
}
@@ -4435,7 +4436,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
+ " to main stack for VR");
final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().getOrCreateStack(
WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */);
- moveTaskToStack(r.getTask().taskId, stack.mStackId, true /* toTop */);
+ moveTaskToStack(r.getTaskRecord().taskId, stack.mStackId, true /* toTop */);
}
mH.post(() -> {
if (!mVrController.onVrModeChanged(r)) {
@@ -4511,6 +4512,21 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return mKeyguardController.isKeyguardLocked();
}
+ /**
+ * Clears launch params for the given package.
+ * @param packageNames the names of the packages of which the launch params are to be cleared
+ */
+ @Override
+ public void clearLaunchParamsForPackages(List<String> packageNames) {
+ mAmInternal.enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "clearLaunchParamsForPackages");
+ synchronized (mGlobalLock) {
+ for (int i = 0; i < packageNames.size(); ++i) {
+ mStackSupervisor.mLaunchParamsPersister.removeRecordForPackage(packageNames.get(i));
+ }
+ }
+ }
+
void dumpLastANRLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
if (mLastANRState == null) {
@@ -4631,7 +4647,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
needSep = true;
synchronized (mGlobalLock) {
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
if (lastTask != task) {
lastTask = task;
pw.print("TASK "); pw.print(lastTask.affinity);
@@ -5095,7 +5111,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
/** Update AMS states when an activity is resumed. */
void setResumedActivityUncheckLocked(ActivityRecord r, String reason) {
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
if (task.isActivityTypeStandard()) {
if (mCurAppTimeTracker != r.appTimeTracker) {
// We are switching app tracking. Complete the current one.
@@ -5127,7 +5143,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (mLastResumedActivity != null) {
final IVoiceInteractionSession session;
- final TaskRecord lastResumedActivityTask = mLastResumedActivity.getTask();
+ final TaskRecord lastResumedActivityTask = mLastResumedActivity.getTaskRecord();
if (lastResumedActivityTask != null
&& lastResumedActivityTask.voiceSession != null) {
session = lastResumedActivityTask.voiceSession;
@@ -5145,8 +5161,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
- if (mLastResumedActivity != null && r.userId != mLastResumedActivity.userId) {
- mAmInternal.sendForegroundProfileChanged(r.userId);
+ if (mLastResumedActivity != null && r.mUserId != mLastResumedActivity.mUserId) {
+ mAmInternal.sendForegroundProfileChanged(r.mUserId);
}
updateResumedAppTrace(r);
mLastResumedActivity = r;
@@ -5157,7 +5173,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
applyUpdateVrModeLocked(r);
EventLogTags.writeAmSetResumedActivity(
- r == null ? -1 : r.userId,
+ r == null ? -1 : r.mUserId,
r == null ? "NULL" : r.shortComponentName,
reason);
}
@@ -5219,7 +5235,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
void updateUsageStats(ActivityRecord component, boolean resumed) {
final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::updateUsageStats,
- mAmInternal, component.realActivity, component.app.mUid, component.userId, resumed);
+ mAmInternal, component.mActivityComponent, component.app.mUid, component.mUserId,
+ resumed);
mH.sendMessage(m);
}
@@ -5254,7 +5271,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mHeavyWeightProcess = root.app;
final Message m = PooledLambda.obtainMessage(
ActivityTaskManagerService::postHeavyWeightProcessNotification, this,
- root.app, root.intent, root.userId);
+ root.app, root.intent, root.mUserId);
mH.sendMessage(m);
}
@@ -5576,8 +5593,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_SUPERVISOR_STACK_MSG = 200;
- public H() {
- super(DisplayThread.get().getLooper());
+ H(Looper looper) {
+ super(looper);
}
@Override
@@ -5622,7 +5639,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
synchronized (mGlobalLock) {
final ActivityRecord homeActivity =
mRootActivityContainer.getDefaultDisplayHomeActivityForUser(userId);
- return homeActivity == null ? null : homeActivity.realActivity;
+ return homeActivity == null ? null : homeActivity.mActivityComponent;
}
}
@@ -6116,9 +6133,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
int requestCode, int resultCode, Intent data) {
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
- if (r != null && r.getStack() != null) {
- r.getStack().sendActivityResultLocked(callingUid, r, resultWho, requestCode,
- resultCode, data);
+ if (r != null && r.getActivityStack() != null) {
+ r.getActivityStack().sendActivityResultLocked(callingUid, r, resultWho,
+ requestCode, resultCode, data);
}
}
}
@@ -6392,7 +6409,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final ActivityRecord homeActivity =
mRootActivityContainer.getDefaultDisplayHomeActivity();
if (homeActivity != null) {
- activityOptions.setLaunchTaskId(homeActivity.getTask().taskId);
+ activityOptions.setLaunchTaskId(homeActivity.getTaskRecord().taskId);
}
mContext.startActivityAsUser(intent, activityOptions.toBundle(),
UserHandle.CURRENT);
@@ -6879,5 +6896,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mProfilerInfo = profilerInfo;
}
}
+
+ @Override
+ public ActivityMetricsLaunchObserverRegistry getLaunchObserverRegistry() {
+ synchronized (mGlobalLock) {
+ return mStackSupervisor.getActivityMetricsLogger().getLaunchObserverRegistry();
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AppWarnings.java b/services/core/java/com/android/server/wm/AppWarnings.java
index 04368570e02e..6c3fbc1f4160 100644
--- a/services/core/java/com/android/server/wm/AppWarnings.java
+++ b/services/core/java/com/android/server/wm/AppWarnings.java
@@ -123,7 +123,8 @@ class AppWarnings {
// TODO(b/75318890): Need to move this to when the app actually crashes.
if (/*ActivityManager.isRunningInTestHarness()
- &&*/ !mAlwaysShowUnsupportedCompileSdkWarningActivities.contains(r.realActivity)) {
+ &&*/ !mAlwaysShowUnsupportedCompileSdkWarningActivities.contains(
+ r.mActivityComponent)) {
// Don't show warning if we are running in a test harness and we don't have to always
// show for this activity.
return;
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index b9b9d31f5b71..bb38f3035a6c 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -53,7 +53,8 @@ class AppWindowThumbnail implements Animatable {
AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader) {
mAppToken = appToken;
- mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, appToken.mService);
+ mSurfaceAnimator =
+ new SurfaceAnimator(this, this::onAnimationFinished, appToken.mWmService);
mWidth = thumbnailHeader.getWidth();
mHeight = thumbnailHeader.getHeight();
@@ -93,11 +94,11 @@ class AppWindowThumbnail implements Animatable {
void startAnimation(Transaction t, Animation anim, Point position) {
anim.restrictDuration(MAX_ANIMATION_DURATION);
- anim.scaleCurrentDuration(mAppToken.mService.getTransitionAnimationScaleLocked());
+ anim.scaleCurrentDuration(mAppToken.mWmService.getTransitionAnimationScaleLocked());
mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
new WindowAnimationSpec(anim, position,
mAppToken.getDisplayContent().mAppTransition.canSkipFirstFrame()),
- mAppToken.mService.mSurfaceAnimationRunner), false /* hidden */);
+ mAppToken.mWmService.mSurfaceAnimationRunner), false /* hidden */);
}
private void onAnimationFinished() {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index df81c07ba530..fb93d39b33d4 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -554,7 +554,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// * or this is an opening app and windows are being replaced.
boolean visibilityChanged = false;
if (isHidden() == visible || (isHidden() && mIsExiting) || (visible && waitingForReplacement())) {
- final AccessibilityController accessibilityController = mService.mAccessibilityController;
+ final AccessibilityController accessibilityController =
+ mWmService.mAccessibilityController;
boolean changed = false;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM,
"Changing app " + this + " hidden=" + isHidden() + " performLayout=" + performLayout);
@@ -595,7 +596,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// We are becoming visible, so better freeze the screen with the windows that are
// getting visible so we also wait for them.
- forAllWindows(mService::makeWindowFreezingScreenIfNeededLocked, true);
+ forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
}
if (DEBUG_APP_TRANSITIONS) {
@@ -606,9 +607,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (changed) {
getDisplayContent().getInputMonitor().setUpdateInputWindowsNeededLw();
if (performLayout) {
- mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
false /*updateInputWindows*/);
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
}
getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
}
@@ -635,7 +636,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// The token was made immediately visible, there will be no entrance animation.
// We need to inform the client the enter animation was finished.
mEnteringAnimation = true;
- mService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(token);
+ mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
+ token);
}
// If we're becoming visible, immediately change client visibility as well. there seem
@@ -658,7 +660,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// Take the screenshot before possibly hiding the WSA, otherwise the screenshot
// will not be taken.
- mService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
+ mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
}
// If we are hidden but there is no delay needed we immediately
@@ -774,7 +776,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
getDisplayContent().mOpeningApps.remove(this);
getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
- mService.mTaskSnapshotController.onAppRemoved(this);
+ mWmService.mTaskSnapshotController.onAppRemoved(this);
waitingToShow = false;
if (getDisplayContent().mClosingApps.contains(this)) {
delayed = true;
@@ -827,7 +829,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this
+ " displayId=" + dc.getDisplayId());
dc.setFocusedApp(null);
- mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
+ mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
}
if (!delayed) {
@@ -1141,7 +1143,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// if we got a replacement window, reset the timeout to give drawing more time
if (gotReplacementWindow) {
- mService.scheduleWindowReplacementTimeouts(this);
+ mWmService.scheduleWindowReplacementTimeouts(this);
}
checkKeyguardFlagsChanged();
}
@@ -1271,7 +1273,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
final WindowState win = mChildren.get(i);
win.onUnfreezeBounds();
}
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
}
void setAppLayoutChanges(int changes, String reason) {
@@ -1279,7 +1281,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
final DisplayContent dc = getDisplayContent();
dc.pendingLayoutChanges |= changes;
if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
+ mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
}
}
}
@@ -1300,12 +1302,12 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (!hiddenRequested) {
if (!mFreezingScreen) {
mFreezingScreen = true;
- mService.registerAppFreezeListener(this);
- mService.mAppsFreezingScreen++;
- if (mService.mAppsFreezingScreen == 1) {
- mService.startFreezingDisplayLocked(0, 0, getDisplayContent());
- mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
- mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
+ mWmService.registerAppFreezeListener(this);
+ mWmService.mAppsFreezingScreen++;
+ if (mWmService.mAppsFreezingScreen == 1) {
+ mWmService.startFreezingDisplayLocked(0, 0, getDisplayContent());
+ mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
+ mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
}
}
final int count = mChildren.size();
@@ -1330,15 +1332,15 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (force || unfrozeWindows) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "No longer freezing: " + this);
mFreezingScreen = false;
- mService.unregisterAppFreezeListener(this);
- mService.mAppsFreezingScreen--;
- mService.mLastFinishedFreezeSource = this;
+ mWmService.unregisterAppFreezeListener(this);
+ mWmService.mAppsFreezingScreen--;
+ mWmService.mLastFinishedFreezeSource = this;
}
if (unfreezeSurfaceNow) {
if (unfrozeWindows) {
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
}
- mService.stopFreezingDisplayLocked();
+ mWmService.stopFreezingDisplayLocked();
}
}
@@ -1429,10 +1431,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// pending opening apps.
getDisplayContent().mOpeningApps.remove(this);
- mService.updateFocusedWindowLocked(
+ mWmService.updateFocusedWindowLocked(
UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
getDisplayContent().setLayoutNeeded();
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -1602,7 +1604,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (mDisplayContent != null) {
mDisplayContent.setLayoutNeeded();
}
- mService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
+ mWmService.mH.obtainMessage(NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
// Notify the pinned stack upon all windows drawn. If there was an animation in
// progress then this signal will resume that animation.
@@ -1636,8 +1638,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
return false;
}
- if (mLastTransactionSequence != mService.mTransactionSequence) {
- mLastTransactionSequence = mService.mTransactionSequence;
+ if (mLastTransactionSequence != mWmService.mTransactionSequence) {
+ mLastTransactionSequence = mWmService.mTransactionSequence;
mNumDrawnWindows = 0;
startingDisplayed = false;
@@ -1769,7 +1771,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
final ActivityManager.TaskSnapshot snapshot =
- mService.mTaskSnapshotController.getSnapshot(
+ mWmService.mTaskSnapshotController.getSnapshot(
getTask().mTaskId, getTask().mUserId,
false /* restoreFromDisk */, false /* reducedResolution */);
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
@@ -1788,7 +1790,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (theme != 0) {
AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
com.android.internal.R.styleable.Window,
- mService.mCurrentUserId);
+ mWmService.mCurrentUserId);
if (ent == null) {
// Whoops! App doesn't exist. Um. Okay. We'll just pretend like we didn't
// see that.
@@ -1838,7 +1840,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
- startingData = new SplashScreenStartingData(mService, pkg,
+ startingData = new SplashScreenStartingData(mWmService, pkg,
theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
getMergedOverrideConfiguration());
scheduleAddStartingWindow();
@@ -1853,7 +1855,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
- startingData = new SnapshotStartingData(mService, snapshot);
+ startingData = new SnapshotStartingData(mWmService, snapshot);
scheduleAddStartingWindow();
return true;
}
@@ -1862,9 +1864,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// Note: we really want to do sendMessageAtFrontOfQueue() because we
// want to process the message ASAP, before any other queued
// messages.
- if (!mService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
+ if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Enqueueing ADD_STARTING");
- mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
+ mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
}
}
@@ -1872,9 +1874,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
@Override
public void run() {
- synchronized (mService.mGlobalLock) {
+ synchronized (mWmService.mGlobalLock) {
// There can only be one adding request, silly caller!
- mService.mAnimationHandler.removeCallbacks(this);
+ mWmService.mAnimationHandler.removeCallbacks(this);
}
if (startingData == null) {
@@ -1898,7 +1900,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
if (surface != null) {
boolean abort = false;
- synchronized (mService.mGlobalLock) {
+ synchronized (mWmService.mGlobalLock) {
// If the window was successfully added, then
// we need to remove it.
if (removed || startingData == null) {
@@ -1998,7 +2000,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
// Use the same thread to remove the window as we used to add it, as otherwise we end up
// with things in the view hierarchy being called from different threads.
- mService.mAnimationHandler.post(() -> {
+ mWmService.mAnimationHandler.post(() -> {
if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
try {
surface.remove();
@@ -2054,7 +2056,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
|| containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
- mService.notifyKeyguardFlagsChanged(null /* callback */,
+ mWmService.notifyKeyguardFlagsChanged(null /* callback */,
getDisplayContent().getDisplayId());
}
mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
@@ -2194,7 +2196,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
boolean isVoiceInteraction) {
- if (mService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
+ if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
Slog.v(TAG_WM, "applyAnimation: transition animation is disabled or skipped."
+ " atoken=" + this);
@@ -2228,7 +2230,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
getDisplayContent().mAppTransition.canSkipFirstFrame(),
appStackClipMode,
true /* isAppAnimation */),
- mService.mSurfaceAnimationRunner);
+ mWmService.mSurfaceAnimationRunner);
if (a.getZAdjustment() == Animation.ZORDER_TOP) {
mNeedsZBoost = true;
}
@@ -2311,7 +2313,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
final int containingWidth = frame.width();
final int containingHeight = frame.height();
a.initialize(containingWidth, containingHeight, width, height);
- a.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
+ a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
}
return a;
}
@@ -2516,7 +2518,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
return;
}
final Rect frame = win.getFrameLw();
- final int thumbnailDrawableRes = getTask().mUserId == mService.mCurrentUserId
+ final int thumbnailDrawableRes = getTask().mUserId == mWmService.mCurrentUserId
? R.drawable.ic_account_circle
: R.drawable.ic_corp_badge;
final GraphicBuffer thumbnail =
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index fa3c7ca29284..aea071f94ba2 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -131,7 +131,7 @@ class Dimmer {
if (!mDimming) {
dimAnimatable.getPendingTransaction().destroy(mDimLayer);
}
- }, mHost.mService);
+ }, mHost.mWmService);
}
}
@@ -333,7 +333,7 @@ class Dimmer {
SurfaceControl.Transaction t, float startAlpha, float endAlpha) {
mSurfaceAnimatorStarter.startAnimation(animator, t, new LocalAnimationAdapter(
new AlphaAnimationSpec(startAlpha, endAlpha, getDimDuration(container)),
- mHost.mService.mSurfaceAnimationRunner), false /* hidden */);
+ mHost.mWmService.mSurfaceAnimationRunner), false /* hidden */);
}
private long getDimDuration(WindowContainer container) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c0e983653b27..05e82676a40a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -29,12 +29,12 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
+import static android.view.InsetsState.TYPE_IME;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
-import static android.view.InsetsState.TYPE_IME;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
@@ -100,6 +100,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.CUSTOM_SCREEN_ROTATION;
+import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE;
import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
@@ -208,21 +209,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
/** The containers below are the only child containers the display can have. */
// Contains all window containers that are related to apps (Activities)
- private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(mService);
+ private final TaskStackContainers mTaskStackContainers = new TaskStackContainers(mWmService);
// Contains all non-app window containers that should be displayed above the app containers
// (e.g. Status bar)
private final AboveAppWindowContainers mAboveAppWindowsContainers =
- new AboveAppWindowContainers("mAboveAppWindowsContainers", mService);
+ new AboveAppWindowContainers("mAboveAppWindowsContainers", mWmService);
// Contains all non-app window containers that should be displayed below the app containers
// (e.g. Wallpaper).
private final NonAppWindowContainers mBelowAppWindowsContainers =
- new NonAppWindowContainers("mBelowAppWindowsContainers", mService);
+ new NonAppWindowContainers("mBelowAppWindowsContainers", mWmService);
// Contains all IME window containers. Note that the z-ordering of the IME windows will depend
// on the IME target. We mainly have this container grouping so we can keep track of all the IME
// window containers together and move them in-sync if/when needed. We use a subclass of
// WindowContainer which is omitted from screen magnification, as the IME is never magnified.
private final NonMagnifiableWindowContainers mImeWindowsContainers =
- new NonMagnifiableWindowContainers("mImeWindowsContainers", mService);
+ new NonMagnifiableWindowContainers("mImeWindowsContainers", mWmService);
private WindowState mTmpWindow;
private WindowState mTmpWindow2;
@@ -525,7 +526,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (w.performShowLocked()) {
pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
+ mWmService.mWindowPlacerLocked.debugLayoutRepeats(
"updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
}
}
@@ -556,7 +557,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private final Consumer<WindowState> mScheduleToastTimeout = w -> {
final int lostFocusUid = mTmpWindow.mOwnerUid;
- final Handler handler = mService.mH;
+ final Handler handler = mWmService.mH;
if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
@@ -618,7 +619,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private final Consumer<WindowState> mPerformLayout = w -> {
// Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
// wasting time and funky changes while a window is animating away.
- final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w))
+ final boolean gone = (mTmpWindow != null && mWmService.mPolicy.canBeHiddenByKeyguardLw(w))
|| w.isGoneForLayoutLw();
if (DEBUG_LAYOUT && !w.mLayoutAttached) {
@@ -686,7 +687,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// If this view is GONE, then skip it -- keep the current frame, and let the caller
// know so they can ignore it if they want. (We do the normal layout for INVISIBLE
// windows, since that means "perform layout as normal, just don't display").
- if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) {
+ if (mTmpWindow != null && mWmService.mPolicy.canBeHiddenByKeyguardLw(w)) {
return;
}
if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
@@ -721,10 +722,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mInputMethodTarget);
private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
- final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
+ final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
final boolean obscuredChanged = w.mObscured !=
mTmpApplySurfaceChangesTransactionState.obscured;
- final RootWindowContainer root = mService.mRoot;
+ final RootWindowContainer root = mWmService.mRoot;
// Update effect.
w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
@@ -815,7 +816,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
if (!mLosingFocus.isEmpty() && w.isFocused() && w.isDisplayedLw()) {
- mService.mH.obtainMessage(REPORT_LOSING_FOCUS, this).sendToTarget();
+ mWmService.mH.obtainMessage(REPORT_LOSING_FOCUS, this).sendToTarget();
}
w.updateResizingWindowIfNeeded();
@@ -840,7 +841,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mDisplay = display;
mDisplayId = display.getDisplayId();
- mWallpaperController = new WallpaperController(mService, this);
+ mWallpaperController = new WallpaperController(mWmService, this);
display.getDisplayInfo(mDisplayInfo);
display.getMetrics(mDisplayMetrics);
isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
@@ -857,8 +858,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mBoundsAnimationController = new BoundsAnimationController(service.mContext,
mAppTransition, SurfaceAnimationThread.getHandler(), animationHandler);
- if (mService.mInputManager != null) {
- final InputChannel inputChannel = mService.mInputManager.monitorInput("Display "
+ if (mWmService.mInputManager != null) {
+ final InputChannel inputChannel = mWmService.mInputManager.monitorInput("Display "
+ mDisplayId, mDisplayId);
mPointerEventDispatcher = inputChannel != null
? new PointerEventDispatcher(inputChannel) : null;
@@ -870,18 +871,18 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (isDefaultDisplay) {
// The policy may be invoked right after here, so it requires the necessary default
// fields of this display content.
- mService.mPolicy.setDefaultDisplay(this);
+ mWmService.mPolicy.setDefaultDisplay(this);
}
- if (mService.mDisplayReady) {
+ if (mWmService.mDisplayReady) {
mDisplayPolicy.onConfigurationChanged();
}
- if (mService.mSystemReady) {
+ if (mWmService.mSystemReady) {
mDisplayPolicy.systemReady();
}
mDividerControllerLocked = new DockedStackDividerController(service, this);
mPinnedStackControllerLocked = new PinnedStackController(service, this);
- final SurfaceControl.Builder b = mService.makeSurfaceBuilder(mSession).setOpaque(true);
+ final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(mSession).setOpaque(true);
mWindowingLayer = b.setName("Display Root").build();
mOverlayLayer = b.setName("Display Overlays").build();
@@ -900,20 +901,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
super.addChild(mImeWindowsContainers, null);
// Add itself as a child to the root container.
- mService.mRoot.addChild(this, null);
+ mWmService.mRoot.addChild(this, null);
// TODO(b/62541591): evaluate whether this is the best spot to declare the
// {@link DisplayContent} ready for use.
mDisplayReady = true;
- mService.mAnimator.addDisplayLocked(mDisplayId);
+ mWmService.mAnimator.addDisplayLocked(mDisplayId);
mInputMonitor = new InputMonitor(service, mDisplayId);
mInsetsStateController = new InsetsStateController(this);
}
boolean isReady() {
// The display is ready when the system and the individual display are both ready.
- return mService.mDisplayReady && mDisplayReady;
+ return mWmService.mDisplayReady && mDisplayReady;
}
int getDisplayId() {
@@ -933,7 +934,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
private void addWindowToken(IBinder binder, WindowToken token) {
- final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
+ final DisplayContent dc = mWmService.mRoot.getWindowTokenDisplay(token);
if (dc != null) {
// We currently don't support adding a window token to the display if the display
// already has the binder mapped to another token. If there is a use case for supporting
@@ -1139,7 +1140,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
/** Notify the configuration change of this display. */
void sendNewConfiguration() {
- mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, this).sendToTarget();
+ mWmService.mH.obtainMessage(SEND_NEW_CONFIGURATION, this).sendToTarget();
}
/**
@@ -1214,7 +1215,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
screenRotationAnimation =
- mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
+ mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
// Rotation updates cannot be performed while the previous rotation change
// animation is still in progress. Skip this update. We will try updating
@@ -1222,7 +1223,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, animation in progress.");
return false;
}
- if (mService.mDisplayFrozen) {
+ if (mWmService.mDisplayFrozen) {
// Even if the screen rotation animation has finished (e.g. isAnimating
// returns false), there is still some time where we haven't yet unfrozen
// the display. We also need to abort rotation here.
@@ -1232,7 +1233,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
- if (!mService.mDisplayEnabled) {
+ if (!mWmService.mDisplayEnabled) {
// No point choosing a rotation if the display is not enabled.
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Deferring rotation, display is not enabled.");
return false;
@@ -1263,8 +1264,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (hasPinnedStack()) {
mayRotateSeamlessly = false;
}
- for (int i = 0; i < mService.mSessions.size(); i++) {
- if (mService.mSessions.valueAt(i).hasAlertWindowSurfaces()) {
+ for (int i = 0; i < mWmService.mSessions.size(); i++) {
+ if (mWmService.mSessions.valueAt(i).hasAlertWindowSurfaces()) {
mayRotateSeamlessly = false;
break;
}
@@ -1302,8 +1303,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mRotation = rotation;
mAltOrientation = altOrientation;
- mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
- mService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
+ mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE;
+ mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT,
this, WINDOW_FREEZE_TIMEOUT_DURATION);
setLayoutNeeded();
@@ -1311,14 +1312,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mDisplayPolicy.selectRotationAnimationLw(anim);
if (!rotateSeamlessly) {
- mService.startFreezingDisplayLocked(anim[0], anim[1], this);
+ mWmService.startFreezingDisplayLocked(anim[0], anim[1], this);
// startFreezingDisplayLocked can reset the ScreenRotationAnimation.
} else {
// The screen rotation animation uses a screenshot to freeze the screen
// while windows resize underneath.
// When we are rotating seamlessly, we allow the elements to transition
// to their rotated state independently and without a freeze required.
- mService.startSeamlessRotation();
+ mWmService.startSeamlessRotation();
}
return true;
@@ -1333,9 +1334,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
void applyRotationLocked(final int oldRotation, final int rotation) {
mDisplayRotation.setRotation(rotation);
- final boolean rotateSeamlessly = mService.isRotatingSeamlessly();
+ final boolean rotateSeamlessly = mWmService.isRotatingSeamlessly();
ScreenRotationAnimation screenRotationAnimation = rotateSeamlessly
- ? null : mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
+ ? null : mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
// We need to update our screen size information to match the new rotation. If the rotation
// has actually changed then this method will return true and, according to the comment at
// the top of the method, the caller is obligated to call computeNewConfigurationLocked().
@@ -1348,9 +1349,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
&& screenRotationAnimation.hasScreenshot()) {
if (screenRotationAnimation.setRotation(getPendingTransaction(), rotation,
- MAX_ANIMATION_DURATION, mService.getTransitionAnimationScaleLocked(),
+ MAX_ANIMATION_DURATION, mWmService.getTransitionAnimationScaleLocked(),
mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
- mService.scheduleAnimationLocked();
+ mWmService.scheduleAnimationLocked();
}
}
@@ -1359,27 +1360,27 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
rotateSeamlessly);
}, true /* traverseTopToBottom */);
- mService.mDisplayManagerInternal.performTraversal(getPendingTransaction());
+ mWmService.mDisplayManagerInternal.performTraversal(getPendingTransaction());
scheduleAnimation();
forAllWindows(w -> {
if (w.mHasSurface && !rotateSeamlessly) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Set mOrientationChanging of " + w);
w.setOrientationChanging(true);
- mService.mRoot.mOrientationChangeComplete = false;
+ mWmService.mRoot.mOrientationChangeComplete = false;
w.mLastFreezeDuration = 0;
}
w.mReportOrientationChanged = true;
}, true /* traverseTopToBottom */);
if (rotateSeamlessly) {
- mService.mH.sendNewMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT,
+ mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.SEAMLESS_ROTATION_TIMEOUT,
this, SEAMLESS_ROTATION_TIMEOUT_DURATION);
}
- for (int i = mService.mRotationWatchers.size() - 1; i >= 0; i--) {
+ for (int i = mWmService.mRotationWatchers.size() - 1; i >= 0; i--) {
final WindowManagerService.RotationWatcher rotationWatcher
- = mService.mRotationWatchers.get(i);
+ = mWmService.mRotationWatchers.get(i);
if (rotationWatcher.mDisplayId == mDisplayId) {
try {
rotationWatcher.mWatcher.onRotationChanged(rotation);
@@ -1392,9 +1393,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// TODO (multi-display): Magnification is supported only for the default display.
// Announce rotation only if we will not animate as we already have the
// windows in final state. Otherwise, we make this call at the rotation end.
- if (screenRotationAnimation == null && mService.mAccessibilityController != null
+ if (screenRotationAnimation == null && mWmService.mAccessibilityController != null
&& isDefaultDisplay) {
- mService.mAccessibilityController.onRotationChangedLocked(this);
+ mWmService.mAccessibilityController.onRotationChangedLocked(this);
}
}
@@ -1428,9 +1429,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
Slog.d(TAG,
"Registering PointerEventListener for DisplayId: " + mDisplayId);
}
- mTapDetector = new TaskTapPointerEventListener(mService, this);
+ mTapDetector = new TaskTapPointerEventListener(mWmService, this);
registerPointerEventListener(mTapDetector);
- registerPointerEventListener(mService.mMousePositionTracker);
+ registerPointerEventListener(mWmService.mMousePositionTracker);
}
}
@@ -1495,7 +1496,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// because we don't want letter-/pillar-boxing during resize.
final DisplayInfo overrideDisplayInfo = mShouldOverrideDisplayConfiguration
? mDisplayInfo : null;
- mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
+ mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(mDisplayId,
overrideDisplayInfo);
mBaseDisplayRect.set(0, 0, dw, dh);
@@ -1581,10 +1582,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
config.densityDpi = displayInfo.logicalDensityDpi;
config.colorMode =
- ((displayInfo.isHdr() && mService.hasHdrSupport())
+ ((displayInfo.isHdr() && mWmService.hasHdrSupport())
? Configuration.COLOR_MODE_HDR_YES
: Configuration.COLOR_MODE_HDR_NO)
- | (displayInfo.isWideColorGamut() && mService.hasWideColorGamutSupport()
+ | (displayInfo.isWideColorGamut() && mWmService.hasWideColorGamutSupport()
? Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_YES
: Configuration.COLOR_MODE_WIDE_COLOR_GAMUT_NO);
@@ -1596,7 +1597,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
int keyboardPresence = 0;
int navigationPresence = 0;
- final InputDevice[] devices = mService.mInputManager.getInputDevices();
+ final InputDevice[] devices = mWmService.mInputManager.getInputDevices();
final int len = devices != null ? devices.length : 0;
for (int i = 0; i < len; i++) {
InputDevice device = devices[i];
@@ -1607,7 +1608,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
WindowManagerPolicy.PRESENCE_INTERNAL;
// TODO(multi-display): Configure on per-display basis.
- if (mService.mIsTouchDevice) {
+ if (mWmService.mIsTouchDevice) {
if ((sources & InputDevice.SOURCE_TOUCHSCREEN) ==
InputDevice.SOURCE_TOUCHSCREEN) {
config.touchscreen = Configuration.TOUCHSCREEN_FINGER;
@@ -1632,7 +1633,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
- if (config.navigation == Configuration.NAVIGATION_NONAV && mService.mHasPermanentDpad) {
+ if (config.navigation == Configuration.NAVIGATION_NONAV && mWmService.mHasPermanentDpad) {
config.navigation = Configuration.NAVIGATION_DPAD;
navigationPresence |= WindowManagerPolicy.PRESENCE_INTERNAL;
}
@@ -1640,10 +1641,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// Determine whether a hard keyboard is available and enabled.
// TODO(multi-display): Should the hardware keyboard be tied to a display or to a device?
boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
- if (hardKeyboardAvailable != mService.mHardKeyboardAvailable) {
- mService.mHardKeyboardAvailable = hardKeyboardAvailable;
- mService.mH.removeMessages(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
- mService.mH.sendEmptyMessage(WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ if (hardKeyboardAvailable != mWmService.mHardKeyboardAvailable) {
+ mWmService.mHardKeyboardAvailable = hardKeyboardAvailable;
+ mWmService.mH.removeMessages(REPORT_HARD_KEYBOARD_STATUS_CHANGE);
+ mWmService.mH.sendEmptyMessage(REPORT_HARD_KEYBOARD_STATUS_CHANGE);
}
mDisplayPolicy.updateConfigurationDependentBehaviors();
@@ -1652,7 +1653,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
config.navigationHidden = Configuration.NAVIGATIONHIDDEN_NO;
- mService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
+ mWmService.mPolicy.adjustConfigurationLw(config, keyboardPresence, navigationPresence);
}
private int computeCompatSmallestWidth(boolean rotated, int uiMode, int dw, int dh,
@@ -1949,7 +1950,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Override
void onAppTransitionDone() {
super.onAppTransitionDone();
- mService.mWindowsChanged = true;
+ mWmService.mWindowsChanged = true;
}
/**
@@ -2001,9 +2002,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Override
int getOrientation() {
- final WindowManagerPolicy policy = mService.mPolicy;
+ final WindowManagerPolicy policy = mWmService.mPolicy;
- if (mService.mDisplayFrozen) {
+ if (mWmService.mDisplayFrozen) {
if (mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId
+ " is frozen, return " + mLastWindowForcedOrientation);
@@ -2044,7 +2045,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
void initializeDisplayBaseInfo() {
- final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
+ final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal;
if (displayManagerInternal != null) {
// Bootstrap the default logical display from the display manager.
final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
@@ -2067,7 +2068,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
private void updateBaseDisplayMetricsIfNeeded() {
// Get real display metrics without overrides from WM.
- mService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
+ mWmService.mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mDisplayInfo);
final int orientation = mDisplayInfo.rotation;
final boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
final int newWidth = rotated ? mDisplayInfo.logicalHeight : mDisplayInfo.logicalWidth;
@@ -2096,7 +2097,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mInitialDisplayHeight = newHeight;
mInitialDisplayDensity = newDensity;
mInitialDisplayCutout = newCutout;
- mService.reconfigureDisplayLocked(this);
+ mWmService.reconfigureDisplayLocked(this);
}
}
@@ -2147,9 +2148,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
void setForcedDensity(int density, int userId) {
final boolean clear = density == mInitialDisplayDensity;
final boolean updateCurrent = userId == UserHandle.USER_CURRENT;
- if (mService.mCurrentUserId == userId || updateCurrent) {
+ if (mWmService.mCurrentUserId == userId || updateCurrent) {
mBaseDisplayDensity = density;
- mService.reconfigureDisplayLocked(this);
+ mWmService.reconfigureDisplayLocked(this);
}
if (updateCurrent) {
// We are applying existing settings so no need to save it again.
@@ -2159,7 +2160,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (density == mInitialDisplayDensity) {
density = 0;
}
- mService.mDisplayWindowSettings.setForcedDensity(this, density, userId);
+ mWmService.mDisplayWindowSettings.setForcedDensity(this, density, userId);
}
/** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */
@@ -2170,9 +2171,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mDisplayScalingDisabled = (mode != FORCE_SCALING_MODE_AUTO);
Slog.i(TAG_WM, "Using display scaling mode: " + (mDisplayScalingDisabled ? "off" : "auto"));
- mService.reconfigureDisplayLocked(this);
+ mWmService.reconfigureDisplayLocked(this);
- mService.mDisplayWindowSettings.setForcedScalingMode(this, mode);
+ mWmService.mDisplayWindowSettings.setForcedScalingMode(this, mode);
}
/** If the given width and height equal to initial size, the setting will be cleared. */
@@ -2189,12 +2190,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
updateBaseDisplayMetrics(width, height, mBaseDisplayDensity);
- mService.reconfigureDisplayLocked(this);
+ mWmService.reconfigureDisplayLocked(this);
if (clear) {
width = height = 0;
}
- mService.mDisplayWindowSettings.setForcedSize(this, width, height);
+ mWmService.mDisplayWindowSettings.setForcedSize(this, width, height);
}
void getStableRect(Rect out) {
@@ -2205,7 +2206,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
+ mDisplayId);
- final TaskStack stack = new TaskStack(mService, stackId, controller);
+ final TaskStack stack = new TaskStack(mWmService, stackId, controller);
mTaskStackContainers.addStackToDisplay(stack, onTop);
return stack;
}
@@ -2361,7 +2362,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Override
void switchUser() {
super.switchUser();
- mService.mWindowsChanged = true;
+ mWmService.mWindowsChanged = true;
}
private void resetAnimationBackgroundAnimator() {
@@ -2389,15 +2390,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mUnknownAppVisibilityController.clear();
mAppTransition.removeAppTransitionTimeoutCallbacks();
handleAnimatingStoppedAndTransition();
- mService.stopFreezingDisplayLocked();
+ mWmService.stopFreezingDisplayLocked();
super.removeImmediately();
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
if (mPointerEventDispatcher != null && mTapDetector != null) {
unregisterPointerEventListener(mTapDetector);
- unregisterPointerEventListener(mService.mMousePositionTracker);
+ unregisterPointerEventListener(mWmService.mMousePositionTracker);
mTapDetector = null;
}
- mService.mAnimator.removeDisplayLocked(mDisplayId);
+ mWmService.mAnimator.removeDisplayLocked(mDisplayId);
mWindowingLayer.release();
mOverlayLayer.release();
} finally {
@@ -2406,7 +2407,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
mDisplayPolicy.onDisplayRemoved();
- mService.mWindowPlacerLocked.requestTraversal();
+ mWmService.mWindowPlacerLocked.requestTraversal();
}
/** Returns true if a removal action is still being deferred. */
@@ -2483,7 +2484,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
&& !mDividerControllerLocked.isImeHideRequested();
final boolean dockVisible = isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
+ final TaskStack imeTargetStack = mWmService.getImeFocusStackLocked();
final int imeDockSide = (dockVisible && imeTargetStack != null) ?
imeTargetStack.getDockSide() : DOCKED_INVALID;
final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
@@ -2610,7 +2611,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mDisplayInfo.writeToProto(proto, DISPLAY_INFO);
proto.write(ROTATION, mRotation);
final ScreenRotationAnimation screenRotationAnimation =
- mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
+ mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
if (screenRotationAnimation != null) {
screenRotationAnimation.writeToProto(proto, SCREEN_ROTATION_ANIMATION);
}
@@ -2855,11 +2856,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
if (imWindowChanged) {
- mService.mWindowsChanged = true;
+ mWmService.mWindowsChanged = true;
setLayoutNeeded();
}
- if (DEBUG_FOCUS_LIGHT || mService.localLOGV) Slog.v(TAG_WM, "Changing focus from "
+ if (DEBUG_FOCUS_LIGHT || mWmService.localLOGV) Slog.v(TAG_WM, "Changing focus from "
+ mCurrentFocus + " to " + newFocus + " displayId=" + getDisplayId()
+ " Callers=" + Debug.getCallers(4));
final WindowState oldFocus = mCurrentFocus;
@@ -2898,7 +2899,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
performLayout(true /*initial*/, updateInputWindows);
} else if (mode == UPDATE_FOCUS_REMOVING_FOCUS) {
- mService.mRoot.performSurfacePlacement(false);
+ mWmService.mRoot.performSurfacePlacement(false);
}
}
@@ -2963,16 +2964,16 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// moving containers or resizing them. Need to investigate the best way to have it automatically
// happen so we don't run into issues with programmers forgetting to do it.
void layoutAndAssignWindowLayersIfNeeded() {
- mService.mWindowsChanged = true;
+ mWmService.mWindowsChanged = true;
setLayoutNeeded();
- if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ if (!mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
false /*updateInputWindows*/)) {
assignWindowLayers(false /* setLayoutNeeded */);
}
mInputMonitor.setUpdateInputWindowsNeededLw();
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
mInputMonitor.updateInputWindowsLw(false /*force*/);
}
@@ -2985,14 +2986,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (wsa.mSurfaceController == null) {
return;
}
- if (!mService.mSessions.contains(wsa.mSession)) {
+ if (!mWmService.mSessions.contains(wsa.mSession)) {
Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
+ w + " surface=" + wsa.mSurfaceController
+ " token=" + w.mToken
+ " pid=" + w.mSession.mPid
+ " uid=" + w.mSession.mUid);
wsa.destroySurface();
- mService.mForceRemoves.add(w);
+ mWmService.mForceRemoves.add(w);
mTmpWindow = w;
} else if (w.mAppToken != null && w.mAppToken.isClientHidden()) {
Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
@@ -3016,7 +3017,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// Update display configuration for IME process.
if (mInputMethodWindow != null) {
final int imePid = mInputMethodWindow.mSession.mPid;
- mService.mAtmInternal.onImeWindowSetOnDisplay(imePid,
+ mWmService.mAtmInternal.onImeWindowSetOnDisplay(imePid,
mInputMethodWindow.getDisplayId());
}
computeImeTarget(true /* updateImeTarget */);
@@ -3237,7 +3238,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* Starts the Keyguard exit animation on all windows that don't belong to an app token.
*/
void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
- final WindowManagerPolicy policy = mService.mPolicy;
+ final WindowManagerPolicy policy = mWmService.mPolicy;
forAllWindows(w -> {
if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)
&& w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
@@ -3266,7 +3267,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
} else if (w.mAttrs.type == TYPE_WALLPAPER) {
mHaveWallpaper = true;
} else if (w.mAttrs.type == TYPE_STATUS_BAR) {
- mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
+ mHaveKeyguard = mWmService.mPolicy.isKeyguardDrawnLw();
}
}
return false;
@@ -3279,28 +3280,28 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// if the wallpaper service is disabled on the device, we're never going to have
// wallpaper, don't bother waiting for it
- boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
+ boolean wallpaperEnabled = mWmService.mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableWallpaperService)
- && mService.mContext.getResources().getBoolean(
+ && mWmService.mContext.getResources().getBoolean(
com.android.internal.R.bool.config_checkWallpaperAtBoot)
- && !mService.mOnlyCore;
+ && !mWmService.mOnlyCore;
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
- "******** booted=" + mService.mSystemBooted
- + " msg=" + mService.mShowingBootMessages
+ "******** booted=" + mWmService.mSystemBooted
+ + " msg=" + mWmService.mShowingBootMessages
+ " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp
+ " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled
+ " haveKeyguard=" + mHaveKeyguard);
// If we are turning on the screen to show the boot message, don't do it until the boot
// message is actually displayed.
- if (!mService.mSystemBooted && !mHaveBootMsg) {
+ if (!mWmService.mSystemBooted && !mHaveBootMsg) {
return true;
}
// If we are turning on the screen after the boot is completed normally, don't do so until
// we have the application and wallpaper.
- if (mService.mSystemBooted
+ if (mWmService.mSystemBooted
&& ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
return true;
}
@@ -3366,7 +3367,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mLastDispatchedSystemUiVisibility = visibility;
if (isDefaultDisplay) {
- mService.mInputManager.setSystemUiVisibility(visibility);
+ mWmService.mInputManager.setSystemUiVisibility(visibility);
}
updateSystemUiVisibility(visibility, globalDiff);
return true;
@@ -3395,13 +3396,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
void reevaluateStatusBarVisibility() {
int visibility = getDisplayPolicy().adjustSystemUiVisibilityLw(mLastStatusBarVisibility);
if (updateStatusBarVisibilityLocked(visibility)) {
- mService.mWindowPlacerLocked.requestTraversal();
+ mWmService.mWindowPlacerLocked.requestTraversal();
}
}
void onWindowFreezeTimeout() {
Slog.w(TAG_WM, "Window freeze timeout expired.");
- mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
+ mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
forAllWindows(w -> {
if (!w.getOrientationChanging()) {
@@ -3409,28 +3410,28 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
w.orientationChangeTimedOut();
w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- - mService.mDisplayFreezeTime);
+ - mWmService.mDisplayFreezeTime);
Slog.w(TAG_WM, "Force clearing orientation change: " + w);
}, true /* traverseTopToBottom */);
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
}
void waitForAllWindowsDrawn() {
- final WindowManagerPolicy policy = mService.mPolicy;
+ final WindowManagerPolicy policy = mWmService.mPolicy;
forAllWindows(w -> {
final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
w.mWinAnimator.mDrawState = DRAW_PENDING;
// Force add to mResizingWindows.
w.resetLastContentInsets();
- mService.mWaitingForDrawn.add(w);
+ mWmService.mWaitingForDrawn.add(w);
}
}, true /* traverseTopToBottom */);
}
// TODO: Super crazy long method that should be broken down...
void applySurfaceChangesTransaction(boolean recoveringMemory) {
- final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
+ final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
mTmpUpdateAllDrawn.clear();
@@ -3487,7 +3488,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
prepareSurfaces();
mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent;
- mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
+ mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
mLastHasContent,
mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
mTmpApplySurfaceChangesTransactionState.preferredModeId,
@@ -3496,7 +3497,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final boolean wallpaperVisible = mWallpaperController.isWallpaperVisible();
if (wallpaperVisible != mLastWallpaperVisible) {
mLastWallpaperVisible = wallpaperVisible;
- mService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this);
+ mWmService.mWallpaperVisibilityListeners.notifyWallpaperVisibilityChanged(this);
}
while (!mTmpUpdateAllDrawn.isEmpty()) {
@@ -3594,7 +3595,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mInputMonitor.updateInputWindowsLw(false /*force*/);
}
- mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
+ mWmService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
}
/**
@@ -3604,7 +3605,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* @param config of the output bitmap
*/
Bitmap screenshotDisplayLocked(Bitmap.Config config) {
- if (!mService.mPolicy.isScreenOn()) {
+ if (!mWmService.mPolicy.isScreenOn()) {
if (DEBUG_SCREENSHOT) {
Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
}
@@ -3632,7 +3633,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
convertCropForSurfaceFlinger(frame, rot, dw, dh);
final ScreenRotationAnimation screenRotationAnimation =
- mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
+ mWmService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
final boolean inRotation = screenRotationAnimation != null &&
screenRotationAnimation.isAnimating();
if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM, "Taking screenshot while rotating");
@@ -3688,11 +3689,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mTmpWindow = w;
w.setDisplayLayoutNeeded();
w.finishSeamlessRotation(true /* timeout */);
- mService.markForSeamlessRotation(w, false);
+ mWmService.markForSeamlessRotation(w, false);
}, true /* traverseTopToBottom */);
if (mTmpWindow != null) {
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
}
}
@@ -3720,20 +3721,20 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Override
void onDescendantOverrideConfigurationChanged() {
setLayoutNeeded();
- mService.requestTraversal();
+ mWmService.requestTraversal();
}
boolean okToDisplay() {
if (mDisplayId == DEFAULT_DISPLAY) {
- return !mService.mDisplayFrozen
- && mService.mDisplayEnabled && mService.mPolicy.isScreenOn();
+ return !mWmService.mDisplayFrozen
+ && mWmService.mDisplayEnabled && mWmService.mPolicy.isScreenOn();
}
return mDisplayInfo.state == Display.STATE_ON;
}
boolean okToAnimate() {
return okToDisplay() &&
- (mDisplayId != DEFAULT_DISPLAY || mService.mPolicy.okToAnimate());
+ (mDisplayId != DEFAULT_DISPLAY || mWmService.mPolicy.okToAnimate());
}
static final class TaskForResizePointSearchResult {
@@ -3951,7 +3952,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
} else if (stack == mSplitScreenPrimaryStack) {
mSplitScreenPrimaryStack = null;
// Re-set the split-screen create mode whenever the split-screen stack is removed.
- mService.setDockedStackCreateStateLocked(
+ mWmService.setDockedStackCreateStateLocked(
SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
mDividerControllerLocked.notifyDockedStackExistsChanged(false);
}
@@ -4169,7 +4170,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
final int orientation = super.getOrientation();
- boolean isCar = mService.mContext.getPackageManager().hasSystemFeature(
+ boolean isCar = mWmService.mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_AUTOMOTIVE);
if (isCar) {
// In a car, you cannot physically rotate the screen, so it doesn't make sense to
@@ -4350,10 +4351,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
wt.assignLayer(t, j);
wt.assignChildLayers(t);
- int layer = mService.mPolicy.getWindowLayerFromTypeLw(
+ int layer = mWmService.mPolicy.getWindowLayerFromTypeLw(
wt.windowType, wt.mOwnerCanManageAppTokens);
- if (needAssignIme && layer >= mService.mPolicy.getWindowLayerFromTypeLw(
+ if (needAssignIme && layer >= mWmService.mPolicy.getWindowLayerFromTypeLw(
TYPE_INPUT_METHOD_DIALOG, true)) {
imeContainer.assignRelativeLayer(t, wt.getSurfaceControl(), -1);
needAssignIme = false;
@@ -4376,9 +4377,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
private final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
// Tokens with higher base layer are z-ordered on-top.
- mService.mPolicy.getWindowLayerFromTypeLw(token1.windowType,
+ mWmService.mPolicy.getWindowLayerFromTypeLw(token1.windowType,
token1.mOwnerCanManageAppTokens)
- < mService.mPolicy.getWindowLayerFromTypeLw(token2.windowType,
+ < mWmService.mPolicy.getWindowLayerFromTypeLw(token2.windowType,
token2.mOwnerCanManageAppTokens) ? -1 : 1;
private final Predicate<WindowState> mGetOrientingWindow = w -> {
@@ -4408,7 +4409,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Override
int getOrientation() {
- final WindowManagerPolicy policy = mService.mPolicy;
+ final WindowManagerPolicy policy = mWmService.mPolicy;
// Find a window requesting orientation.
final WindowState win = getWindow(mGetOrientingWindow);
@@ -4416,7 +4417,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final int req = win.mAttrs.screenOrientation;
if (policy.isKeyguardHostWindow(win.mAttrs)) {
mLastKeyguardForcedOrientation = req;
- if (mService.mKeyguardGoingAway) {
+ if (mWmService.mKeyguardGoingAway) {
// Keyguard can't affect the orientation if it is going away...
mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
return SCREEN_ORIENTATION_UNSET;
@@ -4474,7 +4475,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
};
SurfaceControl.Builder makeSurface(SurfaceSession s) {
- return mService.makeSurfaceBuilder(s)
+ return mWmService.makeSurfaceBuilder(s)
.setParent(mWindowingLayer);
}
@@ -4486,7 +4487,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Override
SurfaceControl.Builder makeChildSurface(WindowContainer child) {
SurfaceSession s = child != null ? child.getSession() : getSession();
- final SurfaceControl.Builder b = mService.makeSurfaceBuilder(s);
+ final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(s);
if (child == null) {
return b;
}
@@ -4502,7 +4503,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* and other potpourii.
*/
SurfaceControl.Builder makeOverlay() {
- return mService.makeSurfaceBuilder(mSession)
+ return mWmService.makeSurfaceBuilder(mSession)
.setParent(mOverlayLayer);
}
@@ -4601,7 +4602,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
@Override
void prepareSurfaces() {
final ScreenRotationAnimation screenRotationAnimation =
- mService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
+ mWmService.mAnimator.getScreenRotationAnimationLocked(mDisplayId);
if (screenRotationAnimation != null && screenRotationAnimation.isAnimating()) {
screenRotationAnimation.getEnterTransformation().getMatrix().getValues(mTmpFloats);
mPendingTransaction.setMatrix(mWindowingLayer,
@@ -4689,7 +4690,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
+ mDisplayId + " Callers=" + Debug.getCallers(5));
}
mAppTransition.setReady();
- mService.mWindowPlacerLocked.requestTraversal();
+ mWmService.mWindowPlacerLocked.requestTraversal();
}
}
@@ -4719,7 +4720,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mWallpaperMayChange = true;
// Since the window list has been rebuilt, focus might have to be recomputed since the
// actual order of windows might have changed again.
- mService.mFocusMayChange = true;
+ mWmService.mFocusMayChange = true;
pendingLayoutChanges |= changes;
}
@@ -4732,7 +4733,19 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return mDisplay.supportsSystemDecorations()
// TODO (b/111363427): Remove this and set the new FLAG_SHOULD_SHOW_LAUNCHER flag
// (b/114338689) whenever vr 2d display id is set.
- || mDisplayId == mService.mVr2dDisplayId
- || mService.mForceDesktopModeOnExternalDisplays;
+ || mDisplayId == mWmService.mVr2dDisplayId
+ || mWmService.mForceDesktopModeOnExternalDisplays;
+ }
+
+ /**
+ * Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and
+ * {@link #mOverlayLayer} to the specified surfaceControl.
+ *
+ * @param surfaceControlHandle The handle for the new SurfaceControl, where the DisplayContent's
+ * surfaces will be re-parented to.
+ */
+ void reparentDisplayContent(IBinder surfaceControlHandle) {
+ mPendingTransaction.reparent(mWindowingLayer, surfaceControlHandle)
+ .reparent(mOverlayLayer, surfaceControlHandle);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 0e5947af0c61..f1d77b9961cf 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -45,7 +45,6 @@ import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR;
@@ -2322,12 +2321,6 @@ public class DisplayPolicy {
&& windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
mTopDockedOpaqueOrDimmingWindowState = win;
}
-
- // Take note if a window wants to acquire a sleep token.
- if ((attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0
- && win.canAcquireSleepToken()) {
- mWindowSleepTokenNeeded = true;
- }
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index f1d1e49c1004..7aabc15d9860 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -21,6 +21,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -30,6 +31,7 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.power.V1_0.PowerHint;
+import android.net.Uri;
import android.os.Handler;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -57,6 +59,7 @@ public class DisplayRotation {
private final WindowManagerService mService;
private final DisplayContent mDisplayContent;
private final DisplayPolicy mDisplayPolicy;
+ private final DisplayWindowSettings mDisplayWindowSettings;
private final Context mContext;
private final Object mLock;
@@ -71,10 +74,6 @@ public class DisplayRotation {
private StatusBarManagerInternal mStatusBarManagerInternal;
private SettingsObserver mSettingsObserver;
- // Default display does not rotate, apps that require non-default orientation will have to
- // have the orientation emulated.
- private boolean mForceDefaultOrientation;
-
private int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@VisibleForTesting
@@ -93,6 +92,13 @@ public class DisplayRotation {
private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
private int mUserRotation = Surface.ROTATION_0;
+ /**
+ * A flag to indicate if the display rotation should be fixed to user specified rotation
+ * regardless of all other states (including app requrested orientation). {@code true} the
+ * display rotation should be fixed to user specified rotation, {@code false} otherwise.
+ */
+ private boolean mFixedToUserRotation;
+
private int mDemoHdmiRotation;
private int mDemoRotation;
private boolean mDemoHdmiRotationLock;
@@ -100,15 +106,17 @@ public class DisplayRotation {
DisplayRotation(WindowManagerService service, DisplayContent displayContent) {
this(service, displayContent, displayContent.getDisplayPolicy(),
- service.mContext, service.getWindowManagerLock());
+ service.mDisplayWindowSettings, service.mContext, service.getWindowManagerLock());
}
@VisibleForTesting
DisplayRotation(WindowManagerService service, DisplayContent displayContent,
- DisplayPolicy displayPolicy, Context context, Object lock) {
+ DisplayPolicy displayPolicy, DisplayWindowSettings displayWindowSettings,
+ Context context, Object lock) {
mService = service;
mDisplayContent = displayContent;
mDisplayPolicy = displayPolicy;
+ mDisplayWindowSettings = displayWindowSettings;
mContext = context;
mLock = lock;
isDefaultDisplay = displayContent.isDefaultDisplay;
@@ -204,12 +212,19 @@ public class DisplayRotation {
// so if the orientation is forced, we need to respect that no matter what.
final boolean isTv = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
- mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv) &&
- res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
- // For debug purposes the next line turns this feature off with:
- // $ adb shell setprop config.override_forced_orient true
- // $ adb shell wm size reset
- !"true".equals(SystemProperties.get("config.override_forced_orient"));
+ final boolean forceDefaultOrientationInRes =
+ res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation);
+ final boolean forceDefaultOrienation =
+ ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv)
+ && forceDefaultOrientationInRes
+ // For debug purposes the next line turns this feature off with:
+ // $ adb shell setprop config.override_forced_orient true
+ // $ adb shell wm size reset
+ && !"true".equals(SystemProperties.get("config.override_forced_orient"));
+ // Configuration says we force to use the default orientation. We can fall back to fix
+ // rotation to only user rotation. As long as OEM doesn't change user rotation then the
+ // rotation of this display is effectively stuck at 0 deg.
+ setFixedToUserRotation(forceDefaultOrienation);
}
void setRotation(int rotation) {
@@ -227,7 +242,14 @@ public class DisplayRotation {
}
}
- void restoreUserRotation(int userRotationMode, int userRotation) {
+ void restoreSettings(int userRotationMode, int userRotation,
+ boolean fixedToUserRotation) {
+ mFixedToUserRotation = fixedToUserRotation;
+
+ // We will retrieve user rotation and user rotation mode from settings for default display.
+ if (isDefaultDisplay) {
+ return;
+ }
if (userRotationMode != WindowManagerPolicy.USER_ROTATION_FREE
&& userRotationMode != WindowManagerPolicy.USER_ROTATION_LOCKED) {
Slog.w(TAG, "Trying to restore an invalid user rotation mode " + userRotationMode
@@ -243,6 +265,18 @@ public class DisplayRotation {
mUserRotation = userRotation;
}
+ void setFixedToUserRotation(boolean fixedToUserRotation) {
+ if (mFixedToUserRotation == fixedToUserRotation) {
+ return;
+ }
+
+ mFixedToUserRotation = fixedToUserRotation;
+ mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent,
+ fixedToUserRotation);
+ mService.updateRotation(true /* alwaysSendConfiguration */,
+ false /* forceRelayout */);
+ }
+
private void setUserRotation(int userRotationMode, int userRotation) {
if (isDefaultDisplay) {
// We'll be notified via settings listener, so we don't need to update internal values.
@@ -265,7 +299,7 @@ public class DisplayRotation {
mUserRotation = userRotation;
changed = true;
}
- mService.mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
+ mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
userRotation);
if (changed) {
mService.updateRotation(true /* alwaysSendConfiguration */,
@@ -291,9 +325,8 @@ public class DisplayRotation {
Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) == 0;
}
- /** @return true if com.android.internal.R.bool#config_forceDefaultOrientation is true. */
- boolean isDefaultOrientationForced() {
- return mForceDefaultOrientation;
+ boolean isFixedToUserRotation() {
+ return mFixedToUserRotation;
}
public int getLandscapeRotation() {
@@ -399,6 +432,12 @@ public class DisplayRotation {
* screen is switched off.
*/
private boolean needSensorRunning() {
+ if (mFixedToUserRotation) {
+ // We are sure we only respect user rotation settings, so we are sure we will not
+ // support sensor rotation.
+ return false;
+ }
+
if (mSupportAutoRotation) {
if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
|| mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
@@ -459,8 +498,8 @@ public class DisplayRotation {
);
}
- if (mForceDefaultOrientation) {
- return Surface.ROTATION_0;
+ if (mFixedToUserRotation) {
+ return mUserRotation;
}
int sensorRotation = mOrientationListener != null
@@ -701,8 +740,8 @@ public class DisplayRotation {
// demo, hdmi, vr, etc mode.
// Determine if the rotation is currently forced.
- if (mForceDefaultOrientation) {
- return false; // Rotation is forced to default orientation.
+ if (mFixedToUserRotation) {
+ return false; // Rotation is forced to user settings.
}
final int lidState = mDisplayPolicy.getLidState();
@@ -861,6 +900,7 @@ public class DisplayRotation {
pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
pw.println(prefix + " mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
+ pw.println(prefix + " mFixedToUserRotation=" + mFixedToUserRotation);
}
private class OrientationListener extends WindowOrientationListener {
@@ -945,4 +985,10 @@ public class DisplayRotation {
}
}
}
+
+ @VisibleForTesting
+ interface ContentObserverRegister {
+ void registerContentObserver(Uri uri, boolean notifyForDescendants,
+ ContentObserver observer, @UserIdInt int userHandle);
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index 864f7e1aafae..55b3def7817b 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -90,7 +90,7 @@ public class DisplayWindowController
public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
synchronized (mGlobalLock) {
if (mContainer != null) {
- mContainer.mService.setNewDisplayOverrideConfiguration(overrideConfiguration,
+ mContainer.mWmService.setNewDisplayOverrideConfiguration(overrideConfiguration,
mContainer);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index f7dfd3ffc8bf..45d77dee1851 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -80,6 +80,7 @@ class DisplayWindowSettings {
private boolean mShouldShowWithInsecureKeyguard = false;
private boolean mShouldShowSystemDecors = false;
private boolean mShouldShowIme = false;
+ private boolean mFixedToUserRotation;
private Entry(String name) {
mName = name;
@@ -97,7 +98,8 @@ class DisplayWindowSettings {
&& mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
&& !mShouldShowWithInsecureKeyguard
&& !mShouldShowSystemDecors
- && !mShouldShowIme;
+ && !mShouldShowIme
+ && !mFixedToUserRotation;
}
}
@@ -186,6 +188,13 @@ class DisplayWindowSettings {
writeSettingsIfNeeded(entry, displayInfo);
}
+ void setFixedToUserRotation(DisplayContent displayContent, boolean fixedToUserRotation) {
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ final Entry entry = getOrCreateEntry(displayInfo);
+ entry.mFixedToUserRotation = fixedToUserRotation;
+ writeSettingsIfNeeded(entry, displayInfo);
+ }
+
private int getWindowingModeLocked(Entry entry, int displayId) {
int windowingMode = entry != null ? entry.mWindowingMode
: WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -331,7 +340,8 @@ class DisplayWindowSettings {
displayInfo.overscanRight = entry.mOverscanRight;
displayInfo.overscanBottom = entry.mOverscanBottom;
- dc.getDisplayRotation().restoreUserRotation(entry.mUserRotationMode, entry.mUserRotation);
+ dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode,
+ entry.mUserRotation, entry.mFixedToUserRotation);
if (entry.mForcedDensity != 0) {
dc.mBaseDisplayDensity = entry.mForcedDensity;
@@ -458,6 +468,8 @@ class DisplayWindowSettings {
"shouldShowWithInsecureKeyguard");
entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
+ entry.mFixedToUserRotation = getBooleanAttribute(parser,
+ "fixedToUserRotation");
mEntries.put(name, entry);
}
XmlUtils.skipCurrentTag(parser);
@@ -541,6 +553,10 @@ class DisplayWindowSettings {
if (entry.mShouldShowIme) {
out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
}
+ if (entry.mFixedToUserRotation) {
+ out.attribute(null, "fixedToUserRotation",
+ Boolean.toString(entry.mFixedToUserRotation));
+ }
out.endTag(null, "display");
}
diff --git a/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java b/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
new file mode 100644
index 000000000000..93e2d8d6fba4
--- /dev/null
+++ b/services/core/java/com/android/server/wm/LaunchObserverRegistryImpl.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+import java.util.ArrayList;
+
+/**
+ * Multi-cast implementation of {@link ActivityMetricsLaunchObserver}.
+ *
+ * <br /><br />
+ * If this class is called through the {@link ActivityMetricsLaunchObserver} interface,
+ * then the call is forwarded to all registered observers at the time.
+ *
+ * <br /><br />
+ * All calls are invoked asynchronously in-order on a background thread. This fulfills the
+ * sequential ordering guarantee in {@link ActivityMetricsLaunchObserverRegistry}.
+ *
+ * @see ActivityTaskManagerInternal#getLaunchObserverRegistry()
+ */
+class LaunchObserverRegistryImpl implements
+ ActivityMetricsLaunchObserverRegistry, ActivityMetricsLaunchObserver {
+ private final ArrayList<ActivityMetricsLaunchObserver> mList = new ArrayList<>();
+
+ /**
+ * All calls are posted to a handler because:
+ *
+ * 1. We don't know how long the observer will take to handle this call and we don't want
+ * to block the WM critical section on it.
+ * 2. We don't know the lock ordering of the observer so we don't want to expose a chance
+ * of deadlock.
+ */
+ private final Handler mHandler;
+
+ public LaunchObserverRegistryImpl(Looper looper) {
+ mHandler = new Handler(looper);
+ }
+
+ @Override
+ public void registerLaunchObserver(ActivityMetricsLaunchObserver launchObserver) {
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ LaunchObserverRegistryImpl::handleRegisterLaunchObserver, this, launchObserver));
+ }
+
+ @Override
+ public void unregisterLaunchObserver(ActivityMetricsLaunchObserver launchObserver) {
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ LaunchObserverRegistryImpl::handleUnregisterLaunchObserver, this, launchObserver));
+ }
+
+ @Override
+ public void onIntentStarted(Intent intent) {
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ LaunchObserverRegistryImpl::handleOnIntentStarted, this, intent));
+ }
+
+ @Override
+ public void onIntentFailed() {
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ LaunchObserverRegistryImpl::handleOnIntentFailed, this));
+ }
+
+ @Override
+ public void onActivityLaunched(
+ @ActivityRecordProto byte[] activity,
+ int temperature) {
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ LaunchObserverRegistryImpl::handleOnActivityLaunched,
+ this, activity, temperature));
+ }
+
+ @Override
+ public void onActivityLaunchCancelled(
+ @ActivityRecordProto byte[] activity) {
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ LaunchObserverRegistryImpl::handleOnActivityLaunchCancelled, this, activity));
+ }
+
+ @Override
+ public void onActivityLaunchFinished(
+ @ActivityRecordProto byte[] activity) {
+ mHandler.sendMessage(PooledLambda.obtainMessage(
+ LaunchObserverRegistryImpl::handleOnActivityLaunchFinished, this, activity));
+ }
+
+ // Use PooledLambda.obtainMessage to invoke below methods. Every method reference must be
+ // unbound (i.e. not capture any variables explicitly or implicitly) to fulfill the
+ // singleton-lambda requirement.
+
+ private void handleRegisterLaunchObserver(ActivityMetricsLaunchObserver observer) {
+ mList.add(observer);
+ }
+
+ private void handleUnregisterLaunchObserver(ActivityMetricsLaunchObserver observer) {
+ mList.remove(observer);
+ }
+
+ private void handleOnIntentStarted(Intent intent) {
+ // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
+ for (int i = 0; i < mList.size(); i++) {
+ ActivityMetricsLaunchObserver o = mList.get(i);
+ o.onIntentStarted(intent);
+ }
+ }
+
+ private void handleOnIntentFailed() {
+ // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
+ for (int i = 0; i < mList.size(); i++) {
+ ActivityMetricsLaunchObserver o = mList.get(i);
+ o.onIntentFailed();
+ }
+ }
+
+ private void handleOnActivityLaunched(
+ @ActivityRecordProto byte[] activity,
+ @Temperature int temperature) {
+ // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
+ for (int i = 0; i < mList.size(); i++) {
+ ActivityMetricsLaunchObserver o = mList.get(i);
+ o.onActivityLaunched(activity, temperature);
+ }
+ }
+
+ private void handleOnActivityLaunchCancelled(
+ @ActivityRecordProto byte[] activity) {
+ // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
+ for (int i = 0; i < mList.size(); i++) {
+ ActivityMetricsLaunchObserver o = mList.get(i);
+ o.onActivityLaunchCancelled(activity);
+ }
+ }
+
+ private void handleOnActivityLaunchFinished(
+ @ActivityRecordProto byte[] activity) {
+ // Traverse start-to-end to meet the registerLaunchObserver multi-cast order guarantee.
+ for (int i = 0; i < mList.size(); i++) {
+ ActivityMetricsLaunchObserver o = mList.get(i);
+ o.onActivityLaunchFinished(activity);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
index da9a5071b100..3062d34780b6 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java
@@ -246,8 +246,8 @@ class LaunchParamsPersister {
}
void getLaunchParams(TaskRecord task, ActivityRecord activity, LaunchParams outParams) {
- final ComponentName name = task != null ? task.realActivity : activity.realActivity;
- final int userId = task != null ? task.userId : activity.userId;
+ final ComponentName name = task != null ? task.realActivity : activity.mActivityComponent;
+ final int userId = task != null ? task.userId : activity.mUserId;
outParams.reset();
Map<ComponentName, PersistableLaunchParams> map = mMap.get(userId);
@@ -269,7 +269,7 @@ class LaunchParamsPersister {
outParams.mBounds.set(persistableParams.mBounds);
}
- private void onPackageRemoved(String packageName) {
+ void removeRecordForPackage(String packageName) {
final List<File> fileToDelete = new ArrayList<>();
for (int i = 0; i < mMap.size(); ++i) {
int userId = mMap.keyAt(i);
@@ -310,7 +310,7 @@ class LaunchParamsPersister {
@Override
public void onPackageRemoved(String packageName) {
- LaunchParamsPersister.this.onPackageRemoved(packageName);
+ removeRecordForPackage(packageName);
}
}
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 80dc2458d7f5..d2f2863b8fd1 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -225,7 +225,7 @@ public class LockTaskController {
* of the last locked task and finishing it would mean that lock task mode is ended illegally.
*/
boolean activityBlockedFromFinish(ActivityRecord activity) {
- final TaskRecord task = activity.getTask();
+ final TaskRecord task = activity.getTaskRecord();
if (activity == task.getRootActivity()
&& activity == task.getTopActivity()
&& task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV
@@ -647,7 +647,7 @@ public class LockTaskController {
}
final ActivityRecord r = mSupervisor.mRootActivityContainer.topRunningActivity();
- final TaskRecord task = (r != null) ? r.getTask() : null;
+ final TaskRecord task = (r != null) ? r.getTaskRecord() : null;
if (mLockTaskModeTasks.isEmpty() && task!= null
&& task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
// This task must have just been authorized.
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 24c5228ce0ec..1e287b4e412e 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -148,8 +148,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
// If there are multiple tasks in the target stack (ie. the home stack, with 3p
// and default launchers coexisting), then move the task to the top as a part of
// moving the stack to the front
- if (targetStack.topTask() != targetActivity.getTask()) {
- targetStack.addTask(targetActivity.getTask(), true /* toTop */,
+ if (targetStack.topTask() != targetActivity.getTaskRecord()) {
+ targetStack.addTask(targetActivity.getTaskRecord(), true /* toTop */,
"startRecentsActivity");
}
} else {
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 4dd48c46b891..1d86b4684b32 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -414,7 +414,7 @@ class RootActivityContainer extends ConfigurationContainer
// Only resume home activity if isn't finishing.
if (r != null && !r.finishing) {
r.moveFocusableActivityToTop(myReason);
- return resumeFocusedStacksTopActivities(r.getStack(), prev, null);
+ return resumeFocusedStacksTopActivities(r.getActivityStack(), prev, null);
}
return startHomeOnDisplay(mCurrentUser, myReason, displayId);
}
@@ -843,7 +843,7 @@ class RootActivityContainer extends ConfigurationContainer
mWindowManager.deferSurfaceLayout();
- final ActivityDisplay display = r.getStack().getDisplay();
+ final ActivityDisplay display = r.getActivityStack().getDisplay();
PinnedActivityStack stack = display.getPinnedStack();
// This will clear the pinned stack by moving an existing task to the full screen stack,
@@ -860,7 +860,7 @@ class RootActivityContainer extends ConfigurationContainer
final Rect destBounds = stack.getDefaultPictureInPictureBounds(aspectRatio);
try {
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
// Resize the pinned stack to match the current size of the task the activity we are
// going to be moving is currently contained in. We do this to have the right starting
// animation bounds for the pinned stack to the desired bounds the caller wants.
@@ -882,7 +882,7 @@ class RootActivityContainer extends ConfigurationContainer
// ensures that all the necessary work to migrate states in the old and new stacks
// is also done.
final TaskRecord newTask = task.getStack().createTaskRecord(
- mStackSupervisor.getNextTaskIdForUserLocked(r.userId), r.info,
+ mStackSupervisor.getNextTaskIdForUserLocked(r.mUserId), r.info,
r.intent, null, null, true);
r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
@@ -1538,7 +1538,7 @@ class RootActivityContainer extends ConfigurationContainer
stack = candidateTask.getStack();
}
if (stack == null && r != null) {
- stack = r.getStack();
+ stack = r.getActivityStack();
}
if (stack != null) {
display = stack.getDisplay();
@@ -1604,7 +1604,7 @@ class RootActivityContainer extends ConfigurationContainer
// If {@code r} is already in target display and its task is the same as the candidate task,
// the intention should be getting a launch stack for the reusable activity, so we can use
// the existing stack.
- if (r.getDisplayId() == displayId && r.getTask() == candidateTask) {
+ if (r.getDisplayId() == displayId && r.getTaskRecord() == candidateTask) {
return candidateTask.getStack();
}
@@ -1950,8 +1950,8 @@ class RootActivityContainer extends ConfigurationContainer
final ActivityRecord activityRecord = task.getTopActivity();
final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
- return (activityRecord != null && activityRecord.userId == userId)
- || (resultTo != null && resultTo.userId == userId);
+ return (activityRecord != null && activityRecord.mUserId == userId)
+ || (resultTo != null && resultTo.mUserId == userId);
}
void cancelInitializingActivities() {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 80d1368427a3..b98d15479cf5 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -182,7 +182,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mTopFocusedDisplayId != topFocusedDisplayId && mode == UPDATE_FOCUS_NORMAL;
if (mTopFocusedDisplayId != topFocusedDisplayId) {
mTopFocusedDisplayId = topFocusedDisplayId;
- mService.mInputManager.setFocusedDisplay(mTopFocusedDisplayId);
+ mWmService.mInputManager.setFocusedDisplay(mTopFocusedDisplayId);
if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "New topFocusedDisplayId="
+ mTopFocusedDisplayId);
}
@@ -194,10 +194,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final boolean isTopFocusedDisplay =
topFocusedDisplayChanged && dc.getDisplayId() == mTopFocusedDisplayId;
if (windowFocusChanged || isTopFocusedDisplay) {
- final Message msg = mService.mH.obtainMessage(
+ final Message msg = mWmService.mH.obtainMessage(
WindowManagerService.H.REPORT_FOCUS_CHANGE, dc);
msg.arg1 = topFocusedDisplayChanged ? 1 : 0;
- mService.mH.sendMessage(msg);
+ mWmService.mH.sendMessage(msg);
}
});
@@ -211,7 +211,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
@Override
void onChildPositionChanged() {
- mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
+ mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateInputWindows */);
}
DisplayContent getDisplayContent(int displayId) {
@@ -238,20 +238,20 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
return existing;
}
- final DisplayContent dc = new DisplayContent(display, mService, controller);
+ final DisplayContent dc = new DisplayContent(display, mWmService, controller);
if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
- mService.mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
+ mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
initializeDisplayOverrideConfiguration(controller, dc);
- if (mService.mDisplayManagerInternal != null) {
- mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
+ if (mWmService.mDisplayManagerInternal != null) {
+ mWmService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
displayId, dc.getDisplayInfo());
dc.configureDisplayPolicy();
}
- mService.reconfigureDisplayLocked(dc);
+ mWmService.reconfigureDisplayLocked(dc);
return dc;
}
@@ -436,11 +436,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
void removeReplacedWindows() {
if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION removeReplacedWindows");
- mService.openSurfaceTransaction();
+ mWmService.openSurfaceTransaction();
try {
forAllWindows(sRemoveReplacedWindowsConsumer, true /* traverseTopToBottom */);
} finally {
- mService.closeSurfaceTransaction("removeReplacedWindows");
+ mWmService.closeSurfaceTransaction("removeReplacedWindows");
if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION removeReplacedWindows");
}
}
@@ -488,7 +488,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final SparseIntArray pidCandidates = new SparseIntArray();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
mChildren.get(displayNdx).forAllWindows((w) -> {
- if (mService.mForceRemoves.contains(w)) {
+ if (mWmService.mForceRemoves.contains(w)) {
return;
}
final WindowStateAnimator wsa = w.mWinAnimator;
@@ -503,7 +503,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
pids[i] = pidCandidates.keyAt(i);
}
try {
- if (mService.mActivityManager.killPids(pids, "Free memory", secure)) {
+ if (mWmService.mActivityManager.killPids(pids, "Free memory", secure)) {
killedApps = true;
}
} catch (RemoteException e) {
@@ -547,9 +547,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
int i;
boolean updateInputWindowsNeeded = false;
- if (mService.mFocusMayChange) {
- mService.mFocusMayChange = false;
- updateInputWindowsNeeded = mService.updateFocusedWindowLocked(
+ if (mWmService.mFocusMayChange) {
+ mWmService.mFocusMayChange = false;
+ updateInputWindowsNeeded = mWmService.updateFocusedWindowLocked(
UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
}
@@ -565,31 +565,31 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mUserActivityTimeout = -1;
mObscureApplicationContentOnSecondaryDisplays = false;
mSustainedPerformanceModeCurrent = false;
- mService.mTransactionSequence++;
+ mWmService.mTransactionSequence++;
// TODO(multi-display): recents animation & wallpaper need support multi-display.
- final DisplayContent defaultDisplay = mService.getDefaultDisplayContentLocked();
- final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
+ final DisplayContent defaultDisplay = mWmService.getDefaultDisplayContentLocked();
+ final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
- mService.openSurfaceTransaction();
+ mWmService.openSurfaceTransaction();
try {
applySurfaceChangesTransaction(recoveringMemory);
} catch (RuntimeException e) {
Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
} finally {
- mService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
+ mWmService.closeSurfaceTransaction("performLayoutAndPlaceSurfaces");
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
"<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
}
- mService.mAnimator.executeAfterPrepareSurfacesRunnables();
+ mWmService.mAnimator.executeAfterPrepareSurfacesRunnables();
checkAppTransitionReady(surfacePlacer);
// Defer starting the recents animation until the wallpaper has drawn
final RecentsAnimationController recentsAnimationController =
- mService.getRecentsAnimationController();
+ mWmService.getRecentsAnimationController();
if (recentsAnimationController != null) {
recentsAnimationController.checkAnimationReady(defaultDisplay.mWallpaperController);
}
@@ -606,9 +606,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
- if (mService.mFocusMayChange) {
- mService.mFocusMayChange = false;
- if (mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+ if (mWmService.mFocusMayChange) {
+ mWmService.mFocusMayChange = false;
+ if (mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
false /*updateInputWindows*/)) {
updateInputWindowsNeeded = true;
}
@@ -622,23 +622,23 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
handleResizingWindows();
- if (DEBUG_ORIENTATION && mService.mDisplayFrozen) Slog.v(TAG,
+ if (DEBUG_ORIENTATION && mWmService.mDisplayFrozen) Slog.v(TAG,
"With display frozen, orientationChangeComplete=" + mOrientationChangeComplete);
if (mOrientationChangeComplete) {
- if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
- mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
- mService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
- mService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
+ if (mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
+ mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_NONE;
+ mWmService.mLastFinishedFreezeSource = mLastWindowFreezeSource;
+ mWmService.mH.removeMessages(WINDOW_FREEZE_TIMEOUT);
}
- mService.stopFreezingDisplayLocked();
+ mWmService.stopFreezingDisplayLocked();
}
// Destroy the surface of any windows that are no longer visible.
- i = mService.mDestroySurface.size();
+ i = mWmService.mDestroySurface.size();
if (i > 0) {
do {
i--;
- WindowState win = mService.mDestroySurface.get(i);
+ WindowState win = mWmService.mDestroySurface.get(i);
win.mDestroying = false;
final DisplayContent displayContent = win.getDisplayContent();
if (displayContent.mInputMethodWindow == win) {
@@ -650,7 +650,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
win.destroySurfaceUnchecked();
win.mWinAnimator.destroyPreservedSurfaceLocked();
} while (i > 0);
- mService.mDestroySurface.clear();
+ mWmService.mDestroySurface.clear();
}
// Time to remove any exiting tokens?
@@ -671,8 +671,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
});
- mService.setHoldScreenLocked(mHoldScreen);
- if (!mService.mDisplayFrozen) {
+ mWmService.setHoldScreenLocked(mHoldScreen);
+ if (!mWmService.mDisplayFrozen) {
final int brightness = mScreenBrightness < 0 || mScreenBrightness > 1.0f
? -1 : toBrightnessOverride(mScreenBrightness);
@@ -684,7 +684,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) {
mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent;
- mService.mPowerManagerInternal.powerHint(
+ mWmService.mPowerManagerInternal.powerHint(
PowerHint.SUSTAINED_PERFORMANCE,
(mSustainedPerformanceModeEnabled ? 1 : 0));
}
@@ -694,22 +694,22 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mUpdateRotation = updateRotationUnchecked();
}
- if (mService.mWaitingForDrawnCallback != null
+ if (mWmService.mWaitingForDrawnCallback != null
|| (mOrientationChangeComplete && !isLayoutNeeded()
&& !mUpdateRotation)) {
- mService.checkDrawnWindowsLocked();
+ mWmService.checkDrawnWindowsLocked();
}
- final int N = mService.mPendingRemove.size();
+ final int N = mWmService.mPendingRemove.size();
if (N > 0) {
- if (mService.mPendingRemoveTmp.length < N) {
- mService.mPendingRemoveTmp = new WindowState[N + 10];
+ if (mWmService.mPendingRemoveTmp.length < N) {
+ mWmService.mPendingRemoveTmp = new WindowState[N + 10];
}
- mService.mPendingRemove.toArray(mService.mPendingRemoveTmp);
- mService.mPendingRemove.clear();
+ mWmService.mPendingRemove.toArray(mWmService.mPendingRemoveTmp);
+ mWmService.mPendingRemove.clear();
ArrayList<DisplayContent> displayList = new ArrayList();
for (i = 0; i < N; i++) {
- final WindowState w = mService.mPendingRemoveTmp[i];
+ final WindowState w = mWmService.mPendingRemoveTmp[i];
w.removeImmediately();
final DisplayContent displayContent = w.getDisplayContent();
if (displayContent != null && !displayList.contains(displayContent)) {
@@ -737,12 +737,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// Check to see if we are now in a state where the screen should
// be enabled, because the window obscured flags have changed.
- mService.enableScreenIfNeededLocked();
+ mWmService.enableScreenIfNeededLocked();
- mService.scheduleAnimationLocked();
+ mWmService.scheduleAnimationLocked();
if (DEBUG_WINDOW_TRACE) Slog.e(TAG,
- "performSurfacePlacementInner exit: animating=" + mService.mAnimator.isAnimating());
+ "performSurfacePlacementInner exit: animating="
+ + mWmService.mAnimator.isAnimating());
}
private void checkAppTransitionReady(WindowSurfacePlacer surfacePlacer) {
@@ -782,23 +783,23 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mObscuringWindow = null;
// TODO(multi-display): Support these features on secondary screens.
- final DisplayContent defaultDc = mService.getDefaultDisplayContentLocked();
+ final DisplayContent defaultDc = mWmService.getDefaultDisplayContentLocked();
final DisplayInfo defaultInfo = defaultDc.getDisplayInfo();
final int defaultDw = defaultInfo.logicalWidth;
final int defaultDh = defaultInfo.logicalHeight;
- if (mService.mWatermark != null) {
- mService.mWatermark.positionSurface(defaultDw, defaultDh);
+ if (mWmService.mWatermark != null) {
+ mWmService.mWatermark.positionSurface(defaultDw, defaultDh);
}
- if (mService.mStrictModeFlash != null) {
- mService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
+ if (mWmService.mStrictModeFlash != null) {
+ mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh);
}
- if (mService.mCircularDisplayMask != null) {
- mService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
- mService.getDefaultDisplayRotation());
+ if (mWmService.mCircularDisplayMask != null) {
+ mWmService.mCircularDisplayMask.positionSurface(defaultDw, defaultDh,
+ mWmService.getDefaultDisplayRotation());
}
- if (mService.mEmulatorDisplayOverlay != null) {
- mService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
- mService.getDefaultDisplayRotation());
+ if (mWmService.mEmulatorDisplayOverlay != null) {
+ mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh,
+ mWmService.getDefaultDisplayRotation());
}
final int count = mChildren.size();
@@ -809,7 +810,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// Give the display manager a chance to adjust properties like display rotation if it needs
// to.
- mService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
+ mWmService.mDisplayManagerInternal.performTraversal(mDisplayTransaction);
SurfaceControl.mergeToGlobalTransaction(mDisplayTransaction);
}
@@ -817,14 +818,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
* Handles resizing windows during surface placement.
*/
private void handleResizingWindows() {
- for (int i = mService.mResizingWindows.size() - 1; i >= 0; i--) {
- WindowState win = mService.mResizingWindows.get(i);
+ for (int i = mWmService.mResizingWindows.size() - 1; i >= 0; i--) {
+ WindowState win = mWmService.mResizingWindows.get(i);
if (win.mAppFreezing) {
// Don't remove this window until rotation has completed.
continue;
}
win.reportResized();
- mService.mResizingWindows.remove(i);
+ mWmService.mResizingWindows.remove(i);
}
}
@@ -862,7 +863,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
mHoldScreen = w.mSession;
mHoldScreenWindow = w;
- } else if (DEBUG_KEEP_SCREEN_ON && w == mService.mLastWakeLockHoldingWindow) {
+ } else if (DEBUG_KEEP_SCREEN_ON && w == mWmService.mLastWakeLockHoldingWindow) {
Slog.d(TAG_KEEP_SCREEN_ON, "handleNotObscuredLocked: " + w + " was holding "
+ "screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by"
+ Debug.getCallers(10));
@@ -911,7 +912,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
boolean copyAnimToLayoutParams() {
boolean doRequest = false;
- final int bulkUpdateParams = mService.mAnimator.mBulkUpdateParams;
+ final int bulkUpdateParams = mWmService.mAnimator.mBulkUpdateParams;
if ((bulkUpdateParams & SET_UPDATE_ROTATION) != 0) {
mUpdateRotation = true;
doRequest = true;
@@ -920,8 +921,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mOrientationChangeComplete = false;
} else {
mOrientationChangeComplete = true;
- mLastWindowFreezeSource = mService.mAnimator.mLastWindowFreezeSource;
- if (mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
+ mLastWindowFreezeSource = mWmService.mAnimator.mLastWindowFreezeSource;
+ if (mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_NONE) {
doRequest = true;
}
}
@@ -947,12 +948,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
public void handleMessage(Message msg) {
switch (msg.what) {
case SET_SCREEN_BRIGHTNESS_OVERRIDE:
- mService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
+ mWmService.mPowerManagerInternal.setScreenBrightnessOverrideFromWindowManager(
msg.arg1);
break;
case SET_USER_ACTIVITY_TIMEOUT:
- mService.mPowerManagerInternal.setUserActivityTimeoutOverrideFromWindowManager(
- (Long) msg.obj);
+ mWmService.mPowerManagerInternal.
+ setUserActivityTimeoutOverrideFromWindowManager((Long) msg.obj);
break;
default:
break;
@@ -962,7 +963,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
void dumpDisplayContents(PrintWriter pw) {
pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)");
- if (mService.mDisplayReady) {
+ if (mWmService.mDisplayReady) {
final int count = mChildren.size();
for (int i = 0; i < count; ++i) {
final DisplayContent displayContent = mChildren.get(i);
@@ -1015,7 +1016,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
final long token = proto.start(fieldId);
super.writeToProto(proto, WINDOW_CONTAINER, trim);
- if (mService.mDisplayReady) {
+ if (mWmService.mDisplayReady) {
final int count = mChildren.size();
for (int i = 0; i < count; ++i) {
final DisplayContent displayContent = mChildren.get(i);
@@ -1050,7 +1051,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
@Override
void scheduleAnimation() {
- mService.scheduleAnimationLocked();
+ mWmService.scheduleAnimationLocked();
}
/**
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index ee0e89b24769..3947bd47b588 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -222,7 +222,7 @@ class ScreenRotationAnimation {
}
public ScreenRotationAnimation(Context context, DisplayContent displayContent,
- boolean forceDefaultOrientation, boolean isSecure, WindowManagerService service) {
+ boolean fixedToUserRotation, boolean isSecure, WindowManagerService service) {
mService = service;
mContext = context;
mDisplayContent = displayContent;
@@ -234,7 +234,7 @@ class ScreenRotationAnimation {
final int originalWidth;
final int originalHeight;
DisplayInfo displayInfo = displayContent.getDisplayInfo();
- if (forceDefaultOrientation) {
+ if (fixedToUserRotation) {
// Emulated orientation.
mForceDefaultOrientation = true;
originalWidth = displayContent.mBaseDisplayWidth;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 6904ef58dc24..d3db5dfa5e0f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -332,7 +332,7 @@ class Task extends WindowContainer<AppWindowToken> {
boolean isResizeable() {
return ActivityInfo.isResizeableMode(mResizeMode) || mSupportsPictureInPicture
- || mService.mForceResizableTasks;
+ || mWmService.mForceResizableTasks;
}
/**
@@ -581,7 +581,7 @@ class Task extends WindowContainer<AppWindowToken> {
}
boolean isTaskAnimating() {
- final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController();
+ final RecentsAnimationController recentsAnim = mWmService.getRecentsAnimationController();
if (recentsAnim != null) {
if (recentsAnim.isAnimatingTask(this)) {
return true;
@@ -628,13 +628,13 @@ class Task extends WindowContainer<AppWindowToken> {
}
void forceWindowsScaleable(boolean force) {
- mService.openSurfaceTransaction();
+ mWmService.openSurfaceTransaction();
try {
for (int i = mChildren.size() - 1; i >= 0; i--) {
mChildren.get(i).forceWindowsScaleableInTransaction(force);
}
} finally {
- mService.closeSurfaceTransaction("forceWindowsScaleable");
+ mWmService.closeSurfaceTransaction("forceWindowsScaleable");
}
}
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 3b3feacc5cda..bb3df02146d7 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -283,8 +283,8 @@ class TaskChangeNotificationController {
void notifyActivityPinned(ActivityRecord r) {
mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG);
final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG,
- r.getTask().taskId, r.getStackId(), r.packageName);
- msg.sendingUid = r.userId;
+ r.getTaskRecord().taskId, r.getStackId(), r.packageName);
+ msg.sendingUid = r.mUserId;
forAllLocalListeners(mNotifyActivityPinned, msg);
msg.sendToTarget();
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 8a3dbada8d3f..30751bcebe07 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -903,7 +903,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont
// Correct the activity intent for aliasing. The task record intent will always be based on
// the real activity that will be launched not the alias, so we need to use an intent with
// the component name pointing to the real activity not the alias in the activity record.
- intent.setComponent(r.realActivity);
+ intent.setComponent(r.mActivityComponent);
return intent.filterEquals(this.intent);
}
@@ -1211,7 +1211,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont
* be in the current task or unparented to any task.
*/
void addActivityAtIndex(int index, ActivityRecord r) {
- TaskRecord task = r.getTask();
+ TaskRecord task = r.getTaskRecord();
if (task != null && task != this) {
throw new IllegalArgumentException("Can not add r=" + " to task=" + this
+ " current parent=" + task);
@@ -1285,7 +1285,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont
}
boolean removeActivity(ActivityRecord r, boolean reparenting) {
- if (r.getTask() != this) {
+ if (r.getTaskRecord() != this) {
throw new IllegalArgumentException(
"Activity=" + r + " does not belong to task=" + this);
}
@@ -1401,7 +1401,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont
if (r.finishing) {
continue;
}
- if (r.realActivity.equals(newR.realActivity)) {
+ if (r.mActivityComponent.equals(newR.mActivityComponent)) {
// Here it is! Now finish everything in front...
final ActivityRecord ret = r;
@@ -1559,13 +1559,13 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont
* the index within the history at which it's found, or < 0 if not found.
*/
final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
- final ComponentName realActivity = r.realActivity;
+ final ComponentName realActivity = r.mActivityComponent;
for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord candidate = mActivities.get(activityNdx);
if (candidate.finishing) {
continue;
}
- if (candidate.realActivity.equals(realActivity)) {
+ if (candidate.mActivityComponent.equals(realActivity)) {
return candidate;
}
}
@@ -1990,7 +1990,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont
? reuseActivitiesReport.base.intent.getComponent()
: null;
info.topActivity = reuseActivitiesReport.top != null
- ? reuseActivitiesReport.top.realActivity
+ ? reuseActivitiesReport.top.mActivityComponent
: null;
info.origActivity = origActivity;
info.realActivity = realActivity;
@@ -2041,7 +2041,7 @@ public class TaskRecord extends ConfigurationContainer implements TaskWindowCont
pw.println(origActivity.flattenToShortString());
}
if (realActivity != null) {
- pw.print(prefix); pw.print("realActivity=");
+ pw.print(prefix); pw.print("mActivityComponent=");
pw.println(realActivity.flattenToShortString());
}
if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() || numFullscreen != 0) {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 5deb4f1ab7d4..b1f95f894490 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -450,7 +450,7 @@ public class TaskStack extends WindowContainer<Task> implements
final int newDockSide = getDockSide(parentConfig, inOutBounds);
// Update the dock create mode and clear the dock create bounds, these
// might change after a rotation and the original values will be invalid.
- mService.setDockedStackCreateStateLocked(
+ mWmService.setDockedStackCreateStateLocked(
(newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
: SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
@@ -523,7 +523,7 @@ public class TaskStack extends WindowContainer<Task> implements
mDisplayContent.getDisplayPolicy().getStableInsetsLw(rotation, displayWidth, displayHeight,
displayCutout, outBounds);
final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
- mService.mContext.getResources(), displayWidth, displayHeight,
+ mWmService.mContext.getResources(), displayWidth, displayHeight,
dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
getDockSide(), isMinimizedDockAndHomeStackResizable());
final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
@@ -594,7 +594,7 @@ public class TaskStack extends WindowContainer<Task> implements
private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers,
boolean addingNew) {
final boolean canShowTask =
- showForAllUsers || mService.isCurrentProfileLocked(task.mUserId);
+ showForAllUsers || mWmService.isCurrentProfileLocked(task.mUserId);
final int stackSize = mChildren.size();
int minPosition = 0;
@@ -628,7 +628,7 @@ public class TaskStack extends WindowContainer<Task> implements
final Task tmpTask = mChildren.get(minPosition);
final boolean canShowTmpTask =
tmpTask.showForAllUsers()
- || mService.isCurrentProfileLocked(tmpTask.mUserId);
+ || mWmService.isCurrentProfileLocked(tmpTask.mUserId);
if (canShowTmpTask) {
break;
}
@@ -647,7 +647,7 @@ public class TaskStack extends WindowContainer<Task> implements
final Task tmpTask = mChildren.get(maxPosition);
final boolean canShowTmpTask =
tmpTask.showForAllUsers()
- || mService.isCurrentProfileLocked(tmpTask.mUserId);
+ || mWmService.isCurrentProfileLocked(tmpTask.mUserId);
if (!canShowTmpTask) {
break;
}
@@ -728,7 +728,7 @@ public class TaskStack extends WindowContainer<Task> implements
// We multiply by two to match the client logic for converting view elevation
// to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
- return (int)Math.ceil(mService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP,
+ return (int)Math.ceil(mWmService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP,
displayMetrics) * 2);
}
return 0;
@@ -791,7 +791,7 @@ public class TaskStack extends WindowContainer<Task> implements
if (dockedBounds == null || dockedBounds.isEmpty()) {
// Calculate the primary docked bounds.
- final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
+ final boolean dockedOnTopOrLeft = mWmService.mDockedStackCreateMode
== SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
getStackDockedModeBounds(parentConfig,
true /* primary */, outStackBounds, dockedBounds,
@@ -856,8 +856,8 @@ public class TaskStack extends WindowContainer<Task> implements
outBounds.set(displayRect);
if (primary) {
- if (mService.mDockedStackCreateBounds != null) {
- outBounds.set(mService.mDockedStackCreateBounds);
+ if (mWmService.mDockedStackCreateBounds != null) {
+ outBounds.set(mWmService.mDockedStackCreateBounds);
return;
}
@@ -868,7 +868,7 @@ public class TaskStack extends WindowContainer<Task> implements
mDisplayContent.getDisplayPolicy().getStableInsetsLw(
parentConfig.windowConfiguration.getRotation(),
displayRect.width(), displayRect.height(), displayCutout, mTmpRect2);
- final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
+ final int position = new DividerSnapAlgorithm(mWmService.mContext.getResources(),
displayRect.width(),
displayRect.height(),
dockDividerWidth,
@@ -913,7 +913,7 @@ public class TaskStack extends WindowContainer<Task> implements
throw new IllegalStateException("Not a docked stack=" + this);
}
- mService.mDockedStackCreateBounds = null;
+ mWmService.mDockedStackCreateBounds = null;
final Rect bounds = new Rect();
final Rect tempBounds = new Rect();
@@ -955,7 +955,7 @@ public class TaskStack extends WindowContainer<Task> implements
}
mDisplayContent = null;
- mService.mWindowPlacerLocked.requestTraversal();
+ mWmService.mWindowPlacerLocked.requestTraversal();
}
void resetAnimationBackgroundAnimator() {
@@ -977,7 +977,7 @@ public class TaskStack extends WindowContainer<Task> implements
int top = mChildren.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Task task = mChildren.get(taskNdx);
- if (mService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
+ if (mWmService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
mChildren.remove(taskNdx);
mChildren.add(task);
--top;
@@ -1046,7 +1046,7 @@ public class TaskStack extends WindowContainer<Task> implements
}
mAdjustedForIme = false;
updateAdjustedBounds();
- mService.setResizeDimLayer(false, getWindowingMode(), 1.0f);
+ mWmService.setResizeDimLayer(false, getWindowingMode(), 1.0f);
} else {
mImeGoingAway |= mAdjustedForIme;
}
@@ -1179,7 +1179,7 @@ public class TaskStack extends WindowContainer<Task> implements
}
if (dockSide == DOCKED_TOP) {
- mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
+ mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
int topInset = mTmpRect.top;
mTmpAdjustedBounds.set(getRawBounds());
mTmpAdjustedBounds.bottom = (int) (minimizeAmount * topInset + (1 - minimizeAmount)
@@ -1215,7 +1215,7 @@ public class TaskStack extends WindowContainer<Task> implements
}
if (dockSide == DOCKED_TOP) {
- mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
+ mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
int topInset = mTmpRect.top;
return getRawBounds().bottom - topInset;
} else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
@@ -1240,11 +1240,11 @@ public class TaskStack extends WindowContainer<Task> implements
}
setAdjustedBounds(mTmpAdjustedBounds);
- final boolean isImeTarget = (mService.getImeFocusStackLocked() == this);
+ final boolean isImeTarget = (mWmService.getImeFocusStackLocked() == this);
if (mAdjustedForIme && adjust && !isImeTarget) {
final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
* IME_ADJUST_DIM_AMOUNT;
- mService.setResizeDimLayer(true, getWindowingMode(), alpha);
+ mWmService.setResizeDimLayer(true, getWindowingMode(), alpha);
}
}
@@ -1510,14 +1510,14 @@ public class TaskStack extends WindowContainer<Task> implements
public boolean setPinnedStackSize(Rect stackBounds, Rect tempTaskBounds) {
// Hold the lock since this is called from the BoundsAnimator running on the UiThread
- synchronized (mService.mGlobalLock) {
+ synchronized (mWmService.mGlobalLock) {
if (mCancelCurrentBoundsAnimation) {
return false;
}
}
try {
- mService.mActivityTaskManager.resizePinnedStack(stackBounds, tempTaskBounds);
+ mWmService.mActivityTaskManager.resizePinnedStack(stackBounds, tempTaskBounds);
} catch (RemoteException e) {
// I don't believe you.
}
@@ -1535,7 +1535,7 @@ public class TaskStack extends WindowContainer<Task> implements
@Override // AnimatesBounds
public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
// Hold the lock since this is called from the BoundsAnimator running on the UiThread
- synchronized (mService.mGlobalLock) {
+ synchronized (mWmService.mGlobalLock) {
if (!isAttached()) {
// Don't run the animation if the stack is already detached
return false;
@@ -1555,7 +1555,7 @@ public class TaskStack extends WindowContainer<Task> implements
if (inPinnedWindowingMode()) {
try {
- mService.mActivityTaskManager.notifyPinnedStackAnimationStarted();
+ mWmService.mActivityTaskManager.notifyPinnedStackAnimationStarted();
} catch (RemoteException e) {
// I don't believe you...
}
@@ -1598,9 +1598,9 @@ public class TaskStack extends WindowContainer<Task> implements
}
try {
- mService.mActivityTaskManager.notifyPinnedStackAnimationEnded();
+ mWmService.mActivityTaskManager.notifyPinnedStackAnimationEnded();
if (moveToFullscreen) {
- mService.mActivityTaskManager.moveTasksToFullscreenStack(mStackId,
+ mWmService.mActivityTaskManager.moveTasksToFullscreenStack(mStackId,
true /* onTop */);
}
} catch (RemoteException e) {
@@ -1614,7 +1614,7 @@ public class TaskStack extends WindowContainer<Task> implements
@Override
public boolean isAttached() {
- synchronized (mService.mGlobalLock) {
+ synchronized (mWmService.mGlobalLock) {
return mDisplayContent != null;
}
}
@@ -1623,19 +1623,19 @@ public class TaskStack extends WindowContainer<Task> implements
* Called immediately prior to resizing the tasks at the end of the pinned stack animation.
*/
public void onPipAnimationEndResize() {
- synchronized (mService.mGlobalLock) {
+ synchronized (mWmService.mGlobalLock) {
mBoundsAnimating = false;
for (int i = 0; i < mChildren.size(); i++) {
final Task t = mChildren.get(i);
t.clearPreserveNonFloatingState();
}
- mService.requestTraversal();
+ mWmService.requestTraversal();
}
}
@Override
public boolean shouldDeferStartOnMoveToFullscreen() {
- synchronized (mService.mGlobalLock) {
+ synchronized (mWmService.mGlobalLock) {
if (!isAttached()) {
// Unnecessary to pause the animation because the stack is detached.
return false;
diff --git a/services/core/java/com/android/server/wm/VrController.java b/services/core/java/com/android/server/wm/VrController.java
index abe40a731a43..3e136d355f9d 100644
--- a/services/core/java/com/android/server/wm/VrController.java
+++ b/services/core/java/com/android/server/wm/VrController.java
@@ -187,7 +187,7 @@ final class VrController {
synchronized (mGlobalAmLock) {
vrMode = record.requestedVrComponent != null;
requestedPackage = record.requestedVrComponent;
- userId = record.userId;
+ userId = record.mUserId;
callingPackage = record.info.getComponentName();
// Tell the VrController that a VR mode change is requested.
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 7e4c62935e05..1275ca057e65 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -115,7 +115,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
*/
protected final Transaction mPendingTransaction;
protected final SurfaceAnimator mSurfaceAnimator;
- protected final WindowManagerService mService;
+ protected final WindowManagerService mWmService;
private final Point mTmpPos = new Point();
protected final Point mLastSurfacePosition = new Point();
@@ -129,10 +129,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
*/
private boolean mCommittedReparentToAnimationLeash;
- WindowContainer(WindowManagerService service) {
- mService = service;
- mPendingTransaction = service.mTransactionFactory.make();
- mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, service);
+ WindowContainer(WindowManagerService wms) {
+ mWmService = wms;
+ mPendingTransaction = wms.mTransactionFactory.make();
+ mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b91afcd18e45..52b24b3e7307 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -66,6 +66,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
import static com.android.server.LockGuard.INDEX_WINDOW;
@@ -208,6 +209,7 @@ import android.view.IWindowSessionCallback;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEventReceiver;
+import android.view.InsetsState;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
@@ -218,7 +220,6 @@ import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
import android.view.WindowContentFrameStats;
-import android.view.InsetsState;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.RemoveContentMode;
@@ -3591,6 +3592,17 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ void setRotateForApp(int displayId, boolean enabled) {
+ synchronized (mGlobalLock) {
+ final DisplayContent display = mRoot.getDisplayContent(displayId);
+ if (display == null) {
+ Slog.w(TAG, "Trying to set rotate for app for a missing display.");
+ return;
+ }
+ display.getDisplayRotation().setFixedToUserRotation(enabled);
+ }
+ }
+
@Override
public void freezeRotation(int rotation) {
freezeDisplayRotation(Display.DEFAULT_DISPLAY, rotation);
@@ -5397,7 +5409,7 @@ public class WindowManagerService extends IWindowManager.Stub
displayContent.updateDisplayInfo();
screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
- displayContent.getDisplayRotation().isDefaultOrientationForced(), isSecure,
+ displayContent.getDisplayRotation().isFixedToUserRotation(), isSecure,
this);
mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
screenRotationAnimation);
@@ -5629,22 +5641,12 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- // TODO: Make the callers use getNavBarPosition(int) only.
- /**
- * Used by SystemUI and shared SystemUI libraries.
- * @see DisplayPolicy#getNavBarPosition()
- */
- @Override
- @WindowManagerPolicy.NavigationBarPosition
- public int getNavBarPosition() {
- return getNavBarPosition(Display.DEFAULT_DISPLAY);
- }
-
/**
* Used by ActivityManager to determine where to position an app with aspect ratio shorter then
* the screen is.
* @see DisplayPolicy#getNavBarPosition()
*/
+ @Override
@WindowManagerPolicy.NavigationBarPosition
public int getNavBarPosition(int displayId) {
synchronized (mGlobalLock) {
@@ -5654,7 +5656,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (displayContent == null) {
Slog.w(TAG, "getNavBarPosition with invalid displayId=" + displayId
+ " callers=" + Debug.getCallers(3));
- return -1;
+ return NAV_BAR_INVALID;
}
displayContent.performLayout(false /* initial */,
false /* updateInputWindows */);
@@ -7446,4 +7448,29 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
+
+ @Override
+ public void reparentDisplayContent(int displayId, IBinder surfaceControlHandle) {
+ final Display display = mDisplayManager.getDisplay(displayId);
+ if (display == null) {
+ throw new IllegalArgumentException(
+ "Can't reparent display for non-existent displayId: " + displayId);
+ }
+
+ final int callingUid = Binder.getCallingUid();
+ final int displayOwnerUid = display.getOwnerUid();
+ if (callingUid != displayOwnerUid) {
+ throw new SecurityException("Only owner of the display can reparent surfaces to it.");
+ }
+
+ synchronized (mGlobalLock) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+ displayContent.reparentDisplayContent(surfaceControlHandle);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index bf77ba86075d..6865ce305442 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -76,6 +76,8 @@ public class WindowManagerShellCommand extends ShellCommand {
getNextArgRequired());
case "set-user-rotation":
return runSetDisplayUserRotation(pw);
+ case "set-fix-to-user-rotation":
+ return runSetFixToUserRotation(pw);
default:
return handleDefaultCommands(cmd);
}
@@ -297,6 +299,32 @@ public class WindowManagerShellCommand extends ShellCommand {
}
}
+ private int runSetFixToUserRotation(PrintWriter pw) {
+ int displayId = Display.DEFAULT_DISPLAY;
+ String arg = getNextArgRequired();
+ if ("-d".equals(arg)) {
+ displayId = Integer.parseInt(getNextArgRequired());
+ arg = getNextArgRequired();
+ }
+
+ final boolean enabled;
+ switch (arg) {
+ case "enabled":
+ enabled = true;
+ break;
+ case "disabled":
+ enabled = false;
+ break;
+ default:
+ getErrPrintWriter().println("Error: expecting enabled or disabled, but we get "
+ + arg);
+ return -1;
+ }
+
+ mInternal.setRotateForApp(displayId, enabled);
+ return 0;
+ }
+
@Override
public void onHelp() {
PrintWriter pw = getOutPrintWriter();
@@ -316,6 +344,8 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
pw.println(" set-user-rotation [free|lock] [-d DISPLAY_ID] [rotation]");
pw.println(" Set user rotation mode and user rotation.");
+ pw.println(" set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled]");
+ pw.println(" Enable or disable rotating display for app requested orientation.");
if (!IS_USER) {
pw.println(" tracing (start | stop)");
pw.println(" Start or stop window tracing.");
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 578af2eebe88..2dec4dd13cbe 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -443,7 +443,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
for (int i = 0; i < activities.size(); i++) {
final ActivityRecord r = activities.get(i);
if (!r.finishing && r.isInStackLocked()) {
- r.getStack().finishActivityLocked(r, Activity.RESULT_CANCELED,
+ r.getActivityStack().finishActivityLocked(r, Activity.RESULT_CANCELED,
null, "finish-heavy", true);
}
}
@@ -513,7 +513,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
ActivityRecord hist = mActivities.get(0);
intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName);
- intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTask().taskId);
+ intent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.getTaskRecord().taskId);
}
}
@@ -524,7 +524,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
// Don't kill process(es) that has an activity not stopped.
return false;
}
- final TaskRecord otherTask = activity.getTask();
+ final TaskRecord otherTask = activity.getTaskRecord();
if (tr.taskId != otherTask.taskId && otherTask.inRecents) {
// Don't kill process(es) that has an activity in a different task that is
// also in recents.
@@ -557,7 +557,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
continue;
}
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
if (task != null) {
if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Collecting release task " + task
+ " from " + r);
@@ -600,7 +600,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
if (r.visible) {
callback.onVisibleActivity();
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
if (task != null && minTaskLayer > 0) {
final int layer = task.mLayerRank;
if (layer >= 0 && minTaskLayer > layer) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index cfd1f86cdeaa..cdf911881395 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -195,7 +195,6 @@ import android.view.animation.Interpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.policy.WindowManagerPolicy.DisplayContentInfo;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
import com.android.server.wm.utils.InsetUtils;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -598,7 +597,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (mForceSeamlesslyRotate || requested) {
mPendingSeamlessRotate = new SeamlessRotator(oldRotation, rotation, getDisplayInfo());
mPendingSeamlessRotate.unrotate(transaction, this);
- mService.markForSeamlessRotation(this, true);
+ mWmService.markForSeamlessRotation(this, true);
}
}
@@ -607,7 +606,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mPendingSeamlessRotate.finish(this, timeout);
mFinishSeamlessRotateFrameNumber = getFrameNumber();
mPendingSeamlessRotate = null;
- mService.markForSeamlessRotation(this, false);
+ mWmService.markForSeamlessRotation(this, false);
}
}
@@ -651,8 +650,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mAttrs.copyFrom(a);
mLastSurfaceInsets.set(mAttrs.surfaceInsets);
mViewVisibility = viewVisibility;
- mPolicy = mService.mPolicy;
- mContext = mService.mContext;
+ mPolicy = mWmService.mPolicy;
+ mContext = mWmService.mContext;
DeathRecipient deathRecipient = new DeathRecipient();
mSeq = seq;
mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
@@ -846,7 +845,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mWindowFrames.mContainingFrame.bottom =
mWindowFrames.mContainingFrame.top + frozen.height();
}
- final WindowState imeWin = mService.mRoot.getCurrentInputMethodWindow();
+ final WindowState imeWin = mWmService.mRoot.getCurrentInputMethodWindow();
// IME is up and obscuring this window. Adjust the window position so it is visible.
if (imeWin != null && imeWin.isVisibleNow() && isInputMethodTarget()) {
if (inFreeformWindowingMode() && mWindowFrames.mContainingFrame.bottom
@@ -1204,7 +1203,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
updateLastInsetValues();
- mService.makeWindowFreezingScreenIfNeededLocked(this);
+ mWmService.makeWindowFreezingScreenIfNeededLocked(this);
// If the orientation is changing, or we're starting or ending a drag resizing action,
// then we need to hold off on unfreezing the display until this window has been
@@ -1221,9 +1220,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mAppToken.clearAllDrawn();
}
}
- if (!mService.mResizingWindows.contains(this)) {
+ if (!mWmService.mResizingWindows.contains(this)) {
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG_WM, "Resizing window " + this);
- mService.mResizingWindows.add(this);
+ mWmService.mResizingWindows.add(this);
}
} else if (getOrientationChanging()) {
if (isDrawnLw()) {
@@ -1231,7 +1230,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
+ this + ", surfaceController " + winAnimator.mSurfaceController);
setOrientationChanging(false);
mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- - mService.mDisplayFreezeTime);
+ - mWmService.mDisplayFreezeTime);
}
}
}
@@ -1604,7 +1603,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// 3. WS is currently visible
if (!runningAppAnimation && isVisibleNow) {
final AccessibilityController accessibilityController =
- mService.mAccessibilityController;
+ mWmService.mAccessibilityController;
final int winTransit = TRANSIT_EXIT;
mWinAnimator.applyAnimationLocked(winTransit, false /* isEntrance */);
//TODO (multidisplay): Magnification is supported only for the default
@@ -1626,8 +1625,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (isVisibleNow()) {
mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
//TODO (multidisplay): Magnification is supported only for the default
- if (mService.mAccessibilityController != null && isDefaultDisplay()) {
- mService.mAccessibilityController.onWindowTransitionLocked(this, TRANSIT_EXIT);
+ if (mWmService.mAccessibilityController != null && isDefaultDisplay()) {
+ mWmService.mAccessibilityController.onWindowTransitionLocked(this, TRANSIT_EXIT);
}
changed = true;
if (displayContent != null) {
@@ -1645,7 +1644,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
@Override
void onResize() {
- final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
+ final ArrayList<WindowState> resizingWindows = mWmService.mResizingWindows;
if (mHasSurface && !isGoneForLayoutLw() && !resizingWindows.contains(this)) {
if (DEBUG_RESIZE) Slog.d(TAG, "onResize: Resizing " + this);
resizingWindows.add(this);
@@ -1669,8 +1668,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mLayoutNeeded = true;
setDisplayLayoutNeeded();
- if (!mService.mResizingWindows.contains(this)) {
- mService.mResizingWindows.add(this);
+ if (!mWmService.mResizingWindows.contains(this)) {
+ mWmService.mResizingWindows.add(this);
}
}
@@ -1702,9 +1701,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
//TODO (multidisplay): Accessibility supported only for the default display.
- if (mService.mAccessibilityController != null
+ if (mWmService.mAccessibilityController != null
&& getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {
- mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
+ mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
try {
@@ -1818,7 +1817,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// we are doing this as part of processing a death note.)
}
- mService.postWindowRemoveCleanupLocked(this);
+ mWmService.postWindowRemoveCleanupLocked(this);
}
@Override
@@ -1859,7 +1858,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
+ " mWillReplaceWindow=" + mWillReplaceWindow
+ " inPendingTransaction="
+ (mAppToken != null ? mAppToken.inPendingTransaction : false)
- + " mDisplayFrozen=" + mService.mDisplayFrozen
+ + " mDisplayFrozen=" + mWmService.mDisplayFrozen
+ " callers=" + Debug.getCallers(6));
// Visibility of the removed window. Will be used later to update orientation later on.
@@ -1894,7 +1893,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mAppDied = true;
setDisplayLayoutNeeded();
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
// Set up a replacement input channel since the app is now dead.
// We need to catch tapping on the dead window to restart the app.
@@ -1913,11 +1912,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// mAnimatingExit affects canAffectSystemUiFlags(). Run layout such that
// any change from that is performed immediately.
setDisplayLayoutNeeded();
- mService.requestTraversal();
+ mWmService.requestTraversal();
}
//TODO (multidisplay): Magnification is supported only for the default display.
- if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
- mService.mAccessibilityController.onWindowTransitionLocked(this, transit);
+ if (mWmService.mAccessibilityController != null
+ && displayId == DEFAULT_DISPLAY) {
+ mWmService.mAccessibilityController.onWindowTransitionLocked(this, transit);
}
}
final boolean isAnimating = isAnimating()
@@ -1951,7 +1951,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
displayContent.sendNewConfiguration();
}
}
- mService.updateFocusedWindowLocked(isFocused()
+ mWmService.updateFocusedWindowLocked(isFocused()
? UPDATE_FOCUS_REMOVING_FOCUS
: UPDATE_FOCUS_NORMAL,
true /*updateInputWindows*/);
@@ -1965,9 +1965,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
setDisplayLayoutNeeded();
// Request a focus update as this window's input channel is already gone. Otherwise
// we could have no focused window in input manager.
- final boolean focusChanged = mService.updateFocusedWindowLocked(
+ final boolean focusChanged = mWmService.updateFocusedWindowLocked(
UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
- mService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
if (focusChanged) {
getDisplayContent().getInputMonitor().updateInputWindowsLw(false /*force*/);
}
@@ -2020,7 +2020,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
private final class DeadWindowEventReceiver extends InputEventReceiver {
DeadWindowEventReceiver(InputChannel inputChannel) {
- super(inputChannel, mService.mH.getLooper());
+ super(inputChannel, mWmService.mH.getLooper());
}
@Override
public void onInputEvent(InputEvent event) {
@@ -2051,7 +2051,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// Create dummy event receiver that simply reports all events as handled.
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
}
- mService.mInputManager.registerInputChannel(mInputChannel, mClient.asBinder());
+ mWmService.mInputManager.registerInputChannel(mInputChannel, mClient.asBinder());
}
void disposeInputChannel() {
@@ -2062,7 +2062,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// unregister server channel first otherwise it complains about broken channel
if (mInputChannel != null) {
- mService.mInputManager.unregisterInputChannel(mInputChannel);
+ mWmService.mInputManager.unregisterInputChannel(mInputChannel);
mInputChannel.dispose();
mInputChannel = null;
@@ -2194,13 +2194,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (isFocused()) {
if (DEBUG_FOCUS_LIGHT) Slog.i(TAG,
"setAnimationLocked: setting mFocusMayChange true");
- mService.mFocusMayChange = true;
+ mWmService.mFocusMayChange = true;
}
setDisplayLayoutNeeded();
// Window is no longer visible -- make sure if we were waiting
// for it to be displayed before enabling the display, that
// we allow the display to be enabled now.
- mService.enableScreenIfNeededLocked();
+ mWmService.enableScreenIfNeededLocked();
}
}
}
@@ -2217,8 +2217,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// We need to turn on screen regardless of visibility.
boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0;
boolean allowTheaterMode =
- mService.mAllowTheaterModeWakeFromLayout || Settings.Global.getInt(
- mService.mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0)
+ mWmService.mAllowTheaterModeWakeFromLayout || Settings.Global.getInt(
+ mWmService.mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0)
== 0;
boolean canTurnScreenOn = mAppToken == null || mAppToken.canTurnScreenOn();
@@ -2268,8 +2268,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// For child windows we want to use the pid for the parent window in case the the child
// window was added from another process.
final int pid = getParentWindow() != null ? getParentWindow().mSession.mPid : mSession.mPid;
- mTempConfiguration.setTo(mService.mProcessConfigurations.get(
- pid, mService.mRoot.getConfiguration()));
+ mTempConfiguration.setTo(mWmService.mProcessConfigurations.get(
+ pid, mWmService.mRoot.getConfiguration()));
return mTempConfiguration;
}
@@ -2325,13 +2325,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
public void binderDied() {
try {
boolean resetSplitScreenResizing = false;
- synchronized (mService.mGlobalLock) {
- final WindowState win = mService.windowForClientLocked(mSession, mClient, false);
+ synchronized (mWmService.mGlobalLock) {
+ final WindowState win = mWmService
+ .windowForClientLocked(mSession, mClient, false);
Slog.i(TAG, "WIN DEATH: " + win);
if (win != null) {
final DisplayContent dc = getDisplayContent();
if (win.mAppToken != null && win.mAppToken.findMainWindow() == win) {
- mService.mTaskSnapshotController.onAppDied(win.mAppToken);
+ mWmService.mTaskSnapshotController.onAppDied(win.mAppToken);
}
win.removeIfPossible(shouldKeepVisibleDeadAppWindow());
if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
@@ -2355,7 +2356,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
try {
// Note: this calls into ActivityManager, so we must *not* hold the window
// manager lock while calling this.
- mService.mActivityTaskManager.setSplitScreenResizing(false);
+ mWmService.mActivityTaskManager.setSplitScreenResizing(false);
} catch (RemoteException e) {
// Local call, shouldn't return RemoteException.
throw e.rethrowAsRuntimeException();
@@ -2462,10 +2463,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mWinAnimator.applyAnimationLocked(TRANSIT_ENTER, true);
}
if (requestAnim) {
- mService.scheduleAnimationLocked();
+ mWmService.scheduleAnimationLocked();
}
if ((mAttrs.flags & FLAG_NOT_FOCUSABLE) == 0) {
- mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
+ mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
}
return true;
}
@@ -2500,18 +2501,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// Window is no longer visible -- make sure if we were waiting
// for it to be displayed before enabling the display, that
// we allow the display to be enabled now.
- mService.enableScreenIfNeededLocked();
+ mWmService.enableScreenIfNeededLocked();
if (isFocused) {
if (DEBUG_FOCUS_LIGHT) Slog.i(TAG,
"WindowState.hideLw: setting mFocusMayChange true");
- mService.mFocusMayChange = true;
+ mWmService.mFocusMayChange = true;
}
}
if (requestAnim) {
- mService.scheduleAnimationLocked();
+ mWmService.scheduleAnimationLocked();
}
if (isFocused) {
- mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
+ mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /* updateImWindows */);
}
return true;
}
@@ -2573,7 +2574,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// and add the window only if the permission was granted. Therefore, if
// the mode is MODE_DEFAULT we want the op to succeed as the window is
// shown.
- final int mode = mService.mAppOps.startOpNoThrow(mAppOp,
+ final int mode = mWmService.mAppOps.startOpNoThrow(mAppOp,
getOwningUid(), getOwningPackage(), true);
if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) {
setAppOpVisibilityLw(false);
@@ -2582,7 +2583,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void resetAppOpsState() {
if (mAppOp != OP_NONE && mAppOpVisibility) {
- mService.mAppOps.finishOp(mAppOp, getOwningUid(), getOwningPackage());
+ mWmService.mAppOps.finishOp(mAppOp, getOwningUid(), getOwningPackage());
}
}
@@ -2595,13 +2596,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (mAppOpVisibility) {
// There is a race between the check and the finish calls but this is fine
// as this would mean we will get another change callback and will reconcile.
- int mode = mService.mAppOps.checkOpNoThrow(mAppOp, uid, packageName);
+ int mode = mWmService.mAppOps.checkOpNoThrow(mAppOp, uid, packageName);
if (mode != MODE_ALLOWED && mode != MODE_DEFAULT) {
- mService.mAppOps.finishOp(mAppOp, uid, packageName);
+ mWmService.mAppOps.finishOp(mAppOp, uid, packageName);
setAppOpVisibilityLw(false);
}
} else {
- final int mode = mService.mAppOps.startOpNoThrow(mAppOp, uid, packageName, true);
+ final int mode = mWmService.mAppOps.startOpNoThrow(mAppOp, uid, packageName, true);
if (mode == MODE_ALLOWED || mode == MODE_DEFAULT) {
setAppOpVisibilityLw(true);
}
@@ -2622,7 +2623,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// in wake lock statistics. So in particular, we don't want to include the
// window's hash code as in toString().
final CharSequence tag = getWindowTag();
- mDrawLock = mService.mPowerManager.newWakeLock(DRAW_WAKE_LOCK, "Window:" + tag);
+ mDrawLock = mWmService.mPowerManager.newWakeLock(DRAW_WAKE_LOCK, "Window:" + tag);
mDrawLock.setReferenceCounted(false);
mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
}
@@ -2707,10 +2708,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mAppFreezing = false;
if (mHasSurface && !getOrientationChanging()
- && mService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
+ && mWmService.mWindowsFreezingScreen != WINDOWS_FREEZING_SCREENS_TIMEOUT) {
if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "set mOrientationChanging of " + this);
setOrientationChanging(true);
- mService.mRoot.mOrientationChangeComplete = false;
+ mWmService.mRoot.mOrientationChangeComplete = false;
}
mLastFreezeDuration = 0;
setDisplayLayoutNeeded();
@@ -2800,7 +2801,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
return win.mShowToOwnerOnly
- && !mService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid));
+ && !mWmService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid));
}
private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
@@ -2899,7 +2900,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
+ ": " + mWindowFrames.mCompatFrame);
final MergedConfiguration mergedConfiguration =
- new MergedConfiguration(mService.mRoot.getConfiguration(),
+ new MergedConfiguration(mWmService.mRoot.getConfiguration(),
getMergedOverrideConfiguration());
setLastReportedMergedConfiguration(mergedConfiguration);
@@ -2920,7 +2921,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
&& mClient instanceof IWindow.Stub) {
// To prevent deadlock simulate one-way call if win.mClient is a local object.
- mService.mH.post(new Runnable() {
+ mWmService.mH.post(new Runnable() {
@Override
public void run() {
try {
@@ -2939,8 +2940,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
//TODO (multidisplay): Accessibility supported only for the default display.
- if (mService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
- mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
+ if (mWmService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
+ mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
mWindowFrames.resetInsetsChanged();
@@ -2949,12 +2950,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
} catch (RemoteException e) {
setOrientationChanging(false);
mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
- - mService.mDisplayFreezeTime);
+ - mWmService.mDisplayFreezeTime);
// We are assuming the hosting process is dead or in a zombie state.
Slog.w(TAG, "Failed to report 'resized' to the client of " + this
+ ", removing this window.");
- mService.mPendingRemove.add(this);
- mService.mWindowPlacerLocked.requestTraversal();
+ mWmService.mPendingRemove.add(this);
+ mWmService.mWindowPlacerLocked.requestTraversal();
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -3015,7 +3016,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
public void registerFocusObserver(IWindowFocusObserver observer) {
- synchronized (mService.mGlobalLock) {
+ synchronized (mWmService.mGlobalLock) {
if (mFocusCallbacks == null) {
mFocusCallbacks = new RemoteCallbackList<IWindowFocusObserver>();
}
@@ -3024,7 +3025,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
public void unregisterFocusObserver(IWindowFocusObserver observer) {
- synchronized (mService.mGlobalLock) {
+ synchronized (mWmService.mGlobalLock) {
if (mFocusCallbacks != null) {
mFocusCallbacks.unregister(observer);
}
@@ -3097,7 +3098,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
@Override
void setWaitingForDrawnIfResizingChanged() {
if (isDragResizeChanged()) {
- mService.mWaitingForDrawn.add(this);
+ mWmService.mWaitingForDrawn.add(this);
}
super.setWaitingForDrawnIfResizingChanged();
}
@@ -3586,7 +3587,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (dc != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
dc.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
dc.setLayoutNeeded();
- mService.mWindowPlacerLocked.requestTraversal();
+ mWmService.mWindowPlacerLocked.requestTraversal();
}
for (int i = mChildren.size() - 1; i >= 0; i--) {
@@ -3684,7 +3685,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
logPerformShow("Showing ");
- mService.enableScreenIfNeededLocked();
+ mWmService.enableScreenIfNeededLocked();
mWinAnimator.applyEnterAnimationLocked();
// Force the show in the next prepareSurfaceLocked() call.
@@ -3692,7 +3693,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (DEBUG_ANIM) Slog.v(TAG,
"performShowLocked: mDrawState=HAS_DRAWN in " + this);
mWinAnimator.mDrawState = HAS_DRAWN;
- mService.scheduleAnimationLocked();
+ mWmService.scheduleAnimationLocked();
if (mHidden) {
mHidden = false;
@@ -3971,7 +3972,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (mWinAnimator.mEnteringAnimation) {
mWinAnimator.mEnteringAnimation = false;
- mService.requestTraversal();
+ mWmService.requestTraversal();
// System windows don't have an activity and an app token as a result, but need a way
// to be informed about their entrance animation end.
if (mAppToken == null) {
@@ -3987,8 +3988,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
//TODO (multidisplay): Accessibility is supported only for the default display.
- if (mService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
- mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
+ if (mWmService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
+ mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
}
if (!isSelfOrAncestorWindowAnimatingExit()) {
@@ -4014,10 +4015,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mAppToken.destroySurfaces();
} else {
if (hasSurface) {
- mService.mDestroySurface.add(this);
+ mWmService.mDestroySurface.add(this);
}
if (mRemoveOnExit) {
- mService.mPendingRemove.add(this);
+ mWmService.mPendingRemove.add(this);
mRemoveOnExit = false;
}
}
@@ -4048,7 +4049,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
if (mDestroying) {
mDestroying = false;
- mService.mDestroySurface.remove(this);
+ mWmService.mDestroySurface.remove(this);
didSomething = true;
}
}
@@ -4077,7 +4078,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (displayContent != null) {
displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats("hideWallpaperWindow " + this,
+ mWmService.mWindowPlacerLocked.debugLayoutRepeats("hideWallpaperWindow " + this,
displayContent.pendingLayoutChanges);
}
}
@@ -4292,7 +4293,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
if (mDestroying) {
mDestroying = false;
- mService.mDestroySurface.remove(this);
+ mWmService.mDestroySurface.remove(this);
}
if (oldVisibility == View.GONE) {
mWinAnimator.mEnterAnimationPending = true;
@@ -4360,10 +4361,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
anim.initialize(mWindowFrames.mFrame.width(), mWindowFrames.mFrame.height(),
displayInfo.appWidth, displayInfo.appHeight);
anim.restrictDuration(MAX_ANIMATION_DURATION);
- anim.scaleCurrentDuration(mService.getWindowAnimationScaleLocked());
+ anim.scaleCurrentDuration(mWmService.getWindowAnimationScaleLocked());
final AnimationAdapter adapter = new LocalAnimationAdapter(
new WindowAnimationSpec(anim, mSurfacePosition, false /* canSkipFirstFrame */),
- mService.mSurfaceAnimationRunner);
+ mWmService.mSurfaceAnimationRunner);
startAnimation(mPendingTransaction, adapter);
commitPendingTransaction();
}
@@ -4377,7 +4378,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
transformFrameToSurfacePosition(left, top, newPosition);
final AnimationAdapter adapter = new LocalAnimationAdapter(
new MoveAnimationSpec(oldPosition.x, oldPosition.y, newPosition.x, newPosition.y),
- mService.mSurfaceAnimationRunner);
+ mWmService.mSurfaceAnimationRunner);
startAnimation(getPendingTransaction(), adapter);
}
@@ -4471,7 +4472,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
public boolean isFocused() {
final WindowState outer = mOuter.get();
if (outer != null) {
- synchronized (outer.mService.mGlobalLock) {
+ synchronized (outer.mWmService.mGlobalLock) {
return outer.isFocused();
}
}
@@ -4811,7 +4812,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final Animation anim = AnimationUtils.loadAnimation(mContext,
com.android.internal.R.anim.window_move_from_decor);
mDuration = (long)
- (anim.computeDurationHint() * mService.getWindowAnimationScaleLocked());
+ (anim.computeDurationHint() * mWmService.getWindowAnimationScaleLocked());
mInterpolator = anim.getInterpolator();
mFrom.set(fromX, fromY);
mTo.set(toX, toY);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 78a3fe5ac4ca..8bc6db7fb9a7 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -234,7 +234,7 @@ class WindowStateAnimator {
private final Point mTmpPos = new Point();
WindowStateAnimator(final WindowState win) {
- final WindowManagerService service = win.mService;
+ final WindowManagerService service = win.mWmService;
mService = service;
mAnimator = service.mAnimator;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index d8242f8a6daa..9c1378211e6d 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -172,8 +172,8 @@ class WindowToken extends WindowContainer<WindowState> {
setHidden(true);
if (changed) {
- mService.mWindowPlacerLocked.performSurfacePlacement();
- mService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /*updateInputWindows*/);
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
+ mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, false /*updateInputWindows*/);
}
if (delayed) {
@@ -202,7 +202,7 @@ class WindowToken extends WindowContainer<WindowState> {
if (!mChildren.contains(win)) {
if (DEBUG_ADD_REMOVE) Slog.v(TAG_WM, "Adding " + win + " to " + this);
addChild(win, mWindowComparator);
- mService.mWindowsChanged = true;
+ mWmService.mWindowsChanged = true;
// TODO: Should we also be setting layout needed here and other places?
}
}
@@ -326,9 +326,9 @@ class WindowToken extends WindowContainer<WindowState> {
* system bars, or in other words extend outside of the "Decor Frame"
*/
boolean canLayerAboveSystemBars() {
- int layer = mService.mPolicy.getWindowLayerFromTypeLw(windowType,
+ int layer = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,
mOwnerCanManageAppTokens);
- int navLayer = mService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
+ int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
mOwnerCanManageAppTokens);
return mOwnerCanManageAppTokens && (layer > navLayer);
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index bf83ac13fd93..8b873e3f9ad7 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -108,6 +108,7 @@ cc_defaults {
"android.hardware.contexthub@1.0",
"android.hardware.gnss@1.0",
"android.hardware.gnss@1.1",
+ "android.hardware.gnss@2.0",
"android.hardware.ir@1.0",
"android.hardware.light@2.0",
"android.hardware.power@1.0",
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index fcd9335874e1..43d2dcf7e0d1 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -32,6 +32,7 @@
#include <atomic>
#include <cinttypes>
#include <limits.h>
+#include <android-base/parseint.h>
#include <android-base/stringprintf.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/Log.h>
@@ -71,6 +72,7 @@
#define INDENT " "
+using android::base::ParseUint;
using android::base::StringPrintf;
namespace android {
@@ -81,6 +83,7 @@ namespace android {
static const float POINTER_SPEED_EXPONENT = 1.0f / 4;
static struct {
+ jclass clazz;
jmethodID notifyConfigurationChanged;
jmethodID notifyInputDevicesChanged;
jmethodID notifySwitch;
@@ -95,6 +98,7 @@ static struct {
jmethodID checkInjectEventsPermission;
jmethodID getVirtualKeyQuietTimeMillis;
jmethodID getExcludedDeviceNames;
+ jmethodID getInputPortAssociations;
jmethodID getKeyRepeatTimeout;
jmethodID getKeyRepeatDelay;
jmethodID getHoverTapTimeout;
@@ -183,6 +187,13 @@ enum {
WM_ACTION_PASS_TO_USER = 1,
};
+static std::string getStringElementFromJavaArray(JNIEnv* env, jobjectArray array, jsize index) {
+ jstring item = jstring(env->GetObjectArrayElement(array, index));
+ ScopedUtfChars chars(env, item);
+ std::string result(chars.c_str());
+ return result;
+}
+
// --- NativeInputManager ---
@@ -452,20 +463,44 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
}
outConfig->excludedDeviceNames.clear();
- jobjectArray excludedDeviceNames = jobjectArray(env->CallObjectMethod(mServiceObj,
- gServiceClassInfo.getExcludedDeviceNames));
+ jobjectArray excludedDeviceNames = jobjectArray(env->CallStaticObjectMethod(
+ gServiceClassInfo.clazz, gServiceClassInfo.getExcludedDeviceNames));
if (!checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && excludedDeviceNames) {
jsize length = env->GetArrayLength(excludedDeviceNames);
for (jsize i = 0; i < length; i++) {
- jstring item = jstring(env->GetObjectArrayElement(excludedDeviceNames, i));
- const char* deviceNameChars = env->GetStringUTFChars(item, nullptr);
- outConfig->excludedDeviceNames.push_back(deviceNameChars);
- env->ReleaseStringUTFChars(item, deviceNameChars);
- env->DeleteLocalRef(item);
+ std::string deviceName = getStringElementFromJavaArray(env, excludedDeviceNames, i);
+ outConfig->excludedDeviceNames.push_back(deviceName);
}
env->DeleteLocalRef(excludedDeviceNames);
}
+ // Associations between input ports and display ports
+ // The java method packs the information in the following manner:
+ // Original data: [{'inputPort1': '1'}, {'inputPort2': '2'}]
+ // Received data: ['inputPort1', '1', 'inputPort2', '2']
+ // So we unpack accordingly here.
+ outConfig->portAssociations.clear();
+ jobjectArray portAssociations = jobjectArray(env->CallStaticObjectMethod(
+ gServiceClassInfo.clazz, gServiceClassInfo.getInputPortAssociations));
+ if (!checkAndClearExceptionFromCallback(env, "getInputPortAssociations") && portAssociations) {
+ jsize length = env->GetArrayLength(portAssociations);
+ for (jsize i = 0; i < length / 2; i++) {
+ std::string inputPort = getStringElementFromJavaArray(env, portAssociations, 2 * i);
+ std::string displayPortStr =
+ getStringElementFromJavaArray(env, portAssociations, 2 * i + 1);
+ uint8_t displayPort;
+ // Should already have been validated earlier, but do it here for safety.
+ bool success = ParseUint(displayPortStr, &displayPort);
+ if (!success) {
+ ALOGE("Could not parse entry in port configuration file, received: %s",
+ displayPortStr.c_str());
+ continue;
+ }
+ outConfig->portAssociations.insert({inputPort, displayPort});
+ }
+ env->DeleteLocalRef(portAssociations);
+ }
+
jint hoverTapTimeout = env->CallIntMethod(mServiceObj,
gServiceClassInfo.getHoverTapTimeout);
if (!checkAndClearExceptionFromCallback(env, "getHoverTapTimeout")) {
@@ -1697,6 +1732,10 @@ static const JNINativeMethod gInputManagerMethods[] = {
var = env->GetMethodID(clazz, methodName, methodDescriptor); \
LOG_FATAL_IF(! (var), "Unable to find method " methodName);
+#define GET_STATIC_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+ var = env->GetStaticMethodID(clazz, methodName, methodDescriptor); \
+ LOG_FATAL_IF(! (var), "Unable to find static method " methodName);
+
#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
LOG_FATAL_IF(! (var), "Unable to find field " fieldName);
@@ -1711,6 +1750,7 @@ int register_android_server_InputManager(JNIEnv* env) {
jclass clazz;
FIND_CLASS(clazz, "com/android/server/input/InputManagerService");
+ gServiceClassInfo.clazz = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
GET_METHOD_ID(gServiceClassInfo.notifyConfigurationChanged, clazz,
"notifyConfigurationChanged", "(J)V");
@@ -1754,9 +1794,12 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gServiceClassInfo.getVirtualKeyQuietTimeMillis, clazz,
"getVirtualKeyQuietTimeMillis", "()I");
- GET_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz,
+ GET_STATIC_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz,
"getExcludedDeviceNames", "()[Ljava/lang/String;");
+ GET_STATIC_METHOD_ID(gServiceClassInfo.getInputPortAssociations, clazz,
+ "getInputPortAssociations", "()[Ljava/lang/String;");
+
GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz,
"getKeyRepeatTimeout", "()I");
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 92160053804d..4d0556c7507a 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -20,9 +20,11 @@
#include <android/hardware/gnss/1.0/IGnss.h>
#include <android/hardware/gnss/1.1/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnss.h>
#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
+#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
#include <nativehelper/JNIHelp.h>
#include "jni.h"
#include "hardware_legacy/power.h"
@@ -110,13 +112,15 @@ using android::hidl::base::V1_0::IBase;
using IGnss_V1_0 = android::hardware::gnss::V1_0::IGnss;
using IGnss_V1_1 = android::hardware::gnss::V1_1::IGnss;
+using IGnss_V2_0 = android::hardware::gnss::V2_0::IGnss;
using IGnssConfiguration_V1_0 = android::hardware::gnss::V1_0::IGnssConfiguration;
using IGnssConfiguration_V1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
+using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
using IGnssMeasurementCallback_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
using IGnssMeasurementCallback_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
-
+using IGnssMeasurementCallback_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
struct GnssDeathRecipient : virtual public hidl_death_recipient
{
@@ -135,6 +139,7 @@ static const uint32_t ADR_STATE_HALF_CYCLE_REPORTED = (1<<4);
sp<GnssDeathRecipient> gnssHalDeathRecipient = nullptr;
sp<IGnss_V1_0> gnssHal = nullptr;
sp<IGnss_V1_1> gnssHal_V1_1 = nullptr;
+sp<IGnss_V2_0> gnssHal_V2_0 = nullptr;
sp<IGnssXtra> gnssXtraIface = nullptr;
sp<IAGnssRil> agnssRilIface = nullptr;
sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
@@ -146,6 +151,7 @@ sp<IGnssConfiguration_V1_1> gnssConfigurationIface_V1_1 = nullptr;
sp<IGnssNi> gnssNiIface = nullptr;
sp<IGnssMeasurement_V1_0> gnssMeasurementIface = nullptr;
sp<IGnssMeasurement_V1_1> gnssMeasurementIface_V1_1 = nullptr;
+sp<IGnssMeasurement_V2_0> gnssMeasurementIface_V2_0 = nullptr;
sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
#define WAKE_LOCK_NAME "GPS"
@@ -744,7 +750,9 @@ Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb(
* GnssMeasurementCallback implements the callback methods required for the
* GnssMeasurement interface.
*/
-struct GnssMeasurementCallback : public IGnssMeasurementCallback_V1_1 {
+struct GnssMeasurementCallback : public IGnssMeasurementCallback_V2_0 {
+ Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_V2_0::GnssData& data)
+ override;
Return<void> gnssMeasurementCb(const IGnssMeasurementCallback_V1_1::GnssData& data) override;
Return<void> GnssMeasurementCb(const IGnssMeasurementCallback_V1_0::GnssData& data) override;
private:
@@ -761,6 +769,11 @@ struct GnssMeasurementCallback : public IGnssMeasurementCallback_V1_1 {
void setMeasurementData(JNIEnv* env, jobject clock, jobjectArray measurementArray);
};
+Return<void> GnssMeasurementCallback::gnssMeasurementCb_2_0(
+ const IGnssMeasurementCallback_V2_0::GnssData& data) {
+ // TODO(b/119571122): implement gnssMeasurementCb_2_0
+ return Void();
+}
Return<void> GnssMeasurementCallback::gnssMeasurementCb(
const IGnssMeasurementCallback_V1_1::GnssData& data) {
@@ -1126,13 +1139,22 @@ Return<void> GnssBatchingCallback::gnssLocationBatchCb(const hidl_vec<GnssLocati
}
static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
+ gnssHal_V2_0 = IGnss_V2_0::getService();
+ if (gnssHal_V2_0 != nullptr) {
+ gnssHal = gnssHal_V2_0;
+ gnssHal_V1_1 = gnssHal_V2_0;
+ return;
+ }
+
+ ALOGD("gnssHal 2.0 was null, trying 1.1");
gnssHal_V1_1 = IGnss_V1_1::getService();
- if (gnssHal_V1_1 == nullptr) {
- ALOGD("gnssHal 1.1 was null, trying 1.0");
- gnssHal = IGnss_V1_0::getService();
- } else {
+ if (gnssHal_V1_1 != nullptr) {
gnssHal = gnssHal_V1_1;
+ return;
}
+
+ ALOGD("gnssHal 1.1 was null, trying 1.0");
+ gnssHal = IGnss_V1_0::getService();
}
static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass clazz) {
@@ -1187,110 +1209,120 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass
LOG_ALWAYS_FATAL("Unable to get Java VM. Error: %d", jvmStatus);
}
- if (gnssHal != nullptr) {
- gnssHalDeathRecipient = new GnssDeathRecipient();
- hardware::Return<bool> linked = gnssHal->linkToDeath(
- gnssHalDeathRecipient, /*cookie*/ 0);
- if (!linked.isOk()) {
- ALOGE("Transaction error in linking to GnssHAL death: %s",
- linked.description().c_str());
- } else if (!linked) {
- ALOGW("Unable to link to GnssHal death notifications");
- } else {
- ALOGD("Link to death notification successful");
- }
+ if (gnssHal == nullptr) {
+ ALOGE("Unable to get GPS service\n");
+ return;
+ }
- auto gnssXtra = gnssHal->getExtensionXtra();
- if (!gnssXtra.isOk()) {
- ALOGD("Unable to get a handle to Xtra");
- } else {
- gnssXtraIface = gnssXtra;
- }
+ gnssHalDeathRecipient = new GnssDeathRecipient();
+ hardware::Return<bool> linked = gnssHal->linkToDeath(gnssHalDeathRecipient, /*cookie*/ 0);
+ if (!linked.isOk()) {
+ ALOGE("Transaction error in linking to GnssHAL death: %s",
+ linked.description().c_str());
+ } else if (!linked) {
+ ALOGW("Unable to link to GnssHal death notifications");
+ } else {
+ ALOGD("Link to death notification successful");
+ }
- auto gnssRil = gnssHal->getExtensionAGnssRil();
- if (!gnssRil.isOk()) {
- ALOGD("Unable to get a handle to AGnssRil");
- } else {
- agnssRilIface = gnssRil;
- }
+ auto gnssXtra = gnssHal->getExtensionXtra();
+ if (!gnssXtra.isOk()) {
+ ALOGD("Unable to get a handle to Xtra");
+ } else {
+ gnssXtraIface = gnssXtra;
+ }
- auto gnssAgnss = gnssHal->getExtensionAGnss();
- if (!gnssAgnss.isOk()) {
- ALOGD("Unable to get a handle to AGnss");
- } else {
- agnssIface = gnssAgnss;
- }
+ auto gnssRil = gnssHal->getExtensionAGnssRil();
+ if (!gnssRil.isOk()) {
+ ALOGD("Unable to get a handle to AGnssRil");
+ } else {
+ agnssRilIface = gnssRil;
+ }
- auto gnssNavigationMessage = gnssHal->getExtensionGnssNavigationMessage();
- if (!gnssNavigationMessage.isOk()) {
- ALOGD("Unable to get a handle to GnssNavigationMessage");
- } else {
- gnssNavigationMessageIface = gnssNavigationMessage;
- }
+ auto gnssAgnss = gnssHal->getExtensionAGnss();
+ if (!gnssAgnss.isOk()) {
+ ALOGD("Unable to get a handle to AGnss");
+ } else {
+ agnssIface = gnssAgnss;
+ }
- if (gnssHal_V1_1 != nullptr) {
- auto gnssMeasurement = gnssHal_V1_1->getExtensionGnssMeasurement_1_1();
- if (!gnssMeasurement.isOk()) {
- ALOGD("Unable to get a handle to GnssMeasurement");
- } else {
- gnssMeasurementIface_V1_1 = gnssMeasurement;
- gnssMeasurementIface = gnssMeasurementIface_V1_1;
- }
- } else {
- auto gnssMeasurement_V1_0 = gnssHal->getExtensionGnssMeasurement();
- if (!gnssMeasurement_V1_0.isOk()) {
- ALOGD("Unable to get a handle to GnssMeasurement");
- } else {
- gnssMeasurementIface = gnssMeasurement_V1_0;
- }
- }
+ auto gnssNavigationMessage = gnssHal->getExtensionGnssNavigationMessage();
+ if (!gnssNavigationMessage.isOk()) {
+ ALOGD("Unable to get a handle to GnssNavigationMessage");
+ } else {
+ gnssNavigationMessageIface = gnssNavigationMessage;
+ }
- auto gnssDebug = gnssHal->getExtensionGnssDebug();
- if (!gnssDebug.isOk()) {
- ALOGD("Unable to get a handle to GnssDebug");
+ if (gnssHal_V2_0 != nullptr) {
+ // TODO(b/119638366): getExtensionGnssMeasurement_1_1 from gnssHal_V2_0
+ auto gnssMeasurement = gnssHal_V2_0->getExtensionGnssMeasurement_2_0();
+ if (!gnssMeasurement.isOk()) {
+ ALOGD("Unable to get a handle to GnssMeasurement_V2_0");
} else {
- gnssDebugIface = gnssDebug;
+ gnssMeasurementIface_V2_0 = gnssMeasurement;
+ gnssMeasurementIface_V1_1 = gnssMeasurementIface_V2_0;
+ gnssMeasurementIface = gnssMeasurementIface_V2_0;
}
+ } else if (gnssHal_V1_1 != nullptr) {
+ auto gnssMeasurement = gnssHal_V1_1->getExtensionGnssMeasurement_1_1();
+ if (!gnssMeasurement.isOk()) {
+ ALOGD("Unable to get a handle to GnssMeasurement_V1_1");
+ } else {
+ gnssMeasurementIface_V1_1 = gnssMeasurement;
+ gnssMeasurementIface = gnssMeasurementIface_V1_1;
+ }
+ } else {
+ auto gnssMeasurement_V1_0 = gnssHal->getExtensionGnssMeasurement();
+ if (!gnssMeasurement_V1_0.isOk()) {
+ ALOGD("Unable to get a handle to GnssMeasurement");
+ } else {
+ gnssMeasurementIface = gnssMeasurement_V1_0;
+ }
+ }
- auto gnssNi = gnssHal->getExtensionGnssNi();
- if (!gnssNi.isOk()) {
- ALOGD("Unable to get a handle to GnssNi");
- } else {
- gnssNiIface = gnssNi;
- }
+ auto gnssDebug = gnssHal->getExtensionGnssDebug();
+ if (!gnssDebug.isOk()) {
+ ALOGD("Unable to get a handle to GnssDebug");
+ } else {
+ gnssDebugIface = gnssDebug;
+ }
- if (gnssHal_V1_1 != nullptr) {
- auto gnssConfiguration = gnssHal_V1_1->getExtensionGnssConfiguration_1_1();
- if (!gnssConfiguration.isOk()) {
- ALOGD("Unable to get a handle to GnssConfiguration");
- } else {
- gnssConfigurationIface_V1_1 = gnssConfiguration;
- gnssConfigurationIface = gnssConfigurationIface_V1_1;
- }
- } else {
- auto gnssConfiguration_V1_0 = gnssHal->getExtensionGnssConfiguration();
- if (!gnssConfiguration_V1_0.isOk()) {
- ALOGD("Unable to get a handle to GnssConfiguration");
- } else {
- gnssConfigurationIface = gnssConfiguration_V1_0;
- }
- }
+ auto gnssNi = gnssHal->getExtensionGnssNi();
+ if (!gnssNi.isOk()) {
+ ALOGD("Unable to get a handle to GnssNi");
+ } else {
+ gnssNiIface = gnssNi;
+ }
- auto gnssGeofencing = gnssHal->getExtensionGnssGeofencing();
- if (!gnssGeofencing.isOk()) {
- ALOGD("Unable to get a handle to GnssGeofencing");
+ if (gnssHal_V1_1 != nullptr) {
+ auto gnssConfiguration = gnssHal_V1_1->getExtensionGnssConfiguration_1_1();
+ if (!gnssConfiguration.isOk()) {
+ ALOGD("Unable to get a handle to GnssConfiguration");
} else {
- gnssGeofencingIface = gnssGeofencing;
+ gnssConfigurationIface_V1_1 = gnssConfiguration;
+ gnssConfigurationIface = gnssConfigurationIface_V1_1;
}
-
- auto gnssBatching = gnssHal->getExtensionGnssBatching();
- if (!gnssBatching.isOk()) {
- ALOGD("Unable to get a handle to gnssBatching");
+ } else {
+ auto gnssConfiguration_V1_0 = gnssHal->getExtensionGnssConfiguration();
+ if (!gnssConfiguration_V1_0.isOk()) {
+ ALOGD("Unable to get a handle to GnssConfiguration");
} else {
- gnssBatchingIface = gnssBatching;
+ gnssConfigurationIface = gnssConfiguration_V1_0;
}
+ }
+
+ auto gnssGeofencing = gnssHal->getExtensionGnssGeofencing();
+ if (!gnssGeofencing.isOk()) {
+ ALOGD("Unable to get a handle to GnssGeofencing");
+ } else {
+ gnssGeofencingIface = gnssGeofencing;
+ }
+
+ auto gnssBatching = gnssHal->getExtensionGnssBatching();
+ if (!gnssBatching.isOk()) {
+ ALOGD("Unable to get a handle to gnssBatching");
} else {
- ALOGE("Unable to get GPS service\n");
+ gnssBatchingIface = gnssBatching;
}
}
@@ -1820,10 +1852,11 @@ static jboolean android_location_GnssMeasurementsProvider_start_measurement_coll
sp<GnssMeasurementCallback> cbIface = new GnssMeasurementCallback();
IGnssMeasurement_V1_0::GnssMeasurementStatus result =
- IGnssMeasurement_V1_0::GnssMeasurementStatus::ERROR_GENERIC;;
- if (gnssMeasurementIface_V1_1 != nullptr) {
- result = gnssMeasurementIface_V1_1->setCallback_1_1(cbIface,
- enableFullTracking);
+ IGnssMeasurement_V1_0::GnssMeasurementStatus::ERROR_GENERIC;
+ if (gnssMeasurementIface_V2_0 != nullptr) {
+ result = gnssMeasurementIface_V2_0->setCallback_2_0(cbIface, enableFullTracking);
+ } else if (gnssMeasurementIface_V1_1 != nullptr) {
+ result = gnssMeasurementIface_V1_1->setCallback_1_1(cbIface, enableFullTracking);
} else {
if (enableFullTracking == JNI_TRUE) {
// full tracking mode not supported in 1.0 HAL
@@ -1837,7 +1870,7 @@ static jboolean android_location_GnssMeasurementsProvider_start_measurement_coll
static_cast<int32_t>(result));
return JNI_FALSE;
} else {
- ALOGD("gnss measurement infc has been enabled");
+ ALOGD("gnss measurement infc has been enabled");
}
return JNI_TRUE;
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index fa17b6125983..746c4530a5e1 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -143,9 +143,6 @@
<activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity2" />
<activity android:name="com.android.server.pm.BaseShortcutManagerTest$ShortcutActivity3" />
- <activity android:name="com.android.server.wm.ScreenDecorWindowTests$TestActivity"
- android:showWhenLocked="true"/>
-
<activity android:name="com.android.server.pm.ShortcutTestActivity"
android:enabled="true" android:exported="true" />
@@ -206,12 +203,6 @@
</intent-filter>
</activity-alias>
- <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityA" />
- <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityB" />
- <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityRequestedOrientationChange" />
- <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityTaskChangeCallbacks" />
- <activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityTaskDescriptionChange" />
-
<receiver android:name="com.android.server.appwidget.DummyAppWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
diff --git a/services/tests/servicestests/res/raw/input_port_associations.xml b/services/tests/servicestests/res/raw/input_port_associations.xml
new file mode 100644
index 000000000000..b10d541f942c
--- /dev/null
+++ b/services/tests/servicestests/res/raw/input_port_associations.xml
@@ -0,0 +1,4 @@
+<ports>
+ <port display="0" input="USB1" />
+ <port display="1" input="USB2" />
+</ports> \ No newline at end of file
diff --git a/services/tests/servicestests/res/raw/input_port_associations_bad_displayport.xml b/services/tests/servicestests/res/raw/input_port_associations_bad_displayport.xml
new file mode 100644
index 000000000000..8eeb1f58ef9e
--- /dev/null
+++ b/services/tests/servicestests/res/raw/input_port_associations_bad_displayport.xml
@@ -0,0 +1,3 @@
+<ports>
+ <port display="a" input="USB1" />
+</ports> \ No newline at end of file
diff --git a/services/tests/servicestests/res/raw/input_port_associations_bad_xml.xml b/services/tests/servicestests/res/raw/input_port_associations_bad_xml.xml
new file mode 100644
index 000000000000..cf6e12486239
--- /dev/null
+++ b/services/tests/servicestests/res/raw/input_port_associations_bad_xml.xml
@@ -0,0 +1,3 @@
+<ports>
+ <port Garbage data inside xml>
+</ports> \ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
index c7409d7f8335..89c7b71e2cc1 100644
--- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
@@ -20,7 +20,6 @@ import static com.android.server.am.MemoryStatUtil.BYTES_IN_KILOBYTE;
import static com.android.server.am.MemoryStatUtil.JIFFY_NANOS;
import static com.android.server.am.MemoryStatUtil.MemoryStat;
import static com.android.server.am.MemoryStatUtil.PAGE_SIZE;
-import static com.android.server.am.MemoryStatUtil.parseMemoryMaxUsageFromMemCg;
import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromMemcg;
import static com.android.server.am.MemoryStatUtil.parseMemoryStatFromProcfs;
import static com.android.server.am.MemoryStatUtil.parseVmHWMFromProcfs;
@@ -197,23 +196,6 @@ public class MemoryStatUtilTest {
}
@Test
- public void testParseMemoryMaxUsageFromMemCg_parsesCorrectValue() {
- assertEquals(1234, parseMemoryMaxUsageFromMemCg("1234"));
- }
-
- @Test
- public void testParseMemoryMaxUsageFromMemCg_emptyContents() {
- assertEquals(0, parseMemoryMaxUsageFromMemCg(""));
-
- assertEquals(0, parseMemoryMaxUsageFromMemCg(null));
- }
-
- @Test
- public void testParseMemoryMaxUsageFromMemCg_incorrectValue() {
- assertEquals(0, parseMemoryMaxUsageFromMemCg("memory"));
- }
-
- @Test
public void testParseMemoryStatFromProcfs_parsesCorrectValues() {
MemoryStat stat = parseMemoryStatFromProcfs(PROC_STAT_CONTENTS);
assertEquals(1, stat.pgfault);
diff --git a/services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java b/services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java
new file mode 100644
index 000000000000..636aa375a84c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/input/ConfigurationProcessorTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.util.Pair;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * Build/Install/Run:
+ * atest ConfigurationProcessorTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class ConfigurationProcessorTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
+ }
+
+ @Test
+ public void testGetInputPortAssociations() {
+ final int res = com.android.frameworks.servicestests.R.raw.input_port_associations;
+ InputStream xml = mContext.getResources().openRawResource(res);
+ List<Pair<String, String>> associations = null;
+ try {
+ associations = ConfigurationProcessor.processInputPortAssociations(xml);
+ } catch (Exception e) {
+ fail("Could not process xml file for input associations");
+ }
+ assertNotNull(associations);
+ assertEquals(2, associations.size());
+ assertTrue(associations.contains(Pair.create("USB1", "0")));
+ assertTrue(associations.contains(Pair.create("USB2", "1")));
+ }
+
+ @Test
+ public void testGetInputPortAssociationsBadDisplayport() {
+ final int res =
+ com.android.frameworks.servicestests.R.raw.input_port_associations_bad_displayport;
+ InputStream xml = mContext.getResources().openRawResource(res);
+ List<Pair<String, String>> associations = null;
+ try {
+ associations = ConfigurationProcessor.processInputPortAssociations(xml);
+ } catch (Exception e) {
+ fail("Could not process xml file for input associations");
+ }
+ assertNotNull(associations);
+ assertEquals(0, associations.size());
+ }
+
+ @Test
+ public void testGetInputPortAssociationsEmptyConfig() {
+ final int res = com.android.frameworks.servicestests.R.raw.input_port_associations_bad_xml;
+ InputStream xml = mContext.getResources().openRawResource(res);
+ try {
+ ConfigurationProcessor.processInputPortAssociations(xml);
+ fail("Parsing should fail, because xml contains bad data");
+ } catch (Exception e) {
+ // This is expected
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java
new file mode 100644
index 000000000000..fc2dcb9cc83b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SP800DeriveTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.locksettings;
+
+import android.test.AndroidTestCase;
+
+import com.android.internal.util.HexDump;
+
+public class SP800DeriveTests extends AndroidTestCase {
+ public void testFixedInput() throws Exception {
+ // CAVP: https://csrc.nist.gov/projects/cryptographic-algorithm-validation-program/key-derivation
+ byte[] keyBytes = HexDump.hexStringToByteArray(
+ "e204d6d466aad507ffaf6d6dab0a5b26"
+ + "152c9e21e764370464e360c8fbc765c6");
+ SP800Derive sk = new SP800Derive(keyBytes);
+ byte[] fixedInput = HexDump.hexStringToByteArray(
+ "7b03b98d9f94b899e591f3ef264b71b1"
+ + "93fba7043c7e953cde23bc5384bc1a62"
+ + "93580115fae3495fd845dadbd02bd645"
+ + "5cf48d0f62b33e62364a3a80");
+ byte[] res = sk.fixedInput(fixedInput);
+ assertEquals((
+ "770dfab6a6a4a4bee0257ff335213f78"
+ + "d8287b4fd537d5c1fffa956910e7c779").toUpperCase(), HexDump.toHexString(res));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 92efc3cc2b3c..99b827c11853 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.net;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
@@ -72,7 +72,6 @@ import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
-import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
@@ -142,9 +141,8 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
-import com.android.server.net.NetworkPolicyManagerInternal;
-import com.android.server.net.NetworkPolicyManagerService;
-import com.android.server.net.NetworkStatsManagerInternal;
+import com.android.server.DeviceIdleController;
+import com.android.server.LocalServices;
import com.google.common.util.concurrent.AbstractFuture;
@@ -195,15 +193,6 @@ import java.util.stream.Collectors;
/**
* Tests for {@link NetworkPolicyManagerService}.
- *
- * <p>Typical usage:
- *
- * <pre><code>
- m -j32 FrameworksServicesTests && adb install -r -g \
- ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk && \
- adb shell am instrument -e class "com.android.server.NetworkPolicyManagerServiceTest" -w \
- "com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner"
- * </code></pre>
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
@@ -376,7 +365,7 @@ public class NetworkPolicyManagerServiceTest {
return null;
}
}).when(mActivityManager).registerUidObserver(any(), anyInt(),
- eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), isNull(String.class));
+ eq(NetworkPolicyManager.FOREGROUND_THRESHOLD_STATE), any(String.class));
mFutureIntent = newRestrictBackgroundChangedFuture();
mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
@@ -425,7 +414,7 @@ public class NetworkPolicyManagerServiceTest {
// catch INetworkManagementEventObserver during systemReady()
final ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
- ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
+ ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
verify(mNetworkManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
@@ -1782,7 +1771,7 @@ public class NetworkPolicyManagerServiceTest {
}
private static NetworkPolicy buildFakeMobilePolicy(int cycleDay, long warningBytes,
- long limitBytes, boolean inferred){
+ long limitBytes, boolean inferred) {
final NetworkTemplate template = buildTemplateMobileAll(FAKE_SUBSCRIBER_ID);
return new NetworkPolicy(template, cycleDay, new Time().timezone, warningBytes,
limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, true, inferred);
@@ -1880,7 +1869,7 @@ public class NetworkPolicyManagerServiceTest {
}
private static void assertNotificationType(int expected, String actualTag) {
- assertEquals("notification type mismatch for '" + actualTag +"'",
+ assertEquals("notification type mismatch for '" + actualTag + "'",
Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
}
@@ -1914,7 +1903,8 @@ public class NetworkPolicyManagerServiceTest {
final String action = ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
final Intent intent = future.get(5, TimeUnit.SECONDS);
assertNotNull("Didn't get a " + action + "intent in 5 seconds");
- assertEquals("Wrong package on " + action + " intent", expectedPackage, intent.getPackage());
+ assertEquals("Wrong package on " + action + " intent",
+ expectedPackage, intent.getPackage());
}
// TODO: replace by Truth, Hamcrest, or a similar tool.
@@ -1935,7 +1925,7 @@ public class NetworkPolicyManagerServiceTest {
}
if (errors.length() > 0) {
fail("assertContainsInAnyOrder(expected=" + Arrays.toString(expected)
- + ", actual=" + Arrays.toString(actual) +") failed: \n" + errors);
+ + ", actual=" + Arrays.toString(actual) + ") failed: \n" + errors);
}
}
@@ -1998,7 +1988,7 @@ public class NetworkPolicyManagerServiceTest {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
- Log.d(TAG,"counting down on answer: " + invocation);
+ Log.d(TAG, "counting down on answer: " + invocation);
latch.countDown();
return null;
}
@@ -2036,8 +2026,8 @@ public class NetworkPolicyManagerServiceTest {
final String assetPath = NETPOLICY_DIR + "/" + mNetpolicyXml;
final File netConfigFile = new File(mPolicyDir, "netpolicy.xml");
Log.d(TAG, "Creating " + netConfigFile + " from asset " + assetPath);
- try (final InputStream in = context.getResources().getAssets().open(assetPath);
- final OutputStream out = new FileOutputStream(netConfigFile)) {
+ try (InputStream in = context.getResources().getAssets().open(assetPath);
+ OutputStream out = new FileOutputStream(netConfigFile)) {
Streams.copy(in, out);
}
}
@@ -2049,9 +2039,7 @@ public class NetworkPolicyManagerServiceTest {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NetPolicyXml {
-
- public String value() default "";
-
+ String value() default "";
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index d7988656c9de..ce59e6ec9760 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -31,6 +31,7 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.Signature;
+import android.content.pm.UsesPermissionInfo;
import android.os.Bundle;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
@@ -464,6 +465,7 @@ public class PackageParserTest {
pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo()));
pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo()));
pkg.requestedPermissions.add("foo7");
+ pkg.usesPermissionInfos.add(new UsesPermissionInfo("foo7"));
pkg.implicitPermissions.add("foo25");
pkg.protectedBroadcasts = new ArrayList<>();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
deleted file mode 100644
index 2e47c353d8c2..000000000000
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import static android.app.AppOpsManager.OP_NONE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyFloat;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-
-import android.app.ActivityManager;
-import android.content.ComponentName;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.os.Binder;
-import android.os.IBinder;
-import android.view.IApplicationToken;
-import android.view.IWindow;
-import android.view.SurfaceControl.Transaction;
-import android.view.WindowManager;
-
-import org.mockito.invocation.InvocationOnMock;
-
-/**
- * A collection of static functions that can be referenced by other test packages to provide access
- * to WindowManager related test functionality.
- */
-public class WindowTestUtils {
- private static int sNextTaskId = 0;
-
- /**
- * Creates a mock instance of {@link StackWindowController}.
- */
- public static StackWindowController createMockStackWindowContainerController() {
- StackWindowController controller = mock(StackWindowController.class);
- controller.mContainer = mock(TestTaskStack.class);
-
- // many components rely on the {@link StackWindowController#adjustConfigurationForBounds}
- // to properly set bounds values in the configuration. We must mimick those actions here.
- doAnswer((InvocationOnMock invocationOnMock) -> {
- final Configuration config = invocationOnMock.<Configuration>getArgument(7);
- final Rect bounds = invocationOnMock.<Rect>getArgument(0);
- config.windowConfiguration.setBounds(bounds);
- return null;
- }).when(controller).adjustConfigurationForBounds(any(), any(), any(), any(),
- anyBoolean(), anyBoolean(), anyFloat(), any(), any(), anyInt());
-
- return controller;
- }
-
- /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
- public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
- int userId) {
- synchronized (service.mGlobalLock) {
- final Task newTask = new Task(sNextTaskId++, stack, userId, service, 0, false,
- new ActivityManager.TaskDescription(), null);
- stack.addTask(newTask, POSITION_TOP);
- return newTask;
- }
- }
-
- /**
- * An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
- * normally be mocked out.
- */
- public static class TestTaskStack extends TaskStack {
- TestTaskStack(WindowManagerService service, int stackId) {
- super(service, stackId, null);
- }
-
- @Override
- void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
- // Do nothing.
- }
- }
-
- static TestAppWindowToken createTestAppWindowToken(DisplayContent dc) {
- synchronized (dc.mService.mGlobalLock) {
- return new TestAppWindowToken(dc);
- }
- }
-
- /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
- public static class TestAppWindowToken extends AppWindowToken {
- boolean mOnTop = false;
- private Transaction mPendingTransactionOverride;
-
- private TestAppWindowToken(DisplayContent dc) {
- super(dc.mService, new IApplicationToken.Stub() {
- public String getName() {return null;}
- }, new ComponentName("", ""), false, dc, true /* fillsParent */);
- }
-
- TestAppWindowToken(WindowManagerService service, IApplicationToken token,
- ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
- long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
- int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
- boolean launchTaskBehind, boolean alwaysFocusable, ActivityRecord activityRecord) {
- super(service, token, activityComponent, voiceInteraction, dc,
- inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
- orientation, rotationAnimationHint, configChanges, launchTaskBehind,
- alwaysFocusable, activityRecord);
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
-
- WindowState getFirstChild() {
- return mChildren.peekFirst();
- }
-
- WindowState getLastChild() {
- return mChildren.peekLast();
- }
-
- int positionInParent() {
- return getParent().mChildren.indexOf(this);
- }
-
- void setIsOnTop(boolean onTop) {
- mOnTop = onTop;
- }
-
- @Override
- boolean isOnTop() {
- return mOnTop;
- }
-
- void setPendingTransaction(Transaction transaction) {
- mPendingTransactionOverride = transaction;
- }
-
- @Override
- public Transaction getPendingTransaction() {
- return mPendingTransactionOverride == null
- ? super.getPendingTransaction()
- : mPendingTransactionOverride;
- }
- }
-
- static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
- return createTestWindowToken(type, dc, false /* persistOnEmpty */);
- }
-
- static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
- boolean persistOnEmpty) {
- synchronized (dc.mService.mGlobalLock) {
- return new TestWindowToken(type, dc, persistOnEmpty);
- }
- }
-
- /* Used so we can gain access to some protected members of the {@link WindowToken} class */
- public static class TestWindowToken extends WindowToken {
-
- private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
- super(dc.mService, mock(IBinder.class), type, persistOnEmpty, dc,
- false /* ownerCanManageAppTokens */);
- }
-
- int getWindowsCount() {
- return mChildren.size();
- }
-
- boolean hasWindow(WindowState w) {
- return mChildren.contains(w);
- }
- }
-
- /* Used so we can gain access to some protected members of the {@link Task} class */
- public static class TestTask extends Task {
- boolean mShouldDeferRemoval = false;
- boolean mOnDisplayChangedCalled = false;
- private boolean mIsAnimating = false;
-
- TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service,
- int resizeMode, boolean supportsPictureInPicture,
- TaskWindowContainerController controller) {
- super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture,
- new ActivityManager.TaskDescription(), controller);
- }
-
- boolean shouldDeferRemoval() {
- return mShouldDeferRemoval;
- }
-
- int positionInParent() {
- return getParent().mChildren.indexOf(this);
- }
-
- @Override
- void onDisplayChanged(DisplayContent dc) {
- super.onDisplayChanged(dc);
- mOnDisplayChangedCalled = true;
- }
-
- @Override
- boolean isSelfAnimating() {
- return mIsAnimating;
- }
-
- void setLocalIsAnimating(boolean isAnimating) {
- mIsAnimating = isAnimating;
- }
- }
-
- /**
- * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
- * class.
- */
- public static class TestTaskWindowContainerController extends TaskWindowContainerController {
-
- static final TaskWindowContainerListener NOP_LISTENER = new TaskWindowContainerListener() {
- @Override
- public void registerConfigurationChangeListener(
- ConfigurationContainerListener listener) {
- }
-
- @Override
- public void unregisterConfigurationChangeListener(
- ConfigurationContainerListener listener) {
- }
-
- @Override
- public void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
- }
-
- @Override
- public void requestResize(Rect bounds, int resizeMode) {
- }
- };
-
- TestTaskWindowContainerController(WindowTestsBase testsBase) {
- this(testsBase.createStackControllerOnDisplay(testsBase.mDisplayContent));
- }
-
- TestTaskWindowContainerController(StackWindowController stackController) {
- super(sNextTaskId++, NOP_LISTENER, stackController, 0 /* userId */, null /* bounds */,
- RESIZE_MODE_UNRESIZEABLE, false /* supportsPictureInPicture */, true /* toTop*/,
- true /* showForAllUsers */, new ActivityManager.TaskDescription(),
- stackController.mService);
- }
-
- @Override
- TestTask createTask(int taskId, TaskStack stack, int userId, int resizeMode,
- boolean supportsPictureInPicture, ActivityManager.TaskDescription taskDescription) {
- return new TestTask(taskId, stack, userId, mService, resizeMode,
- supportsPictureInPicture, this);
- }
- }
-
- public static class TestIApplicationToken implements IApplicationToken {
-
- private final Binder mBinder = new Binder();
- @Override
- public IBinder asBinder() {
- return mBinder;
- }
- @Override
- public String getName() {
- return null;
- }
- }
-
- /** Used to track resize reports. */
- public static class TestWindowState extends WindowState {
- boolean resizeReported;
-
- TestWindowState(WindowManagerService service, Session session, IWindow window,
- WindowManager.LayoutParams attrs, WindowToken token) {
- super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
- false /* ownerCanAddInternalSystemWindow */);
- }
-
- @Override
- void reportResized() {
- super.reportResized();
- resizeReported = true;
- }
-
- @Override
- public boolean isGoneForLayoutLw() {
- return false;
- }
-
- @Override
- void updateResizingWindowIfNeeded() {
- // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
- // the system that it can actually update the window.
- boolean hadSurface = mHasSurface;
- mHasSurface = true;
-
- super.updateResizingWindowIfNeeded();
-
- mHasSurface = hadSurface;
- }
- }
-}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 38d8e3990e00..6c7ede3df4db 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -41,6 +41,7 @@ import static org.mockito.Mockito.when;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.ComponentName;
@@ -1097,6 +1098,25 @@ public class ZenModeHelperTest extends UiServiceTestCase {
assertFalse(Objects.equals(defaultRuleName, ruleAfterUpdating.name)); // update name
}
+ @Test
+ public void testAddAutomaticZenRule() {
+ AutomaticZenRule zenRule = new AutomaticZenRule("name",
+ new ComponentName("android", "ScheduleConditionProvider"),
+ ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+ String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+
+ assertTrue(id != null);
+ ZenModeConfig.ZenRule ruleInConfig = mZenModeHelperSpy.mConfig.automaticRules.get(id);
+ assertTrue(ruleInConfig != null);
+ assertEquals(zenRule.isEnabled(), ruleInConfig.enabled);
+ assertEquals(zenRule.isModified(), ruleInConfig.modified);
+ assertEquals(zenRule.getConditionId(), ruleInConfig.conditionId);
+ assertEquals(NotificationManager.zenModeFromInterruptionFilter(
+ zenRule.getInterruptionFilter(), -1), ruleInConfig.zenMode);
+ assertEquals(zenRule.getName(), ruleInConfig.name);
+ }
+
private void setupZenConfig() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index f128b4e2de2b..3f3b99692e9c 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -34,9 +34,13 @@
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.REORDER_TASKS" />
<application android:debuggable="true"
android:testOnly="true">
+ <uses-library android:name="android.test.mock" android:required="true" />
+
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityA" />
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityB" />
<activity android:name="com.android.server.wm.TaskStackChangedListenerTest$ActivityRequestedOrientationChange" />
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 0e30037bde6c..cac9cf69ce4d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -24,20 +24,30 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.timeout;
import android.content.Intent;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.SparseIntArray;
+import android.util.proto.ProtoOutputStream;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
+import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto;
+
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+
+import java.util.Arrays;
/**
* Tests for the {@link ActivityMetricsLaunchObserver} class.
@@ -51,6 +61,7 @@ import org.junit.Test;
public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
private ActivityMetricsLogger mActivityMetricsLogger;
private ActivityMetricsLaunchObserver mLaunchObserver;
+ private ActivityMetricsLaunchObserverRegistry mLaunchObserverRegistry;
private TestActivityStack mStack;
private TaskRecord mTask;
@@ -61,16 +72,13 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
public void setUpAMLO() throws Exception {
setupActivityTaskManagerService();
- mActivityMetricsLogger =
- new ActivityMetricsLogger(mSupervisor, mService.mContext, mService.mH.getLooper());
-
mLaunchObserver = mock(ActivityMetricsLaunchObserver.class);
- // TODO: Use ActivityMetricsLaunchObserverRegistry .
- java.lang.reflect.Field f =
- mActivityMetricsLogger.getClass().getDeclaredField("mLaunchObserver");
- f.setAccessible(true);
- f.set(mActivityMetricsLogger, mLaunchObserver);
+ // ActivityStackSupervisor always creates its own instance of ActivityMetricsLogger.
+ mActivityMetricsLogger = mSupervisor.getActivityMetricsLogger();
+
+ mLaunchObserverRegistry = mActivityMetricsLogger.getLaunchObserverRegistry();
+ mLaunchObserverRegistry.registerLaunchObserver(mLaunchObserver);
// Sometimes we need an ActivityRecord for ActivityMetricsLogger to do anything useful.
// This seems to be the easiest way to create an ActivityRecord.
@@ -81,13 +89,45 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
mActivityRecordTrampoline = new ActivityBuilder(mService).setTask(mTask).build();
}
+ @After
+ public void tearDownAMLO() throws Exception {
+ if (mLaunchObserverRegistry != null) { // Don't NPE if setUp failed.
+ mLaunchObserverRegistry.unregisterLaunchObserver(mLaunchObserver);
+ }
+ }
+
+ static class ActivityRecordMatcher implements ArgumentMatcher</*@ActivityRecordProto*/ byte[]> {
+ private final @ActivityRecordProto byte[] mExpected;
+
+ public ActivityRecordMatcher(ActivityRecord activityRecord) {
+ mExpected = activityRecordToProto(activityRecord);
+ }
+
+ public boolean matches(@ActivityRecordProto byte[] actual) {
+ return Arrays.equals(mExpected, actual);
+ }
+ }
+
+ static @ActivityRecordProto byte[] activityRecordToProto(ActivityRecord record) {
+ return ActivityMetricsLogger.convertActivityRecordToProto(record);
+ }
+
+ static @ActivityRecordProto byte[] eqProto(ActivityRecord record) {
+ return argThat(new ActivityRecordMatcher(record));
+ }
+
+ static <T> T verifyAsync(T mock) {
+ // AMLO callbacks happen on a separate thread than AML calls, so we need to use a timeout.
+ return verify(mock, timeout(100));
+ }
+
@Test
public void testOnIntentStarted() throws Exception {
Intent intent = new Intent("action 1");
mActivityMetricsLogger.notifyActivityLaunching(intent);
- verify(mLaunchObserver).onIntentStarted(eq(intent));
+ verifyAsync(mLaunchObserver).onIntentStarted(eq(intent));
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -102,7 +142,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
activityRecord);
- verify(mLaunchObserver).onIntentFailed();
+ verifyAsync(mLaunchObserver).onIntentFailed();
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -113,7 +153,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
mActivityRecord);
- verify(mLaunchObserver).onActivityLaunched(eq(mActivityRecord), anyInt());
+ verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mActivityRecord), anyInt());
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -127,7 +167,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecord.getWindowingMode(),
SystemClock.uptimeMillis());
- verify(mLaunchObserver).onActivityLaunchFinished(eq(mActivityRecord));
+ verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecord));
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -135,12 +175,12 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
public void testOnActivityLaunchCancelled() throws Exception {
testOnActivityLaunched();
- mActivityRecord.nowVisible = true;
+ mActivityRecord.mDrawn = true;
// Cannot time already-visible activities.
mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mActivityRecord);
- verify(mLaunchObserver).onActivityLaunchCancelled(eq(mActivityRecord));
+ verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mActivityRecord));
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -151,7 +191,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
mActivityRecord);
- verify(mLaunchObserver).onActivityLaunched(eq(mActivityRecord), anyInt());
+ verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mActivityRecord), anyInt());
// A second, distinct, activity launch is coalesced into the the current app launch sequence
mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS,
@@ -170,7 +210,7 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
mActivityMetricsLogger.notifyWindowsDrawn(mActivityRecordTrampoline.getWindowingMode(),
SystemClock.uptimeMillis());
- verify(mLaunchObserver).onActivityLaunchFinished(eq(mActivityRecordTrampoline));
+ verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mActivityRecordTrampoline));
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -178,13 +218,26 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase {
public void testOnActivityLaunchCancelledTrampoline() throws Exception {
testOnActivityLaunchedTrampoline();
- mActivityRecordTrampoline.nowVisible = true;
+ mActivityRecordTrampoline.mDrawn = true;
// Cannot time already-visible activities.
mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
mActivityRecordTrampoline);
- verify(mLaunchObserver).onActivityLaunchCancelled(eq(mActivityRecordTrampoline));
+ verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mActivityRecordTrampoline));
verifyNoMoreInteractions(mLaunchObserver);
}
+
+ @Test
+ public void testActivityRecordProtoIsNotTooBig() throws Exception {
+ // The ActivityRecordProto must not be too big, otherwise converting it at runtime
+ // will become prohibitively expensive.
+ assertWithMessage("mActivityRecord: %s", mActivityRecord).
+ that(activityRecordToProto(mActivityRecord).length).
+ isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
+
+ assertWithMessage("mActivityRecordTrampoline: %s", mActivityRecordTrampoline).
+ that(activityRecordToProto(mActivityRecordTrampoline).length).
+ isAtMost(ActivityMetricsLogger.LAUNCH_OBSERVER_ACTIVITY_RECORD_PROTO_CHUNK_SIZE);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
index 78a67d212f24..f7b5d26ac87e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -18,15 +18,8 @@ package com.android.server.wm;
import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
-import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
-import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -36,9 +29,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
import static com.google.common.truth.Truth.assertThat;
@@ -53,12 +43,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.ArgumentMatchers.eq;
-import android.app.ActivityOptions;
import android.app.WaitResult;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.graphics.Rect;
-import android.os.Build;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.MediumTest;
@@ -66,8 +51,6 @@ import androidx.test.filters.MediumTest;
import org.junit.Before;
import org.junit.Test;
-import java.util.ArrayList;
-
/**
* Tests for the {@link ActivityStackSupervisor} class.
*
@@ -127,7 +110,7 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase {
assertThat(mSupervisor.mWaitingActivityLaunched).isEmpty();
assertEquals(deliverToTopWait.result, START_DELIVERED_TO_TOP);
- assertEquals(deliverToTopWait.who, firstActivity.realActivity);
+ assertEquals(deliverToTopWait.who, firstActivity.mActivityComponent);
}
}
}
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 0da0b247b60c..048384e9536e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -233,7 +233,7 @@ public class ActivityStackTests extends ActivityTestsBase {
.setStack(mStack)
.setUid(0)
.build();
- final TaskRecord task = r.getTask();
+ final TaskRecord task = r.getTaskRecord();
// Overlay must be for a different user to prevent recognizing a matching top activity
final ActivityRecord taskOverlay = new ActivityBuilder(mService).setTask(task)
.setUid(UserHandle.PER_USER_RANGE * 2).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index d78fbcd4571a..5c918b4c8bfe 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -113,6 +113,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
private static final int FAKE_REAL_CALLING_UID = 667;
private static final String FAKE_CALLING_PACKAGE = "com.whatever.dude";
private static final int UNIMPORTANT_UID = 12345;
+ private static final int UNIMPORTANT_UID2 = 12346;
@Before
public void setUp() throws Exception {
@@ -243,7 +244,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
final ActivityRecord source = builder.build();
if (!containsConditions(preconditions, PRECONDITION_NO_INTENT_COMPONENT)) {
- intent.setComponent(source.realActivity);
+ intent.setComponent(source.mActivityComponent);
}
if (containsConditions(preconditions, PRECONDITION_DISALLOW_APP_SWITCHING)) {
@@ -262,11 +263,11 @@ public class ActivityStarterTests extends ActivityTestsBase {
PRECONDITION_ACTIVITY_SUPPORTS_INTENT_EXCEPTION)) {
doAnswer((inv) -> {
throw new RemoteException();
- }).when(packageManager).activitySupportsIntent(eq(source.realActivity), eq(intent),
- any());
+ }).when(packageManager).activitySupportsIntent(
+ eq(source.mActivityComponent), eq(intent), any());
} else {
doReturn(!containsConditions(preconditions, PRECONDITION_NO_VOICE_SESSION_SUPPORT))
- .when(packageManager).activitySupportsIntent(eq(source.realActivity),
+ .when(packageManager).activitySupportsIntent(eq(source.mActivityComponent),
eq(intent), any());
}
} catch (RemoteException e) {
@@ -430,7 +431,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
.setCreateTask(true)
.build();
- focusActivity.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ focusActivity.getActivityStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
final ActivityRecord reusableActivity = new ActivityBuilder(mService)
.setCreateTask(true)
@@ -438,10 +439,10 @@ public class ActivityStarterTests extends ActivityTestsBase {
// Create reusable activity after entering split-screen so that it is the top secondary
// stack.
- reusableActivity.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ reusableActivity.getActivityStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
// Set focus back to primary.
- final ActivityStack focusStack = focusActivity.getStack();
+ final ActivityStack focusStack = focusActivity.getActivityStack();
focusStack.moveToFront("testSplitScreenDeliverToTop");
doReturn(reusableActivity).when(mRootActivityContainer).findTask(any(), anyInt());
@@ -467,14 +468,14 @@ public class ActivityStarterTests extends ActivityTestsBase {
.setCreateTask(true)
.build();
- reusableActivity.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ reusableActivity.getActivityStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
final ActivityRecord focusActivity = new ActivityBuilder(mService)
.setCreateTask(true)
.build();
// Enter split-screen. Primary stack should have focus.
- focusActivity.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ focusActivity.getActivityStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
doReturn(reusableActivity).when(mRootActivityContainer).findTask(any(), anyInt());
@@ -561,8 +562,10 @@ public class ActivityStarterTests extends ActivityTestsBase {
public void testBackgroundActivityStartsAllowed_noStartsAborted() {
doReturn(true).when(mService).isBackgroundActivityStartsEnabled();
- runAndVerifyBackgroundActivityStartsSubtest("allowed_noStartsAborted",
- false, UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1, false, false);
+ runAndVerifyBackgroundActivityStartsSubtest("allowed_noStartsAborted", false,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ false, false);
}
/**
@@ -573,8 +576,11 @@ public class ActivityStarterTests extends ActivityTestsBase {
public void testBackgroundActivityStartsDisallowed_unsupportedStartsAborted() {
doReturn(false).when(mService).isBackgroundActivityStartsEnabled();
- runAndVerifyBackgroundActivityStartsSubtest("disallowed_unsupportedUsecase_aborted",
- true, UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1, false, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_unsupportedUsecase_aborted", true,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ false, false);
}
/**
@@ -586,44 +592,77 @@ public class ActivityStarterTests extends ActivityTestsBase {
public void testBackgroundActivityStartsDisallowed_supportedStartsNotAborted() {
doReturn(false).when(mService).isBackgroundActivityStartsEnabled();
- runAndVerifyBackgroundActivityStartsSubtest("disallowed_rootUid_notAborted",
- false, Process.ROOT_UID, false, PROCESS_STATE_TOP + 1, false, false);
- runAndVerifyBackgroundActivityStartsSubtest("disallowed_systemUid_notAborted",
- false, Process.SYSTEM_UID, false, PROCESS_STATE_TOP + 1, false, false);
- runAndVerifyBackgroundActivityStartsSubtest("disallowed_hasVisibleWindow_notAborted",
- false, UNIMPORTANT_UID, true, PROCESS_STATE_TOP + 1, false, false);
- runAndVerifyBackgroundActivityStartsSubtest("disallowed_processStateTop_notAborted",
- false, UNIMPORTANT_UID, false, PROCESS_STATE_TOP, false, false);
- runAndVerifyBackgroundActivityStartsSubtest("disallowed_hasForegroundActivities_notAborted",
- false, UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1, true, false);
- runAndVerifyBackgroundActivityStartsSubtest("disallowed_callerIsRecents_notAborted",
- false, UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1, false, true);
+ runAndVerifyBackgroundActivityStartsSubtest("disallowed_rootUid_notAborted", false,
+ Process.ROOT_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ false, false);
+ runAndVerifyBackgroundActivityStartsSubtest("disallowed_systemUid_notAborted", false,
+ Process.SYSTEM_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ false, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_callingUidHasVisibleWindow_notAborted", false,
+ UNIMPORTANT_UID, true, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ false, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_callingUidProcessStateTop_notAborted", false,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ false, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_realCallingUidHasVisibleWindow_notAborted", false,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, true, PROCESS_STATE_TOP + 1,
+ false, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_realCallingUidProcessStateTop_notAborted", false,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP,
+ false, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_hasForegroundActivities_notAborted", false,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ true, false);
+ runAndVerifyBackgroundActivityStartsSubtest(
+ "disallowed_callerIsRecents_notAborted", false,
+ UNIMPORTANT_UID, false, PROCESS_STATE_TOP + 1,
+ UNIMPORTANT_UID2, false, PROCESS_STATE_TOP + 1,
+ false, true);
}
private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
- int testCallingUid, boolean hasVisibleWindow, int procState,
+ int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState,
+ int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState,
boolean hasForegroundActivities, boolean callerIsRecents) {
// window visibility
- doReturn(hasVisibleWindow).when(mService.mWindowManager).isAnyWindowVisibleForUid(
- testCallingUid);
+ doReturn(callingUidHasVisibleWindow).when(mService.mWindowManager).isAnyWindowVisibleForUid(
+ callingUid);
+ doReturn(realCallingUidHasVisibleWindow).when(mService.mWindowManager)
+ .isAnyWindowVisibleForUid(realCallingUid);
// process importance
- doReturn(procState).when(mService).getUidStateLocked(testCallingUid);
+ doReturn(callingUidProcState).when(mService).getUidStateLocked(callingUid);
+ doReturn(realCallingUidProcState).when(mService).getUidStateLocked(realCallingUid);
// foreground activities
final IApplicationThread caller = mock(IApplicationThread.class);
final ApplicationInfo ai = new ApplicationInfo();
- ai.uid = testCallingUid;
+ ai.uid = callingUid;
final WindowProcessController callerApp =
- new WindowProcessController(mService, ai, null, testCallingUid, -1, null, null);
+ new WindowProcessController(mService, ai, null, callingUid, -1, null, null);
callerApp.setHasForegroundActivities(hasForegroundActivities);
doReturn(callerApp).when(mService).getProcessController(caller);
// caller is recents
RecentTasks recentTasks = mock(RecentTasks.class);
mService.mStackSupervisor.setRecentTasks(recentTasks);
- doReturn(callerIsRecents).when(recentTasks).isCallerRecents(testCallingUid);
+ doReturn(callerIsRecents).when(recentTasks).isCallerRecents(callingUid);
final ActivityOptions options = spy(ActivityOptions.makeBasic());
- ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK).setCaller(caller)
- .setCallingUid(testCallingUid).setActivityOptions(new SafeActivityOptions(options));
+ ActivityStarter starter = prepareStarter(FLAG_ACTIVITY_NEW_TASK)
+ .setCaller(caller)
+ .setCallingUid(callingUid)
+ .setRealCallingUid(realCallingUid)
+ .setActivityOptions(new SafeActivityOptions(options));
final int result = starter.setReason("testBackgroundActivityStarts_" + name).execute();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index ead9731782e8..3a56419f67ae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -34,7 +34,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
@@ -403,11 +402,10 @@ class ActivityTestsBase {
doReturn(true).when(this).isBackgroundActivityStartsEnabled();
}
- void setActivityManagerService(IntentFirewall intentFirewall,
- PendingIntentController intentController, ActivityManagerInternal amInternal,
- WindowManagerService wm) {
+ void setup(IntentFirewall intentFirewall, PendingIntentController intentController,
+ ActivityManagerInternal amInternal, WindowManagerService wm, Looper looper) {
mAmInternal = amInternal;
- setActivityManagerService(intentFirewall, intentController);
+ initialize(intentFirewall, intentController, looper);
initRootActivityContainerMocks(wm);
setWindowManager(wm);
}
@@ -517,8 +515,8 @@ class ActivityTestsBase {
mWindowManager = prepareMockWindowManager();
mUgmInternal = mock(UriGrantsManagerInternal.class);
- atm.setActivityManagerService(mIntentFirewall, mPendingIntentController,
- new LocalService(), mWindowManager);
+ atm.setup(mIntentFirewall, mPendingIntentController, new LocalService(), mWindowManager,
+ testInjector.mHandlerThread.getLooper());
mActivityTaskManager = atm;
mAtmInternal = atm.mInternal;
diff --git a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
index a9071612a725..5556a150cf3a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingAppWindowTokenRegistryTest.java
@@ -19,12 +19,12 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions;
+
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.FlakyTest;
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 5e12a950c560..5e12a950c560 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 19d18cab931e..577859cf2107 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -24,13 +24,14 @@ import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.spy;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index 4522494349a3..dcfb8797eaba 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -20,11 +20,12 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.SurfaceControl.Transaction;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.verify;
import android.view.SurfaceControl;
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 99abbf7b1f3a..0ee532d0b075 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -34,14 +34,15 @@ import static android.view.WindowManager.TRANSIT_UNSET;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
import android.graphics.Point;
import android.graphics.Rect;
@@ -118,7 +119,8 @@ public class AppWindowTokenTests extends WindowTestsBase {
assertEquals(window1, mToken.findMainWindow());
window1.mAnimatingExit = true;
assertEquals(window1, mToken.findMainWindow());
- final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, mToken, "window2");
+ final WindowState window2 = createWindow(null, TYPE_APPLICATION_STARTING, mToken,
+ "window2");
assertEquals(window2, mToken.findMainWindow());
mToken.removeImmediately();
}
@@ -156,7 +158,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
mWm.updateOrientationFromAppTokens(mDisplayContent.getOverrideConfiguration(), null,
mDisplayContent.getDisplayId());
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mDisplayContent.getLastOrientation());
- appWindow.resizeReported = false;
+ appWindow.mResizeReported = false;
// Update the orientation to perform 180 degree rotation and check that resize was reported.
mToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
@@ -164,7 +166,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
mDisplayContent.getDisplayId());
mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation());
- assertTrue(appWindow.resizeReported);
+ assertTrue(appWindow.mResizeReported);
appWindow.removeImmediately();
}
@@ -185,11 +187,11 @@ public class AppWindowTokenTests extends WindowTestsBase {
// Set initial orientation and update.
performRotation(spiedRotation, Surface.ROTATION_90);
- appWindow.resizeReported = false;
+ appWindow.mResizeReported = false;
// Update the rotation to perform 180 degree rotation and check that resize was reported.
performRotation(spiedRotation, Surface.ROTATION_270);
- assertTrue(appWindow.resizeReported);
+ assertTrue(appWindow.mResizeReported);
appWindow.removeImmediately();
}
@@ -221,7 +223,8 @@ public class AppWindowTokenTests extends WindowTestsBase {
// Can not specify orientation if app isn't visible even though it fills parent.
assertEquals(SCREEN_ORIENTATION_UNSET, mToken.getOrientation());
// Can specify orientation if the current orientation candidate is orientation behind.
- assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mToken.getOrientation(SCREEN_ORIENTATION_BEHIND));
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE,
+ mToken.getOrientation(SCREEN_ORIENTATION_BEHIND));
}
@Test
@@ -247,7 +250,8 @@ public class AppWindowTokenTests extends WindowTestsBase {
// Finish relaunching and ensure flag is now not reported
mToken.finishRelaunching();
- assertFalse(mToken.containsShowWhenLockedWindow() || mToken.containsDismissKeyguardWindow());
+ assertFalse(
+ mToken.containsShowWhenLockedWindow() || mToken.containsDismissKeyguardWindow());
}
@Test
@@ -331,7 +335,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
public void testTransferStartingWindowWhileCreating() {
final WindowTestUtils.TestAppWindowToken token1 = createIsolatedTestAppWindowToken();
final WindowTestUtils.TestAppWindowToken token2 = createIsolatedTestAppWindowToken();
- ((TestWindowManagerPolicy) token1.mService.mPolicy).setRunnableWhenAddingSplashScreen(
+ ((TestWindowManagerPolicy) token1.mWmService.mPolicy).setRunnableWhenAddingSplashScreen(
() -> {
// Surprise, ...! Transfer window in the middle of the creation flow.
token2.addStartingWindow(mPackageName,
diff --git a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
index 1c5391ed3a6c..1c5391ed3a6c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/BoundsAnimationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BoundsAnimationControllerTests.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index a6415d1f2b1f..ee1c8dfdd319 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -16,16 +16,17 @@
package com.android.server.wm;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 43e10f0a5f06..3b8d71dd8176 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -29,6 +29,10 @@ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
@@ -39,10 +43,6 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
import android.annotation.SuppressLint;
import android.content.res.Configuration;
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayPolicyInsetsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java
index 18bd2e45acd4..6767465f838c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayPolicyInsetsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyInsetsTests.java
@@ -28,14 +28,11 @@ import android.platform.test.annotations.Presubmit;
import android.view.DisplayInfo;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
-import org.junit.runner.RunWith;
-@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
public class DisplayPolicyInsetsTests extends DisplayPolicyTestsBase {
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index a91c5e79ccfc..b94f472965ab 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -46,15 +46,12 @@ import android.view.DisplayInfo;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 07d5fea334cd..8349ac7fc62c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -42,12 +42,9 @@ import android.platform.test.annotations.Presubmit;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
-import org.junit.runner.RunWith;
-@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
public class DisplayPolicyTests extends WindowTestsBase {
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index 1d63c57e6cfe..1d63c57e6cfe 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
new file mode 100644
index 000000000000..e9889948c341
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -0,0 +1,823 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atMost;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.PowerManagerInternal;
+import android.os.SystemClock;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.view.Surface;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.LocalServices;
+import com.android.server.UiThread;
+import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test class for {@link DisplayRotation}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:DisplayRotationTests
+ */
+@SmallTest
+@Presubmit
+@FlakyTest(detail = "Confirm stable in post-submit before removing")
+public class DisplayRotationTests {
+ private static final long UI_HANDLER_WAIT_TIMEOUT_MS = 50;
+
+ private StatusBarManagerInternal mPreviousStatusBarManagerInternal;
+
+ private WindowManagerService mMockWm;
+ private DisplayContent mMockDisplayContent;
+ private DisplayPolicy mMockDisplayPolicy;
+ private Context mMockContext;
+ private Resources mMockRes;
+ private SensorManager mMockSensorManager;
+ private Sensor mFakeSensor;
+ private DisplayWindowSettings mMockDisplayWindowSettings;
+ private ContentResolver mMockResolver;
+ private FakeSettingsProvider mFakeSettingsProvider;
+ private StatusBarManagerInternal mMockStatusBarManagerInternal;
+
+ // Fields below are callbacks captured from test target.
+ private ContentObserver mShowRotationSuggestionsObserver;
+ private ContentObserver mAccelerometerRotationObserver;
+ private ContentObserver mUserRotationObserver;
+ private SensorEventListener mOrientationSensorListener;
+
+ private DisplayRotationBuilder mBuilder;
+
+ private DisplayRotation mTarget;
+
+ @Before
+ public void setUp() {
+ FakeSettingsProvider.clearSettingsProvider();
+
+ mMockWm = mock(WindowManagerService.class);
+ mMockWm.mPowerManagerInternal = mock(PowerManagerInternal.class);
+
+ mPreviousStatusBarManagerInternal = LocalServices.getService(
+ StatusBarManagerInternal.class);
+ LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+ mMockStatusBarManagerInternal = mock(StatusBarManagerInternal.class);
+ LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal);
+
+ mBuilder = new DisplayRotationBuilder();
+ }
+
+ @After
+ public void tearDown() {
+ LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
+ if (mPreviousStatusBarManagerInternal != null) {
+ LocalServices.addService(StatusBarManagerInternal.class,
+ mPreviousStatusBarManagerInternal);
+ mPreviousStatusBarManagerInternal = null;
+ }
+ }
+
+ // ================================
+ // Display Settings Related Tests
+ // ================================
+ @Test
+ public void testLocksUserRotation_LockRotation_DefaultDisplay() throws Exception {
+ mBuilder.build();
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+ assertEquals(Surface.ROTATION_180, mTarget.getUserRotation());
+
+ assertEquals(0, Settings.System.getInt(mMockResolver,
+ Settings.System.ACCELEROMETER_ROTATION));
+ assertEquals(Surface.ROTATION_180, Settings.System.getInt(mMockResolver,
+ Settings.System.USER_ROTATION));
+ }
+
+ @Test
+ public void testPersistsUserRotation_LockRotation_NonDefaultDisplay() throws Exception {
+ mBuilder.mIsDefaultDisplay = false;
+
+ mBuilder.build();
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+ assertEquals(Surface.ROTATION_180, mTarget.getUserRotation());
+
+ verify(mMockDisplayWindowSettings).setUserRotation(mMockDisplayContent,
+ WindowManagerPolicy.USER_ROTATION_LOCKED, Surface.ROTATION_180);
+ }
+
+ @Test
+ public void testPersistUserRotation_UnlockRotation_DefaultDisplay() throws Exception {
+ mBuilder.build();
+
+ thawRotation();
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+
+ assertEquals(1, Settings.System.getInt(mMockResolver,
+ Settings.System.ACCELEROMETER_ROTATION));
+ }
+
+ @Test
+ public void testPersistsUserRotation_UnlockRotation_NonDefaultDisplay() throws Exception {
+ mBuilder.mIsDefaultDisplay = false;
+
+ mBuilder.build();
+
+ thawRotation();
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+
+ verify(mMockDisplayWindowSettings).setUserRotation(same(mMockDisplayContent),
+ eq(WindowManagerPolicy.USER_ROTATION_FREE), anyInt());
+ }
+
+ @Test
+ public void testPersistsFixedToUserRotation() throws Exception {
+ mBuilder.build();
+
+ mTarget.setFixedToUserRotation(true);
+
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, true);
+
+ reset(mMockDisplayWindowSettings);
+ mTarget.setFixedToUserRotation(false);
+
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, false);
+ }
+
+ // ========================================
+ // Tests for User Rotation based Rotation
+ // ========================================
+ @Test
+ public void testReturnsUserRotation_UserRotationLocked_NoAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsUserRotation_UserRotationLocked_CompatibleAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsSidesays_UserRotationLocked_IncompatibleAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ final int rotation = mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, Surface.ROTATION_90);
+ assertTrue("Rotation should be sideways, but it's "
+ + Surface.rotationToString(rotation),
+ rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+ }
+
+ // =================================
+ // Tests for Sensor based Rotation
+ // =================================
+ private void verifyOrientationListenerRegistration(int numOfInvocation) {
+ final ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass(
+ SensorEventListener.class);
+ verify(mMockSensorManager, times(numOfInvocation)).registerListener(
+ listenerCaptor.capture(),
+ same(mFakeSensor),
+ anyInt(),
+ any());
+ if (numOfInvocation > 0) {
+ mOrientationSensorListener = listenerCaptor.getValue();
+ }
+ }
+
+ @Test
+ public void testNotEnablesSensor_AutoRotationNotSupported() throws Exception {
+ mBuilder.setSupportAutoRotation(false).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ScreenNotOn() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(false);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_NotAwake() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(false);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_KeyguardNotDrawnCompletely() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(false);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_WindowManagerNotDrawnCompletely() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(false);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_FixedUserRotation() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.setFixedToUserRotation(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ @Test
+ public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(0);
+ }
+
+ private void enableOrientationSensor() {
+ when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
+ when(mMockDisplayPolicy.isAwake()).thenReturn(true);
+ when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
+ when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
+ mTarget.updateOrientationListener();
+ verifyOrientationListenerRegistration(1);
+ }
+
+ private SensorEvent createSensorEvent(int rotation) throws Exception {
+ final Constructor<SensorEvent> constructor =
+ SensorEvent.class.getDeclaredConstructor(int.class);
+ constructor.setAccessible(true);
+ final SensorEvent event = constructor.newInstance(1);
+ event.sensor = mFakeSensor;
+ event.values[0] = rotation;
+ event.timestamp = SystemClock.elapsedRealtimeNanos();
+ return event;
+ }
+
+ @Test
+ public void testReturnsSensorRotation_RotationThawed() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ private boolean waitForUiHandler() throws Exception {
+ final CountDownLatch latch = new CountDownLatch(1);
+ UiThread.getHandler().post(latch::countDown);
+ return latch.await(UI_HANDLER_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+
+ @Test
+ public void testUpdatesRotationWhenSensorUpdates_RotationThawed() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertTrue(waitForUiHandler());
+
+ verify(mMockWm).updateRotation(false, false);
+ }
+
+ @Test
+ public void testNotifiesChoiceWhenSensorUpdates_RotationLocked() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ freezeRotation(Surface.ROTATION_270);
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90));
+ assertTrue(waitForUiHandler());
+
+ verify(mMockStatusBarManagerInternal).onProposedRotationChanged(Surface.ROTATION_90, true);
+ }
+
+ @Test
+ public void testReturnsCompatibleRotation_SensorEnabled_RotationThawed() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ thawRotation();
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+
+ final int rotation = mTarget.rotationForOrientation(SCREEN_ORIENTATION_LANDSCAPE,
+ Surface.ROTATION_0);
+ assertTrue("Rotation should be sideways but it's "
+ + Surface.rotationToString(rotation),
+ rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
+ }
+
+ @Test
+ public void testReturnsUserRotation_SensorEnabled_RotationLocked() throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ freezeRotation(Surface.ROTATION_270);
+
+ enableOrientationSensor();
+
+ mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+
+ assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ // =================================
+ // Tests for Policy based Rotation
+ // =================================
+ @Test
+ public void testReturnsUserRotation_ForceDefaultRotation() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
+ public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
+ public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception {
+ mBuilder.build();
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
+ .thenReturn(true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+
+ assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
+ Surface.ROTATION_180));
+ }
+
+ @Test
+ public void testReturnsLidOpenRotation_LidOpen() throws Exception {
+ mBuilder.setLidOpenRotation(Surface.ROTATION_90).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.getLidState()).thenReturn(
+ WindowManagerPolicy.WindowManagerFuncs.LID_OPEN);
+
+ freezeRotation(Surface.ROTATION_270);
+
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ @Test
+ public void testReturnsCarDockRotation_CarDockedMode() throws Exception {
+ mBuilder.setCarDockRotation(Surface.ROTATION_270).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_CAR);
+
+ freezeRotation(Surface.ROTATION_90);
+
+ assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsDeskDockRotation_DeskDockedMode() throws Exception {
+ mBuilder.setDeskDockRotation(Surface.ROTATION_270).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_DESK);
+
+ freezeRotation(Surface.ROTATION_90);
+
+ assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90));
+ }
+
+ @Test
+ public void testReturnsUserRotation_FixedToUserRotation_IgnoreIncompatibleAppRequest()
+ throws Exception {
+ mBuilder.build();
+ configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
+
+ mTarget.setFixedToUserRotation(true);
+
+ freezeRotation(Surface.ROTATION_180);
+
+ final int rotation = mTarget.rotationForOrientation(
+ ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90);
+ assertEquals(Surface.ROTATION_180, rotation);
+ }
+
+ @Test
+ public void testReturnsUserRotation_NonDefaultDisplay() throws Exception {
+ mBuilder.setIsDefaultDisplay(false).build();
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+
+ freezeRotation(Surface.ROTATION_90);
+
+ assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation(
+ SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
+ }
+
+ /**
+ * Call {@link DisplayRotation#configure(int, int, int, int)} to configure {@link #mTarget}
+ * according to given parameters.
+ */
+ private void configureDisplayRotation(int displayOrientation, boolean isCar, boolean isTv) {
+ final int width;
+ final int height;
+ switch (displayOrientation) {
+ case SCREEN_ORIENTATION_LANDSCAPE:
+ width = 1920;
+ height = 1080;
+ break;
+ case SCREEN_ORIENTATION_PORTRAIT:
+ width = 1080;
+ height = 1920;
+ break;
+ default:
+ throw new IllegalArgumentException("displayOrientation needs to be either landscape"
+ + " or portrait, but we got "
+ + ActivityInfo.screenOrientationToString(displayOrientation));
+ }
+
+ final PackageManager mockPackageManager = mock(PackageManager.class);
+ when(mMockContext.getPackageManager()).thenReturn(mockPackageManager);
+ when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE))
+ .thenReturn(isCar);
+ when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
+ .thenReturn(isTv);
+
+ final int shortSizeDp = (isCar || isTv) ? 540 : 720;
+ final int longSizeDp = 960;
+ mTarget.configure(width, height, shortSizeDp, longSizeDp);
+ }
+
+ private void freezeRotation(int rotation) {
+ mTarget.freezeRotation(rotation);
+
+ if (mTarget.isDefaultDisplay) {
+ mAccelerometerRotationObserver.onChange(false);
+ mUserRotationObserver.onChange(false);
+ }
+ }
+
+ private void thawRotation() {
+ mTarget.thawRotation();
+
+ if (mTarget.isDefaultDisplay) {
+ mAccelerometerRotationObserver.onChange(false);
+ mUserRotationObserver.onChange(false);
+ }
+ }
+
+ private class DisplayRotationBuilder {
+ private boolean mIsDefaultDisplay = true;
+ private boolean mSupportAutoRotation = true;
+
+ private int mLidOpenRotation = WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
+ private int mCarDockRotation;
+ private int mDeskDockRotation;
+ private int mUndockedHdmiRotation;
+
+ private DisplayRotationBuilder setIsDefaultDisplay(boolean isDefaultDisplay) {
+ mIsDefaultDisplay = isDefaultDisplay;
+ return this;
+ }
+
+ private DisplayRotationBuilder setSupportAutoRotation(boolean supportAutoRotation) {
+ mSupportAutoRotation = supportAutoRotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setLidOpenRotation(int rotation) {
+ mLidOpenRotation = rotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setCarDockRotation(int rotation) {
+ mCarDockRotation = rotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setDeskDockRotation(int rotation) {
+ mDeskDockRotation = rotation;
+ return this;
+ }
+
+ private DisplayRotationBuilder setUndockedHdmiRotation(int rotation) {
+ mUndockedHdmiRotation = rotation;
+ return this;
+ }
+
+ private void captureObservers() {
+ ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(
+ ContentObserver.class);
+ verify(mMockResolver, atMost(1)).registerContentObserver(
+ eq(Settings.Secure.getUriFor(Settings.Secure.SHOW_ROTATION_SUGGESTIONS)),
+ anyBoolean(),
+ captor.capture(),
+ anyInt());
+ if (!captor.getAllValues().isEmpty()) {
+ mShowRotationSuggestionsObserver = captor.getValue();
+ }
+
+ captor = ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mMockResolver, atMost(1)).registerContentObserver(
+ eq(Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION)),
+ anyBoolean(),
+ captor.capture(),
+ anyInt());
+ if (!captor.getAllValues().isEmpty()) {
+ mAccelerometerRotationObserver = captor.getValue();
+ }
+
+ captor = ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mMockResolver, atMost(1)).registerContentObserver(
+ eq(Settings.System.getUriFor(Settings.System.USER_ROTATION)),
+ anyBoolean(),
+ captor.capture(),
+ anyInt());
+ if (!captor.getAllValues().isEmpty()) {
+ mUserRotationObserver = captor.getValue();
+ }
+ }
+
+ private Sensor createSensor(int type) throws Exception {
+ Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
+ constr.setAccessible(true);
+ Sensor sensor = constr.newInstance();
+
+ setSensorType(sensor, type);
+ setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type);
+ setSensorField(sensor, "mVendor", "Mock Vendor");
+ setSensorField(sensor, "mVersion", 1);
+ setSensorField(sensor, "mHandle", -1);
+ setSensorField(sensor, "mMaxRange", 10);
+ setSensorField(sensor, "mResolution", 1);
+ setSensorField(sensor, "mPower", 1);
+ setSensorField(sensor, "mMinDelay", 1000);
+ setSensorField(sensor, "mMaxDelay", 1000000000);
+ setSensorField(sensor, "mFlags", 0);
+ setSensorField(sensor, "mId", -1);
+
+ return sensor;
+ }
+
+ private void setSensorType(Sensor sensor, int type) throws Exception {
+ Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE);
+ setter.setAccessible(true);
+ setter.invoke(sensor, type);
+ }
+
+ private void setSensorField(Sensor sensor, String fieldName, Object value)
+ throws Exception {
+ Field field = Sensor.class.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ field.set(sensor, value);
+ }
+
+ private int convertRotationToDegrees(@Surface.Rotation int rotation) {
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ return 0;
+ case Surface.ROTATION_90:
+ return 90;
+ case Surface.ROTATION_180:
+ return 180;
+ case Surface.ROTATION_270:
+ return 270;
+ default:
+ return -1;
+ }
+ }
+
+ private void build() throws Exception {
+ mMockContext = mock(Context.class);
+
+ mMockDisplayContent = mock(WindowTestUtils.TestDisplayContent.class);
+ mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay;
+
+ mMockDisplayPolicy = mock(DisplayPolicy.class);
+
+ mMockRes = mock(Resources.class);
+ when(mMockContext.getResources()).thenReturn((mMockRes));
+ when(mMockRes.getBoolean(com.android.internal.R.bool.config_supportAutoRotation))
+ .thenReturn(mSupportAutoRotation);
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_lidOpenRotation))
+ .thenReturn(convertRotationToDegrees(mLidOpenRotation));
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_carDockRotation))
+ .thenReturn(convertRotationToDegrees(mCarDockRotation));
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_deskDockRotation))
+ .thenReturn(convertRotationToDegrees(mDeskDockRotation));
+ when(mMockRes.getInteger(com.android.internal.R.integer.config_undockedHdmiRotation))
+ .thenReturn(convertRotationToDegrees(mUndockedHdmiRotation));
+
+ mMockSensorManager = mock(SensorManager.class);
+ when(mMockContext.getSystemService(Context.SENSOR_SERVICE))
+ .thenReturn(mMockSensorManager);
+ mFakeSensor = createSensor(Sensor.TYPE_DEVICE_ORIENTATION);
+ when(mMockSensorManager.getSensorList(Sensor.TYPE_DEVICE_ORIENTATION)).thenReturn(
+ Collections.singletonList(mFakeSensor));
+
+ mMockResolver = mock(ContentResolver.class);
+ when(mMockContext.getContentResolver()).thenReturn(mMockResolver);
+ mFakeSettingsProvider = new FakeSettingsProvider();
+ when(mMockResolver.acquireProvider(Settings.AUTHORITY))
+ .thenReturn(mFakeSettingsProvider.getIContentProvider());
+
+ mMockDisplayWindowSettings = mock(DisplayWindowSettings.class);
+ mTarget = new DisplayRotation(mMockWm, mMockDisplayContent, mMockDisplayPolicy,
+ mMockDisplayWindowSettings, mMockContext, new Object());
+
+ captureObservers();
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index b823e706a586..8e881b54c422 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -21,13 +21,19 @@ import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Matchers.eq;
import android.app.WindowConfiguration;
import android.platform.test.annotations.Presubmit;
@@ -378,6 +384,33 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
mSecondaryDisplay.getDisplayRotation().getUserRotation());
}
+ @Test
+ public void testNotFixedToUserRotationByDefault() {
+ mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
+ Surface.ROTATION_0);
+
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ mPrimaryDisplay = spy(mPrimaryDisplay);
+ when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+
+ mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(false));
+ }
+
+ @Test
+ public void testSetFixedToUserRotation() {
+ mTarget.setFixedToUserRotation(mPrimaryDisplay, true);
+
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ mPrimaryDisplay = spy(mPrimaryDisplay);
+ when(mPrimaryDisplay.getDisplayRotation()).thenReturn(displayRotation);
+
+ applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(true));
+ }
+
private static void assertOverscan(DisplayContent display, int left, int top, int right,
int bottom) {
final DisplayInfo info = display.getDisplayInfo();
diff --git a/services/tests/servicestests/src/com/android/server/wm/DockedStackDividerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DockedStackDividerControllerTests.java
index a04bf16eaf1c..32062080a22c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DockedStackDividerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DockedStackDividerControllerTests.java
@@ -30,12 +30,9 @@ import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
-import org.junit.runner.RunWith;
-@RunWith(AndroidJUnit4.class)
@SmallTest
@Presubmit
public class DockedStackDividerControllerTests {
diff --git a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index ad293d963f3e..f1c6eab2143d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -20,13 +20,14 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
import android.content.ClipData;
import android.graphics.PixelFormat;
diff --git a/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
index 241b987e58ba..c11e606386e6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/InsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+
import static org.junit.Assert.assertEquals;
import android.graphics.Insets;
@@ -25,14 +26,11 @@ import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.InsetsSource;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-@RunWith(AndroidJUnit4.class)
+import org.junit.Test;
+
@SmallTest
@FlakyTest(detail = "Promote once confirmed non-flaky")
@Presubmit
diff --git a/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 7505db103bbf..331622ce22a5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -20,20 +20,18 @@ import static android.view.InsetsState.TYPE_IME;
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import android.platform.test.annotations.Presubmit;
import android.view.InsetsState;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-@RunWith(AndroidJUnit4.class)
+import org.junit.Test;
+
@SmallTest
@FlakyTest(detail = "Promote once confirmed non-flaky")
@Presubmit
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index fa4898b16040..3720c8566e74 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -89,9 +89,9 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
final WindowLayout layout = new WindowLayout(0, 0, 0, 0, 0, 0, 0);
final ActivityOptions options = mock(ActivityOptions.class);
- mController.calculate(record.getTask(), layout, record, source, options,
+ mController.calculate(record.getTaskRecord(), layout, record, source, options,
new LaunchParams());
- verify(positioner, times(1)).onCalculate(eq(record.getTask()), eq(layout), eq(record),
+ verify(positioner, times(1)).onCalculate(eq(record.getTaskRecord()), eq(layout), eq(record),
eq(source), eq(options), any(), any());
}
@@ -114,7 +114,7 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
mPersister.putLaunchParams(userId, name, expected);
- mController.calculate(activity.getTask(), null /*layout*/, activity, null /*source*/,
+ mController.calculate(activity.getTaskRecord(), null /*layout*/, activity, null /*source*/,
null /*options*/, new LaunchParams());
verify(positioner, times(1)).onCalculate(any(), any(), any(), any(), any(), eq(expected),
any());
@@ -228,7 +228,7 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
final LaunchParams result = new LaunchParams();
final ActivityRecord vrActivity = new ActivityBuilder(mService).build();
- vrActivity.requestedVrComponent = vrActivity.realActivity;
+ vrActivity.requestedVrComponent = vrActivity.mActivityComponent;
// VR activities should always land on default display.
mController.calculate(null /*task*/, null /*layout*/, vrActivity /*activity*/,
@@ -412,8 +412,9 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
@Override
void getLaunchParams(TaskRecord task, ActivityRecord activity, LaunchParams params) {
- final int userId = task != null ? task.userId : activity.userId;
- final ComponentName name = task != null ? task.realActivity : activity.realActivity;
+ final int userId = task != null ? task.userId : activity.mUserId;
+ final ComponentName name = task != null
+ ? task.realActivity : activity.mActivityComponent;
params.reset();
final Map<ComponentName, LaunchParams> map = mMap.get(userId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
index 2c3c66be6248..f3a125bf79e4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java
@@ -272,6 +272,51 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase {
}
@Test
+ public void testClearsRecordInMemory() {
+ mTarget.saveTask(mTestTask);
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+ mTarget.getLaunchParams(mTestTask, null, mResult);
+
+ assertTrue("Result should be empty.", mResult.isEmpty());
+ }
+
+ @Test
+ public void testClearsWriteQueueItem() {
+ mTarget.saveTask(mTestTask);
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+ final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+ mUserFolderGetter);
+ target.onSystemReady();
+ target.onUnlockUser(TEST_USER_ID);
+
+ target.getLaunchParams(mTestTask, null, mResult);
+
+ assertTrue("Result should be empty.", mResult.isEmpty());
+ }
+
+ @Test
+ public void testClearsFile() {
+ mTarget.saveTask(mTestTask);
+ mPersisterQueue.flush();
+
+ mTarget.removeRecordForPackage(TEST_COMPONENT.getPackageName());
+
+ final LaunchParamsPersister target = new LaunchParamsPersister(mPersisterQueue, mSupervisor,
+ mUserFolderGetter);
+ target.onSystemReady();
+ target.onUnlockUser(TEST_USER_ID);
+
+ target.getLaunchParams(mTestTask, null, mResult);
+
+ assertTrue("Result should be empty.", mResult.isEmpty());
+ }
+
+
+ @Test
public void testClearsRecordInMemoryOnPackageUninstalled() {
mTarget.saveTask(mTestTask);
diff --git a/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
index 1fae317f3af8..63d9fb9c17e9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/PinnedStackControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PinnedStackControllerTest.java
@@ -18,14 +18,15 @@ package com.android.server.wm;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -46,6 +47,8 @@ import org.mockito.MockitoAnnotations;
@Presubmit
public class PinnedStackControllerTest extends WindowTestsBase {
+ private static final int SHELF_HEIGHT = 300;
+
@Mock private IPinnedStackListener mIPinnedStackListener;
@Mock private IPinnedStackListener.Stub mIPinnedStackListenerStub;
@@ -70,8 +73,6 @@ public class PinnedStackControllerTest extends WindowTestsBase {
reset(mIPinnedStackListener);
- final int SHELF_HEIGHT = 300;
-
mWm.setShelfHeight(true, SHELF_HEIGHT);
verify(mIPinnedStackListener).onShelfVisibilityChanged(true, SHELF_HEIGHT);
verify(mIPinnedStackListener).onMovementBoundsChanged(any(), any(), any(), eq(false),
diff --git a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index ee3bba73cd1e..cc6a58a81635 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -21,6 +21,10 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
@@ -28,10 +32,6 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
import android.os.Binder;
import android.os.IInterface;
diff --git a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index fa5379576e8b..ad2a708b88d9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -18,13 +18,14 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
import android.graphics.Point;
import android.graphics.Rect;
@@ -143,8 +144,9 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
@Test
public void testTimeout_scaled() throws Exception {
mWm.setAnimationScale(2, 5.0f);
- try{
- final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
+ try {
+ final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
+ "testWin");
final AnimationAdapter adapter = mController.createAnimationAdapter(win.mAppToken,
new Point(50, 100), new Rect(50, 100, 150, 150));
adapter.startAnimation(mMockLeash, mMockTransaction, mFinishedCallback);
@@ -163,7 +165,6 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
} finally {
mWm.setAnimationScale(2, 1.0f);
}
-
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 631de99dc3ad..9b18388b5305 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -16,8 +16,6 @@
package com.android.server.wm;
-import static android.app.ActivityManager.START_DELIVERED_TO_TOP;
-import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -51,7 +49,6 @@ import static org.mockito.ArgumentMatchers.contains;
import static org.mockito.ArgumentMatchers.eq;
import android.app.ActivityOptions;
-import android.app.WaitResult;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.graphics.Rect;
@@ -101,11 +98,11 @@ public class RootActivityContainerTests extends ActivityTestsBase {
public void testReplacingTaskInPinnedStack() {
final ActivityRecord firstActivity = new ActivityBuilder(mService).setCreateTask(true)
.setStack(mFullscreenStack).build();
- final TaskRecord firstTask = firstActivity.getTask();
+ final TaskRecord firstTask = firstActivity.getTaskRecord();
final ActivityRecord secondActivity = new ActivityBuilder(mService).setCreateTask(true)
.setStack(mFullscreenStack).build();
- final TaskRecord secondTask = secondActivity.getTask();
+ final TaskRecord secondTask = secondActivity.getTaskRecord();
mFullscreenStack.moveToFront("testReplacingTaskInPinnedStack");
@@ -257,7 +254,7 @@ public class RootActivityContainerTests extends ActivityTestsBase {
assertTrue(pinnedActivity.isFocusable());
// Without the overridding activity, stack should not be focusable.
- pinnedStack.removeTask(pinnedActivity.getTask(), "testFocusability",
+ pinnedStack.removeTask(pinnedActivity.getTaskRecord(), "testFocusability",
REMOVE_TASK_MODE_DESTROYING);
assertFalse(pinnedStack.isFocusable());
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
index ce5b13cab1a7..ce5b13cab1a7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/StackWindowControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index 584f2695891b..83e7ee711831 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -16,16 +16,17 @@
package com.android.server.wm;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeastOnce;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import static java.util.concurrent.TimeUnit.SECONDS;
diff --git a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index e638a6accf7c..d14f30db8e9f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -16,16 +16,17 @@
package com.android.server.wm;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index bd8cd1f37f5e..9569c0d5affa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -175,7 +175,7 @@ public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
WINDOWING_MODE_FREEFORM);
ActivityRecord source = createSourceActivity(freeformDisplay);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(source.getTask(), null /* layout */,
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(source.getTaskRecord(), null /* layout */,
null /* activity */, null /* source */, null /* options */, mCurrent, mResult));
assertEquals(freeformDisplay.mDisplayId, mResult.mPreferredDisplayId);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index 785b955863db..b996bfbf2101 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -52,8 +52,8 @@ public class TaskPositionerTests extends WindowTestsBase {
private static final boolean DEBUGGING = false;
private static final String TAG = "TaskPositionerTest";
- private final static int MOUSE_DELTA_X = 5;
- private final static int MOUSE_DELTA_Y = 5;
+ private static final int MOUSE_DELTA_X = 5;
+ private static final int MOUSE_DELTA_Y = 5;
private int mMinVisibleWidth;
private int mMinVisibleHeight;
@@ -315,7 +315,7 @@ public class TaskPositionerTests extends WindowTestsBase {
// Drag all the way to the right and see the height also shrinking.
mPositioner.resizeDrag(2000.0f, midY);
final int w = mMinVisibleWidth;
- final int h = Math.round((float)w / MIN_ASPECT);
+ final int h = Math.round((float) w / MIN_ASPECT);
assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
mPositioner.getWindowDragBounds());
@@ -428,7 +428,7 @@ public class TaskPositionerTests extends WindowTestsBase {
// Drag all the way to the right.
mPositioner.resizeDrag(2000.0f, midY);
w = mMinVisibleWidth;
- h = Math.max(Math.round((float)w * MIN_ASPECT), r.height());
+ h = Math.max(Math.round((float) w * MIN_ASPECT), r.height());
assertBoundsEquals(new Rect(r.right - w, r.top, r.right, r.top + h),
mPositioner.getWindowDragBounds());
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index 00b462954bd9..3991e06d6f96 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -18,14 +18,15 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
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.Matchers.anyInt;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import android.platform.test.annotations.Presubmit;
import android.view.InputChannel;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index 1c6afd545b1f..1c6afd545b1f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index 792e8a6f7582..792e8a6f7582 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index b0eafeeae043..b0eafeeae043 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index 946ffb60c759..946ffb60c759 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index a569b9e6dd6f..624ef9ba1653 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.server.wm;
@@ -20,14 +20,15 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.app.ActivityManager.TaskSnapshot;
import android.content.ComponentName;
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
index f01e9f0662c9..f01e9f0662c9 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 7ac331829fb1..7ac331829fb1 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
index bbf508dd1630..bbf508dd1630 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskWindowContainerControllerTests.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index 432af0d7a469..432af0d7a469 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 7b542cb4f2f7..ba81bd1c3b12 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -19,8 +19,8 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import android.annotation.Nullable;
import android.content.Context;
@@ -46,7 +46,8 @@ import java.util.function.Supplier;
class TestWindowManagerPolicy implements WindowManagerPolicy {
private final Supplier<WindowManagerService> mWmSupplier;
- boolean keyguardShowingAndNotOccluded = false;
+ int mRotationToReport = 0;
+ boolean mKeyguardShowingAndNotOccluded = false;
private Runnable mRunnableWhenAddingSplashScreen;
@@ -236,7 +237,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
@Override
public boolean isKeyguardLocked() {
- return keyguardShowingAndNotOccluded;
+ return mKeyguardShowingAndNotOccluded;
}
@Override
@@ -256,7 +257,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
@Override
public boolean isKeyguardShowingAndNotOccluded() {
- return keyguardShowingAndNotOccluded;
+ return mKeyguardShowingAndNotOccluded;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 9e22c0a86d96..612f9ad923d6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -73,7 +73,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
public void testClear() {
final AppWindowToken token = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(token);
- mDisplayContent.mUnknownAppVisibilityController.clear();;
+ mDisplayContent.mUnknownAppVisibilityController.clear();
assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index 4ea6b3901f03..d07230ef2ca3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -18,11 +18,12 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
import static junit.framework.TestCase.assertNotNull;
import static org.junit.Assert.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
import android.graphics.Bitmap;
import android.os.IBinder;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
index 3643457f061f..3643457f061f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
index 7592f1c1fca0..7592f1c1fca0 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerControllerTests.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index e59afd656420..d4a32cfc4a1d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -22,6 +22,13 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -30,13 +37,6 @@ 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.Mockito.any;
-import static org.mockito.Mockito.anyFloat;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -459,13 +459,13 @@ public class WindowContainerTests extends WindowTestsBase {
@Test
public void testGetOrientation_childSpecified() {
testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_LANDSCAPE,
- SCREEN_ORIENTATION_LANDSCAPE);
+ SCREEN_ORIENTATION_LANDSCAPE);
testGetOrientation_childSpecifiedConfig(false, SCREEN_ORIENTATION_UNSET,
- SCREEN_ORIENTATION_UNSPECIFIED);
+ SCREEN_ORIENTATION_UNSPECIFIED);
}
private void testGetOrientation_childSpecifiedConfig(boolean childVisible, int childOrientation,
- int expectedOrientation) {
+ int expectedOrientation) {
final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
final TestWindowContainer root = builder.setLayer(0).build();
root.setFillsParent(true);
@@ -704,7 +704,7 @@ public class WindowContainerTests extends WindowTestsBase {
final TestWindowContainer root = builder.build();
final TestWindowContainer child = root.addChildWindow();
- child.setBounds(new Rect(1,1,2,2));
+ child.setBounds(new Rect(1, 1, 2, 2));
final TestWindowContainer grandChild = mock(TestWindowContainer.class);
@@ -742,7 +742,7 @@ public class WindowContainerTests extends WindowTestsBase {
private static final Comparator<TestWindowContainer> SUBLAYER_COMPARATOR = (w1, w2) -> {
final int layer1 = w1.mLayer;
final int layer2 = w2.mLayer;
- if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0 )) {
+ if (layer1 < layer2 || (layer1 == layer2 && layer2 < 0)) {
// We insert the child window into the list ordered by the mLayer. For same layers,
// the negative one should go below others; the positive one should go above others.
return -1;
@@ -782,7 +782,7 @@ public class WindowContainerTests extends WindowTestsBase {
}
TestWindowContainer addChildWindow() {
- return addChildWindow(new TestWindowContainerBuilder(mService).setLayer(1));
+ return addChildWindow(new TestWindowContainerBuilder(mWmService).setLayer(1));
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
index fcde08e18a6f..4b666f538ea2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -21,9 +21,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
import android.platform.test.annotations.Presubmit;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 227eb00be7f7..b3e90debc84b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -290,7 +290,7 @@ public class WindowFrameTests extends WindowTestsBase {
w.mRequestedHeight = 300;
w.mAttrs.gravity = Gravity.RIGHT | Gravity.TOP;
w.computeFrameLw();
- assertFrame(w, 700, 0, 1000, 300);
+ assertFrame(w, 700, 0, 1000, 300);
w.mAttrs.gravity = Gravity.RIGHT | Gravity.BOTTOM;
w.computeFrameLw();
assertFrame(w, 700, 700, 1000, 1000);
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java
index 9a13efb4c58b..4a99172160f5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRule.java
@@ -21,14 +21,15 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
import android.app.ActivityManagerInternal;
import android.content.Context;
@@ -100,6 +101,7 @@ public class WindowManagerServiceRule implements TestRule {
mock(PowerManagerInternal.class));
final PowerManagerInternal pm =
LocalServices.getService(PowerManagerInternal.class);
+ doNothing().when(pm).registerLowPowerModeObserver(any());
PowerSaveState state = new PowerSaveState.Builder().build();
doReturn(state).when(pm).getLowPowerState(anyInt());
@@ -146,8 +148,8 @@ public class WindowManagerServiceRule implements TestRule {
final Display display = mService.mDisplayManager.getDisplay(DEFAULT_DISPLAY);
final DisplayWindowController dcw = new DisplayWindowController(display, mService);
- // Display creation is driven by the ActivityManagerService via ActivityStackSupervisor.
- // We emulate those steps here.
+ // Display creation is driven by the ActivityManagerService via
+ // ActivityStackSupervisor. We emulate those steps here.
mService.mRoot.createDisplayContent(display, dcw);
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
index 343d35959df4..343d35959df4 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceRuleTest.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 118ce8962259..7f7803463543 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -32,6 +32,12 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
@@ -43,11 +49,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
import android.graphics.Insets;
import android.graphics.Matrix;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index e56edabfa02f..a1b0411afcde 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static android.app.AppOpsManager.OP_NONE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat;
@@ -23,12 +26,21 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
+import android.app.ActivityManager;
+import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.Binder;
+import android.os.IBinder;
import android.view.Display;
+import android.view.IApplicationToken;
+import android.view.IWindow;
import android.view.Surface;
+import android.view.SurfaceControl.Transaction;
+import android.view.WindowManager;
import org.mockito.invocation.InvocationOnMock;
@@ -37,6 +49,7 @@ import org.mockito.invocation.InvocationOnMock;
* to WindowManager related test functionality.
*/
public class WindowTestUtils {
+ private static int sNextTaskId = 0;
/** An extension of {@link DisplayContent} to gain package scoped access. */
public static class TestDisplayContent extends DisplayContent {
@@ -54,6 +67,14 @@ public class WindowTestUtils {
return null;
}
+ /**
+ * Stubbing method of non-public parent class isn't supported, so here explicitly overrides.
+ */
+ @Override
+ DockedStackDividerController getDockedDividerController() {
+ return null;
+ }
+
/** Create a mocked default {@link DisplayContent}. */
public static TestDisplayContent create(Context context) {
final TestDisplayContent displayContent = mock(TestDisplayContent.class);
@@ -65,7 +86,7 @@ public class WindowTestUtils {
final DisplayRotation displayRotation = new DisplayRotation(
mock(WindowManagerService.class), displayContent, displayPolicy,
- context, new Object());
+ mock(DisplayWindowSettings.class), context, new Object());
displayRotation.mPortraitRotation = Surface.ROTATION_0;
displayRotation.mLandscapeRotation = Surface.ROTATION_90;
displayRotation.mUpsideDownRotation = Surface.ROTATION_180;
@@ -106,6 +127,17 @@ public class WindowTestUtils {
return controller;
}
+ /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */
+ public static Task createTaskInStack(WindowManagerService service, TaskStack stack,
+ int userId) {
+ synchronized (service.mGlobalLock) {
+ final Task newTask = new Task(sNextTaskId++, stack, userId, service, 0, false,
+ new ActivityManager.TaskDescription(), null);
+ stack.addTask(newTask, POSITION_TOP);
+ return newTask;
+ }
+ }
+
/**
* An extension of {@link TestTaskStack}, which overrides package scoped methods that would not
* normally be mocked out.
@@ -120,4 +152,233 @@ public class WindowTestUtils {
// Do nothing.
}
}
+
+ static TestAppWindowToken createTestAppWindowToken(DisplayContent dc) {
+ synchronized (dc.mWmService.mGlobalLock) {
+ return new TestAppWindowToken(dc);
+ }
+ }
+
+ /** Used so we can gain access to some protected members of the {@link AppWindowToken} class. */
+ public static class TestAppWindowToken extends AppWindowToken {
+ boolean mOnTop = false;
+ private Transaction mPendingTransactionOverride;
+
+ private TestAppWindowToken(DisplayContent dc) {
+ super(dc.mWmService, new IApplicationToken.Stub() {
+ @Override
+ public String getName() {
+ return null;
+ }
+ }, new ComponentName("", ""), false, dc, true /* fillsParent */);
+ }
+
+ TestAppWindowToken(WindowManagerService service, IApplicationToken token,
+ ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc,
+ long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers,
+ int targetSdk, int orientation, int rotationAnimationHint, int configChanges,
+ boolean launchTaskBehind, boolean alwaysFocusable, ActivityRecord activityRecord) {
+ super(service, token, activityComponent, voiceInteraction, dc,
+ inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk,
+ orientation, rotationAnimationHint, configChanges, launchTaskBehind,
+ alwaysFocusable, activityRecord);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+
+ WindowState getFirstChild() {
+ return mChildren.peekFirst();
+ }
+
+ WindowState getLastChild() {
+ return mChildren.peekLast();
+ }
+
+ int positionInParent() {
+ return getParent().mChildren.indexOf(this);
+ }
+
+ void setIsOnTop(boolean onTop) {
+ mOnTop = onTop;
+ }
+
+ @Override
+ boolean isOnTop() {
+ return mOnTop;
+ }
+
+ void setPendingTransaction(Transaction transaction) {
+ mPendingTransactionOverride = transaction;
+ }
+
+ @Override
+ public Transaction getPendingTransaction() {
+ return mPendingTransactionOverride == null
+ ? super.getPendingTransaction()
+ : mPendingTransactionOverride;
+ }
+ }
+
+ static TestWindowToken createTestWindowToken(int type, DisplayContent dc) {
+ return createTestWindowToken(type, dc, false /* persistOnEmpty */);
+ }
+
+ static TestWindowToken createTestWindowToken(int type, DisplayContent dc,
+ boolean persistOnEmpty) {
+ synchronized (dc.mWmService.mGlobalLock) {
+ return new TestWindowToken(type, dc, persistOnEmpty);
+ }
+ }
+
+ /* Used so we can gain access to some protected members of the {@link WindowToken} class */
+ public static class TestWindowToken extends WindowToken {
+
+ private TestWindowToken(int type, DisplayContent dc, boolean persistOnEmpty) {
+ super(dc.mWmService, mock(IBinder.class), type, persistOnEmpty, dc,
+ false /* ownerCanManageAppTokens */);
+ }
+
+ int getWindowsCount() {
+ return mChildren.size();
+ }
+
+ boolean hasWindow(WindowState w) {
+ return mChildren.contains(w);
+ }
+ }
+
+ /* Used so we can gain access to some protected members of the {@link Task} class */
+ public static class TestTask extends Task {
+ boolean mShouldDeferRemoval = false;
+ boolean mOnDisplayChangedCalled = false;
+ private boolean mIsAnimating = false;
+
+ TestTask(int taskId, TaskStack stack, int userId, WindowManagerService service,
+ int resizeMode, boolean supportsPictureInPicture,
+ TaskWindowContainerController controller) {
+ super(taskId, stack, userId, service, resizeMode, supportsPictureInPicture,
+ new ActivityManager.TaskDescription(), controller);
+ }
+
+ boolean shouldDeferRemoval() {
+ return mShouldDeferRemoval;
+ }
+
+ int positionInParent() {
+ return getParent().mChildren.indexOf(this);
+ }
+
+ @Override
+ void onDisplayChanged(DisplayContent dc) {
+ super.onDisplayChanged(dc);
+ mOnDisplayChangedCalled = true;
+ }
+
+ @Override
+ boolean isSelfAnimating() {
+ return mIsAnimating;
+ }
+
+ void setLocalIsAnimating(boolean isAnimating) {
+ mIsAnimating = isAnimating;
+ }
+ }
+
+ /**
+ * Used so we can gain access to some protected members of {@link TaskWindowContainerController}
+ * class.
+ */
+ public static class TestTaskWindowContainerController extends TaskWindowContainerController {
+
+ static final TaskWindowContainerListener NOP_LISTENER = new TaskWindowContainerListener() {
+ @Override
+ public void registerConfigurationChangeListener(
+ ConfigurationContainerListener listener) {
+ }
+
+ @Override
+ public void unregisterConfigurationChangeListener(
+ ConfigurationContainerListener listener) {
+ }
+
+ @Override
+ public void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
+ }
+
+ @Override
+ public void requestResize(Rect bounds, int resizeMode) {
+ }
+ };
+
+ TestTaskWindowContainerController(WindowTestsBase testsBase) {
+ this(testsBase.createStackControllerOnDisplay(testsBase.mDisplayContent));
+ }
+
+ TestTaskWindowContainerController(StackWindowController stackController) {
+ super(sNextTaskId++, NOP_LISTENER, stackController, 0 /* userId */, null /* bounds */,
+ RESIZE_MODE_UNRESIZEABLE, false /* supportsPictureInPicture */, true /* toTop*/,
+ true /* showForAllUsers */, new ActivityManager.TaskDescription(),
+ stackController.mService);
+ }
+
+ @Override
+ TestTask createTask(int taskId, TaskStack stack, int userId, int resizeMode,
+ boolean supportsPictureInPicture, ActivityManager.TaskDescription taskDescription) {
+ return new TestTask(taskId, stack, userId, mService, resizeMode,
+ supportsPictureInPicture, this);
+ }
+ }
+
+ public static class TestIApplicationToken implements IApplicationToken {
+
+ private final Binder mBinder = new Binder();
+ @Override
+ public IBinder asBinder() {
+ return mBinder;
+ }
+ @Override
+ public String getName() {
+ return null;
+ }
+ }
+
+ /** Used to track resize reports. */
+ public static class TestWindowState extends WindowState {
+ boolean mResizeReported;
+
+ TestWindowState(WindowManagerService service, Session session, IWindow window,
+ WindowManager.LayoutParams attrs, WindowToken token) {
+ super(service, session, window, token, null, OP_NONE, 0, attrs, 0, 0,
+ false /* ownerCanAddInternalSystemWindow */);
+ }
+
+ @Override
+ void reportResized() {
+ super.reportResized();
+ mResizeReported = true;
+ }
+
+ @Override
+ public boolean isGoneForLayoutLw() {
+ return false;
+ }
+
+ @Override
+ void updateResizingWindowIfNeeded() {
+ // Used in AppWindowTokenTests#testLandscapeSeascapeRotationRelayout to deceive
+ // the system that it can actually update the window.
+ boolean hadSurface = mHasSurface;
+ mHasSurface = true;
+
+ super.updateResizingWindowIfNeeded();
+
+ mHasSurface = hadSurface;
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 1eb46fb05b5e..b3f56e7ae99f 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -37,7 +37,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.mockito.Mockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import android.content.Context;
import android.content.res.Configuration;
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index 3048f1a3487b..3048f1a3487b 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 3dcea75b8ae5..3dcea75b8ae5 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index d97f0c5f7684..143b323892f3 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -304,4 +304,10 @@ interface ITelecomService {
* @see TelecomServiceImpl#handleCallIntent
*/
void handleCallIntent(in Intent intent);
+
+ void setTestDefaultCallScreeningApp(String packageName);
+
+ void addOrRemoveTestCallCompanionApp(String packageName, boolean isAdded);
+
+ void setTestAutoModeApp(String packageName);
}
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index da3acc2eedfe..448207424d59 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -460,6 +460,9 @@ public class RadioAccessFamily implements Parcelable {
if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA)) != 0) {
networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
}
+ if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_NR)) != 0) {
+ networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_NR;
+ }
return (networkTypeRaf == 0) ? TelephonyManager.NETWORK_TYPE_UNKNOWN : networkTypeRaf;
}
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 777d219449a2..13fbeaaa02b7 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -223,9 +223,15 @@ public class ServiceState implements Parcelable {
public static final int RIL_RADIO_TECHNOLOGY_LTE_CA = 19;
/**
- * Number of radio technologies for GSM, UMTS and CDMA.
+ * NR(New Radio) 5G.
+ * @hide
+ */
+ public static final int RIL_RADIO_TECHNOLOGY_NR = 20;
+
+ /**
+ * The number of the radio technologies.
*/
- private static final int NEXT_RIL_RADIO_TECHNOLOGY = 20;
+ private static final int NEXT_RIL_RADIO_TECHNOLOGY = 21;
/** @hide */
public static final int RIL_RADIO_CDMA_TECHNOLOGY_BITMASK =
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 34a8c9659595..45cfe1e303ec 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -569,14 +569,6 @@ public class SubscriptionManager {
public static final String IS_OPPORTUNISTIC = "is_opportunistic";
/**
- * TelephonyProvider column name for subId of parent subscription of an opportunistic
- * subscription.
- * if the parent sub id is valid, then is_opportunistic should always to true.
- * @hide
- */
- public static final String PARENT_SUB_ID = "parent_sub_id";
-
- /**
* TelephonyProvider column name for group ID. Subscriptions with same group ID
* are considered bundled together, and should behave as a single subscription at
* certain scenarios.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 79ed93e009dc..d54da0905e18 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2243,9 +2243,11 @@ public class TelephonyManager {
/** Current network is LTE_CA {@hide} */
@UnsupportedAppUsage
public static final int NETWORK_TYPE_LTE_CA = TelephonyProtoEnums.NETWORK_TYPE_LTE_CA; // = 19.
+ /** Current network is NR(New Radio) 5G. */
+ public static final int NETWORK_TYPE_NR = TelephonyProtoEnums.NETWORK_TYPE_NR; // 20.
/** Max network type number. Update as new types are added. Don't add negative types. {@hide} */
- public static final int MAX_NETWORK_TYPE = NETWORK_TYPE_LTE_CA;
+ public static final int MAX_NETWORK_TYPE = NETWORK_TYPE_NR;
/** @hide */
@IntDef({
@@ -2269,6 +2271,7 @@ public class TelephonyManager {
NETWORK_TYPE_TD_SCDMA,
NETWORK_TYPE_IWLAN,
NETWORK_TYPE_LTE_CA,
+ NETWORK_TYPE_NR,
})
@Retention(RetentionPolicy.SOURCE)
public @interface NetworkType{}
@@ -4214,7 +4217,8 @@ public class TelephonyManager {
}
/**
- * Returns the voice mail count for a subscription. Return 0 if unavailable.
+ * Returns the voice mail count for a subscription. Return 0 if unavailable or the caller does
+ * not have the READ_PHONE_STATE permission.
* @param subId whose voice message count is returned
* @hide
*/
@@ -4225,7 +4229,7 @@ public class TelephonyManager {
ITelephony telephony = getITelephony();
if (telephony == null)
return 0;
- return telephony.getVoiceMessageCountForSubscriber(subId);
+ return telephony.getVoiceMessageCountForSubscriber(subId, getOpPackageName());
} catch (RemoteException ex) {
return 0;
} catch (NullPointerException ex) {
@@ -8579,7 +8583,8 @@ public class TelephonyManager {
/**
* Return the application ID for the uicc application type like {@link #APPTYPE_CSIM}.
- * All uicc applications are uniquely identified by application ID. See ETSI 102.221 and 101.220
+ * All uicc applications are uniquely identified by application ID, represented by the hex
+ * string. e.g, A00000015141434C00. See ETSI 102.221 and 101.220
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
*
@@ -9216,6 +9221,7 @@ public class TelephonyManager {
NETWORK_TYPE_BITMASK_TD_SCDMA,
NETWORK_TYPE_BITMASK_LTE,
NETWORK_TYPE_BITMASK_LTE_CA,
+ NETWORK_TYPE_BITMASK_NR,
})
public @interface NetworkTypeBitMask {}
@@ -9332,6 +9338,13 @@ public class TelephonyManager {
public static final int NETWORK_TYPE_BITMASK_LTE_CA = (1 << NETWORK_TYPE_LTE_CA);
/**
+ * network type bitmask indicating the support of radio tech NR(New Radio) 5G.
+ * @hide
+ */
+ @SystemApi
+ public static final int NETWORK_TYPE_BITMASK_NR = (1 << NETWORK_TYPE_NR);
+
+ /**
* @return Modem supported radio access family bitmask
*
* <p>Requires permission: {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index 2d46ec26a755..41f7bd7ade63 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -17,6 +17,7 @@
package android.telephony.emergency;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.hardware.radio.V1_4.EmergencyNumberSource;
import android.hardware.radio.V1_4.EmergencyServiceCategory;
import android.os.Parcel;
@@ -196,7 +197,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
private final int mEmergencyNumberSourceBitmask;
/** @hide */
- public EmergencyNumber(String number, String countryIso,
+ public EmergencyNumber(@NonNull String number, @NonNull String countryIso,
int emergencyServiceCategories,
int emergencyNumberSources) {
this.mNumber = number;
@@ -403,7 +404,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
* 0 if both have equal display priority.
*/
@Override
- public int compareTo(EmergencyNumber emergencyNumber) {
+ public int compareTo(@NonNull EmergencyNumber emergencyNumber) {
if (this.getDisplayPriorityScore()
> emergencyNumber.getDisplayPriorityScore()) {
return -1;
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index f73036e88a95..a6c24bf4e18a 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -23,6 +23,8 @@ import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.telecom.VideoProfile;
+import android.telephony.emergency.EmergencyNumber;
+import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
import android.util.Log;
import com.android.internal.telephony.PhoneConstants;
@@ -295,6 +297,28 @@ public final class ImsCallProfile implements Parcelable {
public @CallRestrictCause int mRestrictCause = CALL_RESTRICT_CAUSE_NONE;
/**
+ * The emergency service categories, only valid if {@link #getServiceType} returns
+ * {@link #SERVICE_TYPE_EMERGENCY}
+ *
+ * If valid, the value is the bitwise-OR combination of the following constants:
+ * <ol>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_POLICE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AMBULANCE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
+ * </ol>
+ *
+ * Reference: 3gpp 23.167, Section 6 - Functional description;
+ * 3gpp 22.101, Section 10 - Emergency Calls.
+ */
+ private @EmergencyServiceCategories int mEmergencyServiceCategories =
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
+
+ /**
* Extras associated with this {@link ImsCallProfile}.
* <p>
* Valid data types include:
@@ -495,6 +519,7 @@ public final class ImsCallProfile implements Parcelable {
out.writeInt(mCallType);
out.writeBundle(filteredExtras);
out.writeParcelable(mMediaProfile, 0);
+ out.writeInt(mEmergencyServiceCategories);
}
private void readFromParcel(Parcel in) {
@@ -502,6 +527,7 @@ public final class ImsCallProfile implements Parcelable {
mCallType = in.readInt();
mCallExtras = in.readBundle();
mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader());
+ mEmergencyServiceCategories = in.readInt();
}
public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
@@ -710,4 +736,53 @@ public final class ImsCallProfile implements Parcelable {
private static boolean isVideoStateSet(int videoState, int videoStateToCheck) {
return (videoState & videoStateToCheck) == videoStateToCheck;
}
+
+ /**
+ * Set the emergency service categories. The set value is valid only if
+ * {@link #getServiceType} returns {@link #SERVICE_TYPE_EMERGENCY}
+ *
+ * If valid, the value is the bitwise-OR combination of the following constants:
+ * <ol>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_POLICE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AMBULANCE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
+ * </ol>
+ *
+ * Reference: 3gpp 23.167, Section 6 - Functional description;
+ * 3gpp 22.101, Section 10 - Emergency Calls.
+ */
+ public void setEmergencyServiceCategories(
+ @EmergencyServiceCategories int emergencyServiceCategories) {
+ mEmergencyServiceCategories = emergencyServiceCategories;
+ }
+
+ /**
+ * Get the emergency service categories, only valid if {@link #getServiceType} returns
+ * {@link #SERVICE_TYPE_EMERGENCY}
+ *
+ * @return the emergency service categories,
+ *
+ * If valid, the value is the bitwise-OR combination of the following constants:
+ * <ol>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_POLICE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AMBULANCE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MARINE_GUARD} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MOUNTAIN_RESCUE} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_MIEC} </li>
+ * <li>{@link EmergencyNumber#EMERGENCY_SERVICE_CATEGORY_AIEC} </li>
+ * </ol>
+ *
+ * Reference: 3gpp 23.167, Section 6 - Functional description;
+ * 3gpp 22.101, Section 10 - Emergency Calls.
+ */
+ public @EmergencyServiceCategories int getEmergencyServiceCategories() {
+ return mEmergencyServiceCategories;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index fc42de58319e..32e939a0c925 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -393,16 +393,11 @@ interface ITelephony {
int getDataActivationState(int subId, String callingPackage);
/**
- * Returns the unread count of voicemails
- */
- int getVoiceMessageCount();
-
- /**
* Returns the unread count of voicemails for a subId.
* @param subId user preferred subId.
* Returns the unread count of voicemails
*/
- int getVoiceMessageCountForSubscriber(int subId);
+ int getVoiceMessageCountForSubscriber(int subId, String callingPackage);
/**
* Returns true if current state supports both voice and data
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
index 7842a1cd03b3..5b58dd5d758b 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -80,6 +80,7 @@ package android.test.mock {
method public java.io.File getNoBackupFilesDir();
method public java.io.File getObbDir();
method public java.io.File[] getObbDirs();
+ method public java.lang.String getOpPackageName();
method public java.lang.String getPackageCodePath();
method public android.content.pm.PackageManager getPackageManager();
method public java.lang.String getPackageName();
diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
index f1ec000dfa6a..8b2c815432ea 100644
--- a/test-mock/api/test-current.txt
+++ b/test-mock/api/test-current.txt
@@ -1,9 +1,5 @@
package android.test.mock {
- public class MockContext extends android.content.Context {
- method public java.lang.String getOpPackageName();
- }
-
public deprecated class MockPackageManager extends android.content.pm.PackageManager {
method public boolean arePermissionsIndividuallyControlled();
method public java.lang.String getDefaultBrowserPackageNameAsUser(int);
diff --git a/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java b/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java
index 8d8fc84126ec..b9e282ebdfef 100644
--- a/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java
+++ b/tests/Internal/src/android/service/wallpaper/WallpaperServiceTest.java
@@ -38,7 +38,7 @@ public class WallpaperServiceTest {
public Engine onCreateEngine() {
return new Engine() {
@Override
- public void onAmbientModeChanged(boolean inAmbientMode, boolean animated) {
+ public void onAmbientModeChanged(boolean inAmbientMode, long duration) {
ambientModeChangedCount[0]++;
}
};
@@ -47,12 +47,12 @@ public class WallpaperServiceTest {
WallpaperService.Engine engine = service.onCreateEngine();
engine.setCreated(true);
- engine.doAmbientModeChanged(false, false);
+ engine.doAmbientModeChanged(false, 0);
assertFalse("ambient mode should be false", engine.isInAmbientMode());
assertEquals("onAmbientModeChanged should have been called",
ambientModeChangedCount[0], 1);
- engine.doAmbientModeChanged(true, false);
+ engine.doAmbientModeChanged(true, 0);
assertTrue("ambient mode should be false", engine.isInAmbientMode());
assertEquals("onAmbientModeChanged should have been called",
ambientModeChangedCount[0], 2);
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index fdc800bcc177..2f1e53ca5065 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -15,23 +15,54 @@
# limitations under the License.
"""
Generate API lists for non-SDK API enforcement.
-
-usage: generate-hiddenapi-lists.py [-h]
- --input-public INPUT_PUBLIC
- --input-private INPUT_PRIVATE
- [--input-whitelists [INPUT_WHITELISTS [INPUT_WHITELISTS ...]]]
- [--input-greylists [INPUT_GREYLISTS [INPUT_GREYLISTS ...]]]
- [--input-blacklists [INPUT_BLACKLISTS [INPUT_BLACKLISTS ...]]]
- --output-whitelist OUTPUT_WHITELIST
- --output-light-greylist OUTPUT_LIGHT_GREYLIST
- --output-dark-greylist OUTPUT_DARK_GREYLIST
- --output-blacklist OUTPUT_BLACKLIST
"""
import argparse
import os
import sys
import re
+# Names of flags recognized by the `hiddenapi` tool.
+FLAG_WHITELIST = "whitelist"
+FLAG_GREYLIST = "greylist"
+FLAG_BLACKLIST = "blacklist"
+FLAG_GREYLIST_MAX_O = "greylist-max-o"
+
+# List of all known flags.
+FLAGS = [
+ FLAG_WHITELIST,
+ FLAG_GREYLIST,
+ FLAG_BLACKLIST,
+ FLAG_GREYLIST_MAX_O,
+]
+FLAGS_SET = set(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,
+# 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"
+
+# Regex patterns of fields/methods used in serialization. These are
+# considered public API despite being hidden.
+SERIALIZATION_PATTERNS = [
+ r'readObject\(Ljava/io/ObjectInputStream;\)V',
+ r'readObjectNoData\(\)V',
+ r'readResolve\(\)Ljava/lang/Object;',
+ r'serialVersionUID:J',
+ r'serialPersistentFields:\[Ljava/io/ObjectStreamField;',
+ r'writeObject\(Ljava/io/ObjectOutputStream;\)V',
+ r'writeReplace\(\)Ljava/lang/Object;',
+]
+
+# Single regex used to match serialization API. It combines all the
+# SERIALIZATION_PATTERNS into a single regular expression.
+SERIALIZATION_REGEX = re.compile(r'.*->(' + '|'.join(SERIALIZATION_PATTERNS) + r')$')
+
+# Predicates to be used with filter_apis.
+IS_UNASSIGNED = lambda api, flags: not flags
+IS_SERIALIZATION = lambda api, flags: SERIALIZATION_REGEX.match(api)
+
def get_args():
"""Parses command line arguments.
@@ -39,21 +70,21 @@ def get_args():
Namespace: dictionary of parsed arguments
"""
parser = argparse.ArgumentParser()
- parser.add_argument('--input-public', required=True, help='List of all public members')
- parser.add_argument('--input-private', required=True, help='List of all private members')
- parser.add_argument(
- '--input-whitelists', nargs='*',
- help='Lists of members to force on whitelist')
- parser.add_argument(
- '--input-greylists', nargs='*',
- help='Lists of members to force on light greylist')
- parser.add_argument(
- '--input-blacklists', nargs='*',
- help='Lists of members to force on blacklist')
- parser.add_argument('--output-whitelist', required=True)
- parser.add_argument('--output-light-greylist', required=True)
- parser.add_argument('--output-dark-greylist', required=True)
- parser.add_argument('--output-blacklist', required=True)
+ parser.add_argument('--output', required=True)
+ parser.add_argument('--public', required=True, help='list of all public entries')
+ parser.add_argument('--private', required=True, help='list of all private entries')
+ parser.add_argument('--csv', nargs='*', default=[], metavar='CSV_FILE',
+ help='CSV files to be merged into output')
+
+ for flag in FLAGS:
+ ignore_conflicts_flag = flag + FLAG_IGNORE_CONFLICTS_SUFFIX
+ parser.add_argument('--' + flag, dest=flag, nargs='*', default=[], metavar='TXT_FILE',
+ help='lists of entries with flag "' + flag + '"')
+ parser.add_argument('--' + ignore_conflicts_flag, dest=ignore_conflicts_flag, nargs='*',
+ default=[], metavar='TXT_FILE',
+ help='lists of entries with flag "' + flag +
+ '". skip entry if missing or flag conflict.')
+
return parser.parse_args()
def read_lines(filename):
@@ -65,10 +96,13 @@ def read_lines(filename):
filename (string): Path to the file to read from.
Returns:
- list: Lines of the loaded file as a list of strings.
+ Lines of the file as a list of string.
"""
with open(filename, 'r') as f:
- return filter(lambda line: not line.startswith('#'), f.readlines())
+ lines = f.readlines();
+ lines = filter(lambda line: not line.startswith('#'), lines)
+ 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.
@@ -77,167 +111,168 @@ def write_lines(filename, lines):
filename (string): Path to the file to be writting into.
lines (list): List of strings to write into the file.
"""
+ lines = map(lambda line: line + '\n', lines)
with open(filename, 'w') as f:
f.writelines(lines)
-def move_between_sets(subset, src, dst, source = "<unknown>"):
- """Removes a subset of elements from one set and add it to another.
-
- Args:
- subset (set): The subset of `src` to be moved from `src` to `dst`.
- src (set): Source set. Must be a superset of `subset`.
- dst (set): Destination set. Must be disjoint with `subset`.
- """
- assert src.issuperset(subset), (
- "Error processing: {}\n"
- "The following entries were not found:\n"
- "{}"
- "Please visit go/hiddenapi for more information.").format(
- source, "".join(map(lambda x: " " + str(x), subset.difference(src))))
- assert dst.isdisjoint(subset)
- # Order matters if `src` and `subset` are the same object.
- dst.update(subset)
- src.difference_update(subset)
-
-def get_package_name(signature):
- """Returns the package name prefix of a class member signature.
-
- Example: "Ljava/lang/String;->hashCode()J" --> "Ljava/lang/"
-
- Args:
- signature (string): Member signature
-
- Returns
- string: Package name of the given member
- """
- class_name_end = signature.find("->")
- assert class_name_end != -1, "Invalid signature: {}".format(signature)
- package_name_end = signature.rfind("/", 0, class_name_end)
- assert package_name_end != -1, "Invalid signature: {}".format(signature)
- return signature[:package_name_end + 1]
-
-def all_package_names(*args):
- """Returns a set of packages names in given lists of member signatures.
-
- Example: args = [ set([ "Lpkg1/ClassA;->foo()V", "Lpkg2/ClassB;->bar()J" ]),
- set([ "Lpkg1/ClassC;->baz()Z" ]) ]
- return value = set([ "Lpkg1/", "Lpkg2" ])
-
- Args:
- *args (list): List of sets to iterate over and extract the package names
- of its elements (member signatures)
-
- Returns:
- set: All package names extracted from the given lists of signatures.
- """
- packages = set()
- for arg in args:
- packages = packages.union(map(get_package_name, arg))
- return packages
-
-def move_all(src, dst):
- """Moves all elements of one set to another.
-
- Args:
- src (set): Source set. Will become empty.
- dst (set): Destination set. Will contain all elements of `src`.
- """
- move_between_sets(src, src, dst)
-
-def move_from_files(filenames, src, dst):
- """Loads member signatures from a list of files and moves them to a given set.
-
- Opens files in `filenames`, reads all their lines and moves those from `src`
- set to `dst` set.
-
- Args:
- filenames (list): List of paths to files to be loaded.
- src (set): Set that loaded lines should be moved from.
- dst (set): Set that loaded lines should be moved to.
- """
- if filenames:
- for filename in filenames:
- move_between_sets(set(read_lines(filename)), src, dst, filename)
-
-def move_serialization(src, dst):
- """Moves all members matching serialization API signatures between given sets.
-
- Args:
- src (set): Set that will be searched for serialization API and that API
- will be removed from it.
- dst (set): Set that serialization API will be moved to.
- """
- serialization_patterns = [
- r'readObject\(Ljava/io/ObjectInputStream;\)V',
- r'readObjectNoData\(\)V',
- r'readResolve\(\)Ljava/lang/Object;',
- r'serialVersionUID:J',
- r'serialPersistentFields:\[Ljava/io/ObjectStreamField;',
- r'writeObject\(Ljava/io/ObjectOutputStream;\)V',
- r'writeReplace\(\)Ljava/lang/Object;',
- ]
- regex = re.compile(r'.*->(' + '|'.join(serialization_patterns) + r')$')
- move_between_sets(filter(lambda api: regex.match(api), src), src, dst)
-
-def move_from_packages(packages, src, dst):
- """Moves all members of given package names from one set to another.
-
- Args:
- packages (list): List of string package names.
- src (set): Set that will be searched for API matching one of the given
- package names. Surch API will be removed from the set.
- dst (set): Set that matching API will be moved to.
- """
- move_between_sets(filter(lambda api: get_package_name(api) in packages, src), src, dst)
+class FlagsDict:
+ def __init__(self, public_api, private_api):
+ # Bootstrap the entries dictionary.
+
+ # Check that the two sets do not overlap.
+ public_api_set = set(public_api)
+ private_api_set = set(private_api)
+ assert public_api_set.isdisjoint(private_api_set), (
+ "Lists of public and private API overlap. " +
+ "This suggests an issue with the `hiddenapi` build tool.")
+
+ # Compute the whole key set
+ self._dict_keyset = public_api_set.union(private_api_set)
+
+ # Create a dict that creates entries for both public and private API,
+ # and assigns public API to the whitelist.
+ self._dict = {}
+ for api in public_api:
+ self._dict[api] = set([ FLAG_WHITELIST ])
+ for api in private_api:
+ self._dict[api] = set()
+
+ def _check_entries_set(self, keys_subset, source):
+ assert isinstance(keys_subset, set)
+ assert keys_subset.issubset(self._dict_keyset), (
+ "Error processing: {}\n"
+ "The following entries were unexpected:\n"
+ "{}"
+ "Please visit go/hiddenapi for more information.").format(
+ source, "".join(map(lambda x: " " + str(x), keys_subset - self._dict_keyset)))
+
+ def _check_flags_set(self, flags_subset, source):
+ assert isinstance(flags_subset, set)
+ assert flags_subset.issubset(FLAGS_SET), (
+ "Error processing: {}\n"
+ "The following flags were not recognized: \n"
+ "{}\n"
+ "Please visit go/hiddenapi for more information.").format(
+ source, "\n".join(flags_subset - FLAGS_SET))
+
+ def filter_apis(self, filter_fn):
+ """Returns APIs which match a given predicate.
+
+ This is a helper function which allows to filter on both signatures (keys) and
+ flags (values). The built-in filter() invokes the lambda only with dict's keys.
+
+ Args:
+ filter_fn : Function which takes two arguments (signature/flags) and returns a boolean.
+
+ Returns:
+ A set of APIs which match the predicate.
+ """
+ return set(filter(lambda x: filter_fn(x, self._dict[x]), self._dict_keyset))
+
+ def get_valid_subset_of_unassigned_apis(self, api_subset):
+ """Sanitizes a key set input to only include keys which exist in the dictionary
+ and have not been assigned any flags.
+
+ Args:
+ entries_subset (set/list): Key set to be sanitized.
+
+ Returns:
+ Sanitized key set.
+ """
+ assert isinstance(api_subset, set)
+ return api_subset.intersection(self.filter_apis(IS_UNASSIGNED))
+
+ def generate_csv(self):
+ """Constructs CSV entries from a dictionary.
+
+ 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))
+
+ def parse_and_merge_csv(self, csv_lines, source = "<unknown>"):
+ """Parses CSV entries and merges them into a given dictionary.
+
+ The expected CSV format is:
+ <api signature>,<flag1>,<flag2>,...,<flagN>
+
+ Args:
+ csv_lines (list of strings): Lines read from a CSV file.
+ source (string): Origin of `csv_lines`. Will be printed in error messages.
+
+ Throws:
+ AssertionError if parsed API signatures of flags are invalid.
+ """
+ # Split CSV lines into arrays of values.
+ csv_values = [ line.split(',') for line in csv_lines ]
+
+ # Check that all entries exist in the dict.
+ csv_keys = set([ csv[0] for csv in csv_values ])
+ self._check_entries_set(csv_keys, source)
+
+ # Check that all flags are known.
+ csv_flags = set(reduce(lambda x, y: set(x).union(y), [ csv[1:] for csv in csv_values ], []))
+ 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:
+ self._dict[csv[0]].update(csv[1:])
+
+ def assign_flag(self, flag, apis, source="<unknown>"):
+ """Assigns a flag to given subset of entries.
+
+ Args:
+ flag (string): One of FLAGS.
+ apis (set): Subset of APIs to recieve the flag.
+ source (string): Origin of `entries_subset`. Will be printed in error messages.
+
+ Throws:
+ AssertionError if parsed API signatures of flags are invalid.
+ """
+ # Check that all APIs exist in the dict.
+ self._check_entries_set(apis, source)
+
+ # Check that the flag is known.
+ self._check_flags_set(set([ flag ]), source)
+
+ # Iterate over the API subset, find each entry in dict and assign the flag to it.
+ for api in apis:
+ self._dict[api].add(flag)
def main(argv):
- args = get_args()
-
- # Initialize API sets by loading lists of public and private API. Public API
- # are all members resolvable from SDK API stubs, other members are private.
- # As an optimization, skip the step of moving public API from a full set of
- # members and start with a populated whitelist.
- whitelist = set(read_lines(args.input_public))
- uncategorized = set(read_lines(args.input_private))
- light_greylist = set()
- dark_greylist = set()
- blacklist = set()
-
- # Assert that there is no overlap between public and private API.
- assert whitelist.isdisjoint(uncategorized)
- num_all_api = len(whitelist) + len(uncategorized)
-
- # Read all files which manually assign members to specific lists.
- move_from_files(args.input_whitelists, uncategorized, whitelist)
- move_from_files(args.input_greylists, uncategorized, light_greylist)
- move_from_files(args.input_blacklists, uncategorized, blacklist)
-
- # Iterate over all uncategorized members and move serialization API to whitelist.
- move_serialization(uncategorized, whitelist)
-
- # Extract package names of members from whitelist and light greylist, which
- # are assumed to have been finalized at this point. Assign all uncategorized
- # members from the same packages to the dark greylist.
- dark_greylist_packages = all_package_names(whitelist, light_greylist)
- move_from_packages(dark_greylist_packages, uncategorized, dark_greylist)
-
- # Assign all uncategorized members to the blacklist.
- move_all(uncategorized, blacklist)
-
- # Assert we have not missed anything.
- assert whitelist.isdisjoint(light_greylist)
- assert whitelist.isdisjoint(dark_greylist)
- assert whitelist.isdisjoint(blacklist)
- assert light_greylist.isdisjoint(dark_greylist)
- assert light_greylist.isdisjoint(blacklist)
- assert dark_greylist.isdisjoint(blacklist)
- assert num_all_api == len(whitelist) + len(light_greylist) + len(dark_greylist) + len(blacklist)
-
- # Write final lists to disk.
- write_lines(args.output_whitelist, whitelist)
- write_lines(args.output_light_greylist, light_greylist)
- write_lines(args.output_dark_greylist, dark_greylist)
- write_lines(args.output_blacklist, blacklist)
+ # Parse arguments.
+ args = vars(get_args())
+
+ flags = FlagsDict(read_lines(args["public"]), read_lines(args["private"]))
+
+ # 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))
+
+ # (2) Merge input CSV files into the dictionary.
+ for filename in args["csv"]:
+ flags.parse_and_merge_csv(read_lines(filename), filename)
+
+ # (3) Merge text files with a known flag into the dictionary.
+ for flag in FLAGS:
+ for filename in args[flag]:
+ flags.assign_flag(flag, read_lines(filename), filename)
+
+ # Merge text files where conflicts should be ignored.
+ # This will only assign the given flag if:
+ # (a) the entry exists, and
+ # (b) it has not been assigned any other flag.
+ # Because of (b), this must run after all strict assignments have been performed.
+ for flag in FLAGS:
+ for filename in args[flag + FLAG_IGNORE_CONFLICTS_SUFFIX]:
+ valid_entries = flags.get_valid_subset_of_unassigned_apis(read_lines(filename))
+ flags.assign_flag(flag, valid_entries, filename)
+
+ # Assign all remaining entries to the blacklist.
+ flags.assign_flag(FLAG_BLACKLIST, flags.filter_apis(IS_UNASSIGNED))
+
+ # Write output.
+ write_lines(args["output"], flags.generate_csv())
if __name__ == "__main__":
main(sys.argv)
diff --git a/tools/hiddenapi/generate_hiddenapi_lists_test.py b/tools/hiddenapi/generate_hiddenapi_lists_test.py
index 4716241940b5..249f37db5a82 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists_test.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists_test.py
@@ -2,14 +2,14 @@
#
# Copyright (C) 2018 The Android Open Source Project
#
-# Licensed under the Apache License, Version 2.0 (the "License");
+# 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,
+# 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.
@@ -18,90 +18,90 @@ import unittest
from generate_hiddenapi_lists import *
class TestHiddenapiListGeneration(unittest.TestCase):
+ def test_init(self):
+ # Check empty lists
+ flags = FlagsDict([], [])
+ self.assertEquals(flags.generate_csv(), [])
- def test_move_between_sets(self):
- A = set([1, 2, 3, 4])
- B = set([5, 6, 7, 8])
- move_between_sets(set([2, 4]), A, B)
- self.assertEqual(A, set([1, 3]))
- self.assertEqual(B, set([2, 4, 5, 6, 7, 8]))
-
- def test_move_between_sets_fail_not_superset(self):
- A = set([1, 2, 3, 4])
- B = set([5, 6, 7, 8])
- with self.assertRaises(AssertionError) as ar:
- move_between_sets(set([0, 2]), A, B)
-
- def test_move_between_sets_fail_not_disjoint(self):
- A = set([1, 2, 3, 4])
- B = set([4, 5, 6, 7, 8])
- with self.assertRaises(AssertionError) as ar:
- move_between_sets(set([1, 4]), A, B)
-
- def test_get_package_name(self):
- self.assertEqual(get_package_name("Ljava/lang/String;->clone()V"), "Ljava/lang/")
-
- def test_get_package_name_fail_no_arrow(self):
- with self.assertRaises(AssertionError) as ar:
- get_package_name("Ljava/lang/String;-clone()V")
- with self.assertRaises(AssertionError) as ar:
- get_package_name("Ljava/lang/String;>clone()V")
- with self.assertRaises(AssertionError) as ar:
- get_package_name("Ljava/lang/String;__clone()V")
-
- def test_get_package_name_fail_no_package(self):
- with self.assertRaises(AssertionError) as ar:
- get_package_name("LString;->clone()V")
-
- def test_all_package_names(self):
- self.assertEqual(all_package_names(), set())
- self.assertEqual(all_package_names(set(["Lfoo/Bar;->baz()V"])), set(["Lfoo/"]))
- self.assertEqual(
- all_package_names(set(["Lfoo/Bar;->baz()V", "Lfoo/BarX;->bazx()I"])),
- set(["Lfoo/"]))
- self.assertEqual(
- all_package_names(
- set(["Lfoo/Bar;->baz()V"]),
- set(["Lfoo/BarX;->bazx()I", "Labc/xyz/Mno;->ijk()J"])),
- set(["Lfoo/", "Labc/xyz/"]))
-
- def test_move_all(self):
- src = set([ "abc", "xyz" ])
- dst = set([ "def" ])
- move_all(src, dst)
- self.assertEqual(src, set())
- self.assertEqual(dst, set([ "abc", "def", "xyz" ]))
-
- def test_move_from_packages(self):
- src = set([ "Lfoo/bar/ClassA;->abc()J", # will be moved
- "Lfoo/bar/ClassA;->def()J", # will be moved
- "Lcom/pkg/example/ClassD;->ijk:J", # not moved: different package
- "Lfoo/bar/xyz/ClassC;->xyz()Z" ]) # not moved: subpackage
- dst = set()
- packages = set([ "Lfoo/bar/" ])
- move_from_packages(packages, src, dst)
- self.assertEqual(
- src, set([ "Lfoo/bar/xyz/ClassC;->xyz()Z", "Lcom/pkg/example/ClassD;->ijk:J" ]))
+ # Check valid input - two public and two private API signatures.
+ flags = FlagsDict(['A', 'B'], ['C', 'D'])
+ self.assertEquals(flags.generate_csv(),
+ [ 'A,' + FLAG_WHITELIST, 'B,' + FLAG_WHITELIST, 'C', 'D' ])
+
+ # Check invalid input - overlapping public/private API signatures.
+ with self.assertRaises(AssertionError):
+ flags = FlagsDict(['A', 'B'], ['B', 'C', 'D'])
+
+ def test_filter_apis(self):
+ # 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(['A', 'B'], ['C', 'D', 'E'])
+ filter_set = flags.filter_apis(lambda api, flags: not flags)
+ self.assertTrue(isinstance(filter_set, set))
+ self.assertEqual(filter_set, set([ 'C', 'D', 'E' ]))
+
+ def test_get_valid_subset_of_unassigned_keys(self):
+ # Create flags where only A is unassigned.
+ flags = FlagsDict(['A'], ['B', 'C'])
+ flags.assign_flag(FLAG_GREYLIST, set(['C']))
+ self.assertEquals(flags.generate_csv(),
+ [ 'A,' + FLAG_WHITELIST, 'B', 'C,' + FLAG_GREYLIST ])
+
+ # Check three things:
+ # (1) B is selected as valid unassigned
+ # (2) A is not selected because it is assigned 'whitelist'
+ # (3) D is not selected because it is not a valid key
self.assertEqual(
- dst, set([ "Lfoo/bar/ClassA;->abc()J", "Lfoo/bar/ClassA;->def()J" ]))
-
- def test_move_serialization(self):
- # All the entries should be moved apart from the last one
- src = set([ "Lfoo/bar/ClassA;->readObject(Ljava/io/ObjectInputStream;)V",
- "Lfoo/bar/ClassA;->readObjectNoData()V",
- "Lfoo/bar/ClassA;->readResolve()Ljava/lang/Object;",
- "Lfoo/bar/ClassA;->serialVersionUID:J",
- "Lfoo/bar/ClassA;->serialPersistentFields:[Ljava/io/ObjectStreamField;",
- "Lfoo/bar/ClassA;->writeObject(Ljava/io/ObjectOutputStream;)V",
- "Lfoo/bar/ClassA;->writeReplace()Ljava/lang/Object;",
- # Should not be moved as signature does not match
- "Lfoo/bar/ClassA;->readObject(Ljava/io/ObjectInputStream;)I"])
- expectedToMove = len(src) - 1
- dst = set()
- packages = set([ "Lfoo/bar/" ])
- move_serialization(src, dst)
- self.assertEqual(len(src), 1)
- self.assertEqual(len(dst), expectedToMove)
+ flags.get_valid_subset_of_unassigned_apis(set(['A', 'B', 'D'])), set([ 'B' ]))
+
+ def test_parse_and_merge_csv(self):
+ flags = FlagsDict(['A'], ['B'])
+ self.assertEquals(flags.generate_csv(), [ 'A,' + FLAG_WHITELIST, 'B' ])
+
+ # Test empty CSV entry.
+ flags.parse_and_merge_csv(['B'])
+ self.assertEquals(flags.generate_csv(), [ 'A,' + FLAG_WHITELIST, 'B' ])
+
+ # Test assigning an already assigned flag.
+ flags.parse_and_merge_csv(['A,' + FLAG_WHITELIST])
+ self.assertEquals(flags.generate_csv(), [ 'A,' + FLAG_WHITELIST, 'B' ])
+
+ # Test new additions.
+ flags.parse_and_merge_csv([
+ 'A,' + FLAG_GREYLIST,
+ 'B,' + FLAG_BLACKLIST + ',' + FLAG_GREYLIST_MAX_O ])
+ self.assertEqual(flags.generate_csv(),
+ [ 'A,' + FLAG_GREYLIST + "," + FLAG_WHITELIST,
+ 'B,' + FLAG_BLACKLIST + "," + FLAG_GREYLIST_MAX_O ])
+
+ # Test unknown API signature.
+ with self.assertRaises(AssertionError):
+ flags.parse_and_merge_csv([ 'C' ])
+
+ # Test unknown flag.
+ with self.assertRaises(AssertionError):
+ flags.parse_and_merge_csv([ 'A,foo' ])
+
+ def test_assign_flag(self):
+ flags = FlagsDict(['A'], ['B'])
+ self.assertEquals(flags.generate_csv(), [ 'A,' + FLAG_WHITELIST, 'B' ])
+
+ # Test assigning an already assigned flag.
+ flags.assign_flag(FLAG_WHITELIST, set([ 'A' ]))
+ self.assertEquals(flags.generate_csv(), [ 'A,' + FLAG_WHITELIST, 'B' ])
+
+ # Test new additions.
+ flags.assign_flag(FLAG_GREYLIST, set([ 'A', 'B' ]))
+ self.assertEquals(flags.generate_csv(),
+ [ 'A,' + FLAG_GREYLIST + "," + FLAG_WHITELIST, 'B,' + FLAG_GREYLIST ])
+
+ # Test invalid API signature.
+ with self.assertRaises(AssertionError):
+ flags.assign_flag(FLAG_WHITELIST, set([ 'C' ]))
+
+ # Test invalid flag.
+ with self.assertRaises(AssertionError):
+ flags.assign_flag('foo', set([ 'A' ]))
if __name__ == '__main__':
unittest.main()
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 3f42275b4e1b..faa354788c4e 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -262,8 +262,9 @@ static bool isDefaultMessageImpl(const Descriptor* descriptor, const Destination
return false;
case FieldDescriptor::TYPE_STRING:
if (getPrivacyFlags(field).patterns_size() != 0) return false;
+ break;
default:
- continue;
+ break;
}
}
parents->erase(descriptor->full_name());
diff --git a/tools/powermodel/Android.bp b/tools/powermodel/Android.bp
new file mode 100644
index 000000000000..f597aab0f464
--- /dev/null
+++ b/tools/powermodel/Android.bp
@@ -0,0 +1,26 @@
+
+java_library_host {
+ name: "powermodel",
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "guava",
+ ],
+}
+
+java_test_host {
+ name: "powermodel-test",
+
+ test_suites: ["general-tests"],
+
+ srcs: ["test/**/*.java"],
+ java_resource_dirs: ["test-resource"],
+
+ static_libs: [
+ "powermodel",
+ "junit",
+ "mockito",
+ ],
+}
+
diff --git a/tools/powermodel/TEST_MAPPING b/tools/powermodel/TEST_MAPPING
new file mode 100644
index 000000000000..c8db339ce23b
--- /dev/null
+++ b/tools/powermodel/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+ "presubmit": [
+ {
+ "name": "powermodel-test"
+ }
+ ]
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/ActivityReport.java b/tools/powermodel/src/com/android/powermodel/ActivityReport.java
new file mode 100644
index 000000000000..4a8f63370cda
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/ActivityReport.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * ActivityReport contains the summary of the activity that consumes power
+ * as reported by batterystats or statsd.
+ */
+public class ActivityReport {
+ private AppList<AppActivity> mApps;
+
+ public ImmutableList<AppActivity> getAllApps() {
+ return mApps.getAllApps();
+ }
+
+ public ImmutableList<AppActivity> getRegularApps() {
+ return mApps.getRegularApps();
+ }
+
+ public List<AppActivity> findApp(String pkg) {
+ return mApps.findApp(pkg);
+ }
+
+ public AppActivity findApp(SpecialApp specialApp) {
+ return mApps.findApp(specialApp);
+ }
+
+ /**
+ * Find a component in the GLOBAL app.
+ * <p>
+ * Returns null if either the global app doesn't exist (bad data?) or the component
+ * doesn't exist in the global app.
+ */
+ public ComponentActivity findGlobalComponent(Component component) {
+ final AppActivity global = mApps.findApp(SpecialApp.GLOBAL);
+ if (global == null) {
+ return null;
+ }
+ return global.getComponentActivity(component);
+ }
+
+ public static class Builder {
+ private AppList.Builder<AppActivity,AppActivity.Builder> mApps = new AppList.Builder();
+
+ public Builder() {
+ }
+
+ public ActivityReport build() {
+ final ActivityReport result = new ActivityReport();
+ result.mApps = mApps.build();
+ return result;
+ }
+
+ public void addActivity(Component component, Collection<ComponentActivity> activities) {
+ for (final ComponentActivity activity: activities) {
+ addActivity(component, activity);
+ }
+ }
+
+ public void addActivity(Component component, ComponentActivity activity) {
+ AppActivity.Builder app = mApps.get(activity.attribution);
+ if (app == null) {
+ app = new AppActivity.Builder();
+ app.setAttribution(activity.attribution);
+ mApps.put(activity.attribution, app);
+ }
+ app.addComponentActivity(component, activity);
+ }
+ }
+}
diff --git a/tools/powermodel/src/com/android/powermodel/AppActivity.java b/tools/powermodel/src/com/android/powermodel/AppActivity.java
new file mode 100644
index 000000000000..b87426ce0dc3
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/AppActivity.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.util.HashMap;
+
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+public class AppActivity extends AppInfo {
+
+ private ImmutableMap<Component, ComponentActivity> mComponents;
+ // TODO: power rails
+ // private ImmutableMap<Component, PowerRailActivity> mRails;
+
+ private AppActivity() {
+ }
+
+ /**
+ * Returns the {@link ComponentActivity} for the {@link Component} provided,
+ * or null if this AppActivity does not have that component.
+ * @more
+ * If there is no ComponentActivity for a particular Component, then
+ * there was no usage associated with that app for the app in question.
+ */
+ public ComponentActivity getComponentActivity(Component component) {
+ return mComponents.get(component);
+ }
+
+ public ImmutableSet<Component> getComponents() {
+ return mComponents.keySet();
+ }
+
+ public ImmutableMap<Component,ComponentActivity> getComponentActivities() {
+ return mComponents;
+ }
+
+ // TODO: power rails
+ // public ComponentActivity getPowerRail(Component component) {
+ // return mComponents.get(component);
+ // }
+ //
+ // public Set<Component> getPowerRails() {
+ // return mComponents.keySet();
+ // }
+
+ public static class Builder extends AppInfo.Builder<AppActivity> {
+ private HashMap<Component, ComponentActivity> mComponents = new HashMap();
+ // TODO power rails.
+
+ public Builder() {
+ }
+
+ public AppActivity build() {
+ final AppActivity result = new AppActivity();
+ init(result);
+ result.mComponents = ImmutableMap.copyOf(mComponents);
+ return result;
+ }
+
+ public void addComponentActivity(Component component, ComponentActivity activity) {
+ mComponents.put(component, activity);
+ }
+ }
+}
diff --git a/tools/powermodel/src/com/android/powermodel/AppInfo.java b/tools/powermodel/src/com/android/powermodel/AppInfo.java
new file mode 100644
index 000000000000..208339e8e491
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/AppInfo.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+class AppInfo {
+ private AttributionKey mAttribution;
+
+ protected AppInfo() {
+ }
+
+ public boolean hasPackage(String pkg) {
+ return mAttribution.hasPackage(pkg);
+ }
+
+ public AttributionKey getAttribution() {
+ return mAttribution;
+ }
+
+ abstract static class Builder<APP extends AppInfo> {
+ private AttributionKey mAttribution;
+
+ public Builder() {
+ }
+
+ public abstract APP build();
+
+ protected void init(AppInfo app) {
+ if (mAttribution == null) {
+ throw new RuntimeException("setAttribution(AttributionKey attribution) not called");
+ }
+ app.mAttribution = mAttribution;
+ }
+
+ public void setAttribution(AttributionKey attribution) {
+ mAttribution = attribution;
+ }
+
+ public AttributionKey getAttribution() {
+ return mAttribution;
+ }
+ }
+}
diff --git a/tools/powermodel/src/com/android/powermodel/AppList.java b/tools/powermodel/src/com/android/powermodel/AppList.java
new file mode 100644
index 000000000000..19572fc1cf15
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/AppList.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+class AppList<APP extends AppInfo> {
+ private ImmutableList<APP> mAllApps;
+ private ImmutableList<APP> mRegularApps;
+ private ImmutableMap<SpecialApp,APP> mSpecialApps;
+
+ private AppList() {
+ }
+
+ public ImmutableList<APP> getAllApps() {
+ return mAllApps;
+ }
+
+ public ImmutableList<APP> getRegularApps() {
+ return mRegularApps;
+ }
+
+ public List<APP> findApp(String pkg) {
+ List<APP> result = new ArrayList();
+ for (APP app: mRegularApps) {
+ if (app.hasPackage(pkg)) {
+ result.add(app);
+ }
+ }
+ return result;
+ }
+
+ public APP findApp(SpecialApp specialApp) {
+ return mSpecialApps.get(specialApp);
+ }
+
+ public static class Builder<APP extends AppInfo, BUILDER extends AppInfo.Builder<APP>> {
+ private final HashMap<AttributionKey,BUILDER> mApps = new HashMap();
+
+ public Builder() {
+ }
+
+ public AppList<APP> build() {
+ final AppList<APP> result = new AppList();
+ final ArrayList<APP> allApps = new ArrayList();
+ final ArrayList<APP> regularApps = new ArrayList();
+ final HashMap<SpecialApp,APP> specialApps = new HashMap();
+ for (AppInfo.Builder<APP> app: mApps.values()) {
+ final AttributionKey attribution = app.getAttribution();
+ final APP appActivity = app.build();
+ allApps.add(appActivity);
+ if (attribution.isSpecialApp()) {
+ specialApps.put(attribution.getSpecialApp(), appActivity);
+ } else {
+ regularApps.add(appActivity);
+ }
+ }
+ result.mAllApps = ImmutableList.copyOf(allApps);
+ result.mRegularApps = ImmutableList.copyOf(regularApps);
+ result.mSpecialApps = ImmutableMap.copyOf(specialApps);
+ return result;
+ }
+
+ public BUILDER get(AttributionKey attribution) {
+ return mApps.get(attribution);
+ }
+
+ public BUILDER put(AttributionKey attribution, BUILDER app) {
+ return mApps.put(attribution, app);
+ }
+ }
+}
diff --git a/tools/powermodel/src/com/android/powermodel/AppPower.java b/tools/powermodel/src/com/android/powermodel/AppPower.java
new file mode 100644
index 000000000000..283982b8eda6
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/AppPower.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableMap;
+
+public class AppPower extends AppInfo {
+ private ImmutableMap<Component, ComponentPower> mComponents;
+
+ private double mAppPowerMah;
+
+
+ private AppPower() {
+ }
+
+ /**
+ * Returns the {@link ComponentPower} for the {@link Component} provided,
+ * or null if this AppPower does not have that component.
+ * @more
+ * If the component was in the power profile for this device, there
+ * will be a component for it, even if there was no power used
+ * by that component. In that case, the
+ * {@link ComponentPower.getUsage() ComponentPower.getUsage()}
+ * method will return 0.
+ */
+ public ComponentPower getComponentPower(Component component) {
+ return mComponents.get(component);
+ }
+
+ public Set<Component> getComponents() {
+ return mComponents.keySet();
+ }
+
+ /**
+ * Return the total power used by this app.
+ */
+ public double getAppPowerMah() {
+ return mAppPowerMah;
+ }
+
+ /**
+ * Builder class for {@link AppPower}
+ */
+ public static class Builder extends AppInfo.Builder<AppPower> {
+ private HashMap<Component, ComponentPower> mComponents = new HashMap();
+
+ public Builder() {
+ }
+
+ public AppPower build() {
+ final AppPower result = new AppPower();
+ init(result);
+ result.mComponents = ImmutableMap.copyOf(mComponents);
+
+ // Add up the components
+ double appPowerMah = 0;
+ for (final ComponentPower componentPower: mComponents.values()) {
+ appPowerMah += componentPower.powerMah;
+ }
+ result.mAppPowerMah = appPowerMah;
+
+ return result;
+ }
+
+ public void addComponentPower(Component component, ComponentPower componentPower) {
+ mComponents.put(component, componentPower);
+ }
+ }
+}
diff --git a/tools/powermodel/src/com/android/powermodel/AttributionKey.java b/tools/powermodel/src/com/android/powermodel/AttributionKey.java
new file mode 100644
index 000000000000..f19e0b7373c7
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/AttributionKey.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.util.Set;
+import java.util.HashSet;
+
+import com.google.common.collect.ImmutableSet;
+
+public class AttributionKey {
+ private final int mUid;
+ private final ImmutableSet<String> mPackages;
+ private final SpecialApp mSpecialApp;
+
+ public AttributionKey(SpecialApp specialApp) {
+ mUid = -1;
+ mPackages = ImmutableSet.of();
+ mSpecialApp = specialApp;
+ }
+
+ public AttributionKey(int uid, Set<String> packages) {
+ mUid = uid;
+ mPackages = ImmutableSet.copyOf(packages);
+ mSpecialApp = null;
+ }
+
+ public ImmutableSet<String> getPackages() {
+ return mPackages;
+ }
+
+ public boolean hasPackage(String pkg) {
+ return mPackages.contains(pkg);
+ }
+
+ public SpecialApp getSpecialApp() {
+ return mSpecialApp;
+ }
+
+ public boolean isSpecialApp() {
+ return mSpecialApp != null;
+ }
+
+ /**
+ * Returns the uid for this attribution, or -1 if there isn't one
+ * (e.g. if it is a special app).
+ */
+ public int getUid() {
+ return mUid;
+ }
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = (31 * hash) + (mUid);
+ hash = (31 * hash) + (mPackages == null ? 0 : mPackages.hashCode());
+ hash = (31 * hash) + (mSpecialApp == null ? 0 : mSpecialApp.hashCode());
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null) {
+ return false;
+ }
+ if (this.getClass() != o.getClass()) {
+ return false;
+ }
+ final AttributionKey that = (AttributionKey)o;
+ return (this.mUid == that.mUid)
+ && this.mPackages != null && this.mPackages.equals(that.mPackages)
+ && this.mSpecialApp != null && this.mSpecialApp.equals(that.mSpecialApp);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder str = new StringBuilder("AttributionKey(");
+ if (mUid >= 0) {
+ str.append(" uid=");
+ str.append(mUid);
+ }
+ if (mPackages.size() > 0) {
+ str.append(" packages=[");
+ for (String pkg: mPackages) {
+ str.append(' ');
+ str.append(pkg);
+ }
+ str.append(" ]");
+ }
+ if (mSpecialApp != null) {
+ str.append(" specialApp=");
+ str.append(mSpecialApp.name());
+ }
+ str.append(" )");
+ return str.toString();
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/BatteryStatsReader.java b/tools/powermodel/src/com/android/powermodel/BatteryStatsReader.java
new file mode 100644
index 000000000000..595c6612dc3b
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/BatteryStatsReader.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.io.InputStream;
+import java.io.IOException;
+import com.android.powermodel.component.ModemBatteryStatsReader;
+
+public class BatteryStatsReader {
+ /**
+ * Construct a reader.
+ */
+ public BatteryStatsReader() {
+ }
+
+ /**
+ * Parse a powermodel.xml file and return a PowerProfile object.
+ *
+ * @param stream An InputStream containing the batterystats output.
+ *
+ * @throws ParseException Thrown when the xml file can not be parsed.
+ * @throws IOException When there is a problem reading the stream.
+ */
+ public static ActivityReport parse(InputStream stream) throws ParseException, IOException {
+ final Parser parser = new Parser(stream);
+ return parser.parse();
+ }
+
+ /**
+ * Implements the reading and power model logic.
+ */
+ private static class Parser {
+ final InputStream mStream;
+ final ActivityReport mResult;
+ RawBatteryStats mBs;
+
+ /**
+ * Constructor to capture the parameters to read.
+ */
+ Parser(InputStream stream) {
+ mStream = stream;
+ mResult = new ActivityReport();
+ }
+
+ /**
+ * Read the stream, parse it, and apply the power model.
+ * Do not call this more than once.
+ */
+ ActivityReport parse() throws ParseException, IOException {
+ mBs = RawBatteryStats.parse(mStream);
+
+ final ActivityReport.Builder report = new ActivityReport.Builder();
+
+ report.addActivity(Component.MODEM, ModemBatteryStatsReader.createActivities(mBs));
+
+ return report.build();
+ }
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/Component.java b/tools/powermodel/src/com/android/powermodel/Component.java
new file mode 100644
index 000000000000..baae6d784c47
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/Component.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+/**
+ * The hardware components that use power on a device.
+ */
+public enum Component {
+ CPU,
+ SCREEN,
+ MODEM,
+ WIFI,
+ BLUETOOTH,
+ VIDEO,
+ AUDIO,
+ FLASHLIGHT,
+ CAMERA,
+ GPS,
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/ComponentActivity.java b/tools/powermodel/src/com/android/powermodel/ComponentActivity.java
new file mode 100644
index 000000000000..c1e2662b7b5f
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/ComponentActivity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+
+/**
+ * Encapsulates the work done by an app (including synthetic apps) that costs power.
+ */
+public class ComponentActivity {
+ public AttributionKey attribution;
+
+ protected ComponentActivity(AttributionKey attribution) {
+ this.attribution = attribution;
+ }
+
+ // TODO: Can we refactor what goes into the activities so this function
+ // doesn't need the global state?
+ /**
+ * Apply the power profile for this component. Subclasses should implement this
+ * to do the per-component calculatinos. The default implementation returns null.
+ * If this method returns null, then there will be no power associated for this
+ * component, which, for example is true with some of the GLOBAL activities.
+ */
+ public ComponentPower applyProfile(ActivityReport activityReport, PowerProfile profile) {
+ return null;
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/ComponentPower.java b/tools/powermodel/src/com/android/powermodel/ComponentPower.java
new file mode 100644
index 000000000000..b22ff8731d6f
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/ComponentPower.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+/**
+ * The hardware component that uses power on a device.
+ * <p>
+ * This base class contains the total power used by each Component in an app.
+ * Subclasses may add more detail, which is a drill-down, but is not to be
+ * <i>added</i> to {@link #powerMah}.
+ */
+public abstract class ComponentPower<ACTIVITY extends ComponentActivity> {
+ /**
+ * The app associated with this ComponentPower.
+ */
+ public AttributionKey attribution;
+
+ /**
+ * The app activity that resulted in the power usage for this component.
+ */
+ public ACTIVITY activity;
+
+ /**
+ * The total power used by this component in this app.
+ */
+ public double powerMah;
+}
diff --git a/tools/powermodel/src/com/android/powermodel/ComponentProfile.java b/tools/powermodel/src/com/android/powermodel/ComponentProfile.java
new file mode 100644
index 000000000000..e76e5fb52481
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/ComponentProfile.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+public class ComponentProfile {
+}
diff --git a/tools/powermodel/src/com/android/powermodel/CsvParser.java b/tools/powermodel/src/com/android/powermodel/CsvParser.java
new file mode 100644
index 000000000000..78cd261306fc
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/CsvParser.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+
+/**
+ * Parses CSV.
+ * <p>
+ * Call parse() with an InputStream.
+ * <p>
+ * CsvLineProcessor.onLine() will be called for each line in the source document.
+ * <p>
+ * To simplify parsing and to protect against using too much memory for bad
+ * data, the maximum field length is {@link #MAX_FIELD_SIZE}.
+ */
+class CsvParser {
+ /**
+ * The maximum size of a single field in bytes.
+ */
+ public static final int MAX_FIELD_SIZE = (8*1024)-1;
+
+ /**
+ * Callback interface for each line of CSV as it is parsed.
+ */
+ interface LineProcessor {
+ /**
+ * A line of CSV was parsed.
+ *
+ * @param lineNumber the line number in the file, starting at 1
+ * @param fields the comma separated fields for the line
+ */
+ void onLine(int lineNumber, ArrayList<String> fields) throws ParseException;
+ }
+
+ /**
+ * Parse the CSV text in input, calling onto processor for each row.
+ */
+ public static void parse(InputStream input, LineProcessor processor)
+ throws IOException, ParseException {
+ final Charset utf8 = StandardCharsets.UTF_8;
+ final byte[] buf = new byte[MAX_FIELD_SIZE+1];
+ int lineNumber = 1;
+ int readPos = 0;
+ int prev = 0;
+ ArrayList<String> fields = new ArrayList<String>();
+ boolean finalBuffer = false;
+ boolean escaping = false;
+ boolean sawQuote = false;
+
+ while (!finalBuffer) {
+ int amt = input.read(buf, readPos, buf.length-readPos);
+ if (amt < 0) {
+ // No more data. Process whatever's left from before.
+ amt = readPos;
+ finalBuffer = true;
+ } else {
+ // Process whatever's left from before, plus the new data.
+ amt += readPos;
+ finalBuffer = false;
+ }
+
+ // Process as much of this buffer as we can.
+ int fieldStart = 0;
+ int index = readPos;
+ int escapeIndex = escaping ? readPos : -1;
+ while (index < amt) {
+ byte c = buf[index];
+ if (c == '\r' || c == '\n') {
+ if (escaping) {
+ // TODO: Quotes do not escape newlines in our CSV dialect,
+ // but we actually see some data where it should.
+ fields.add(new String(buf, fieldStart, escapeIndex-fieldStart));
+ escapeIndex = -1;
+ escaping = false;
+ sawQuote = false;
+ } else {
+ fields.add(new String(buf, fieldStart, index-fieldStart));
+ }
+ // Don't report blank lines
+ if (fields.size() > 1 || (fields.size() == 1 && fields.get(0).length() > 0)) {
+ processor.onLine(lineNumber, fields);
+ }
+ fields = new ArrayList<String>();
+ if (!(c == '\n' && prev == '\r')) {
+ // Don't double increment for dos line endings.
+ lineNumber++;
+ }
+ fieldStart = index = index + 1;
+ } else {
+ if (escaping) {
+ // Field started with a " so quotes are escaped with " and commas
+ // don't matter except when following a single quote.
+ if (c == '"') {
+ if (sawQuote) {
+ buf[escapeIndex] = buf[index];
+ escapeIndex++;
+ sawQuote = false;
+ } else {
+ sawQuote = true;
+ }
+ index++;
+ } else if (sawQuote && c == ',') {
+ fields.add(new String(buf, fieldStart, escapeIndex-fieldStart));
+ fieldStart = index = index + 1;
+ escapeIndex = -1;
+ escaping = false;
+ sawQuote = false;
+ } else {
+ buf[escapeIndex] = buf[index];
+ escapeIndex++;
+ index++;
+ sawQuote = false;
+ }
+ } else {
+ if (c == ',') {
+ fields.add(new String(buf, fieldStart, index-fieldStart));
+ fieldStart = index + 1;
+ } else if (c == '"' && fieldStart == index) {
+ // First character is a "
+ escaping = true;
+ fieldStart = escapeIndex = index + 1;
+ }
+ index++;
+ }
+ }
+ prev = c;
+ }
+
+ // A single field is greater than buf.length, so fail.
+ if (fieldStart == 0 && index == buf.length) {
+ throw new ParseException(lineNumber, "Line is too long: "
+ + new String(buf, 0, 20, utf8) + "...");
+ }
+
+ // Move whatever we didn't process to the beginning of the buffer
+ // and try again.
+ if (fieldStart != amt) {
+ readPos = (escaping ? escapeIndex : index) - fieldStart;
+ System.arraycopy(buf, fieldStart, buf, 0, readPos);
+ } else {
+ readPos = 0;
+ }
+
+ // Process whatever's left over
+ if (finalBuffer) {
+ fields.add(new String(buf, 0, readPos));
+ // If there is any content, return the last line.
+ if (fields.size() > 1 || (fields.size() == 1 && fields.get(0).length() > 0)) {
+ processor.onLine(lineNumber, fields);
+ }
+ }
+ }
+ }
+}
diff --git a/tools/powermodel/src/com/android/powermodel/ParseException.java b/tools/powermodel/src/com/android/powermodel/ParseException.java
new file mode 100644
index 000000000000..e1f232bfc44f
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/ParseException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+public class ParseException extends Exception {
+ public final int line;
+
+ public ParseException(int line, String message, Throwable th) {
+ super(message, th);
+ this.line = line;
+ }
+
+ public ParseException(int line, String message) {
+ this(line, message, null);
+ }
+
+ public ParseException(String message) {
+ this(0, message, null);
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/PowerProfile.java b/tools/powermodel/src/com/android/powermodel/PowerProfile.java
new file mode 100644
index 000000000000..373a9c981ec5
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/PowerProfile.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import com.android.powermodel.component.AudioProfile;
+import com.android.powermodel.component.BluetoothProfile;
+import com.android.powermodel.component.CameraProfile;
+import com.android.powermodel.component.CpuProfile;
+import com.android.powermodel.component.FlashlightProfile;
+import com.android.powermodel.component.GpsProfile;
+import com.android.powermodel.component.ModemProfile;
+import com.android.powermodel.component.ScreenProfile;
+import com.android.powermodel.component.VideoProfile;
+import com.android.powermodel.component.WifiProfile;
+import com.android.powermodel.util.Conversion;
+
+public class PowerProfile {
+
+ // Remaining fields from the android code for which the actual usage is unclear.
+ // battery.capacity
+ // bluetooth.controller.voltage
+ // modem.controller.voltage
+ // gps.voltage
+ // wifi.controller.voltage
+ // radio.on
+ // radio.scanning
+ // radio.active
+ // memory.bandwidths
+ // wifi.batchedscan
+ // wifi.scan
+ // wifi.on
+ // wifi.active
+ // wifi.controller.tx_levels
+
+ private static Pattern RE_CLUSTER_POWER = Pattern.compile("cpu.cluster_power.cluster([0-9]*)");
+ private static Pattern RE_CORE_SPEEDS = Pattern.compile("cpu.core_speeds.cluster([0-9]*)");
+ private static Pattern RE_CORE_POWER = Pattern.compile("cpu.core_power.cluster([0-9]*)");
+
+ private HashMap<Component, ComponentProfile> mComponents = new HashMap();
+
+ /**
+ * Which element we are currently parsing.
+ */
+ enum ElementState {
+ BEGIN,
+ TOP,
+ ITEM,
+ ARRAY,
+ VALUE
+ }
+
+ /**
+ * Implements the reading and power model logic.
+ */
+ private static class Parser {
+ private final InputStream mStream;
+ private final PowerProfile mResult;
+
+ // Builders for the ComponentProfiles.
+ private final AudioProfile mAudio = new AudioProfile();
+ private final BluetoothProfile mBluetooth = new BluetoothProfile();
+ private final CameraProfile mCamera = new CameraProfile();
+ private final CpuProfile.Builder mCpuBuilder = new CpuProfile.Builder();
+ private final FlashlightProfile mFlashlight = new FlashlightProfile();
+ private final GpsProfile.Builder mGpsBuilder = new GpsProfile.Builder();
+ private final ModemProfile.Builder mModemBuilder = new ModemProfile.Builder();
+ private final ScreenProfile mScreen = new ScreenProfile();
+ private final VideoProfile mVideo = new VideoProfile();
+ private final WifiProfile mWifi = new WifiProfile();
+
+ /**
+ * Constructor to capture the parameters to read.
+ */
+ Parser(InputStream stream) {
+ mStream = stream;
+ mResult = new PowerProfile();
+ }
+
+ /**
+ * Read the stream, parse it, and apply the power model.
+ * Do not call this more than once.
+ */
+ PowerProfile parse() throws ParseException {
+ final SAXParserFactory factory = SAXParserFactory.newInstance();
+ AndroidResourceHandler handler = null;
+ try {
+ final SAXParser saxParser = factory.newSAXParser();
+
+ handler = new AndroidResourceHandler() {
+ @Override
+ public void onItem(Locator locator, String name, float value)
+ throws SAXParseException {
+ Parser.this.onItem(locator, name, value);
+ }
+
+ @Override
+ public void onArray(Locator locator, String name, float[] value)
+ throws SAXParseException {
+ Parser.this.onArray(locator, name, value);
+ }
+ };
+
+ saxParser.parse(mStream, handler);
+ } catch (ParserConfigurationException ex) {
+ // Coding error, not runtime error.
+ throw new RuntimeException(ex);
+ } catch (SAXParseException ex) {
+ throw new ParseException(ex.getLineNumber(), ex.getMessage(), ex);
+ } catch (SAXException | IOException ex) {
+ // Make a guess about the line number.
+ throw new ParseException(handler.getLineNumber(), ex.getMessage(), ex);
+ }
+
+ // TODO: This doesn't cover the multiple algorithms. Some refactoring will
+ // be necessary.
+ mResult.mComponents.put(Component.AUDIO, mAudio);
+ mResult.mComponents.put(Component.BLUETOOTH, mBluetooth);
+ mResult.mComponents.put(Component.CAMERA, mCamera);
+ mResult.mComponents.put(Component.CPU, mCpuBuilder.build());
+ mResult.mComponents.put(Component.FLASHLIGHT, mFlashlight);
+ mResult.mComponents.put(Component.GPS, mGpsBuilder.build());
+ mResult.mComponents.put(Component.MODEM, mModemBuilder.build());
+ mResult.mComponents.put(Component.SCREEN, mScreen);
+ mResult.mComponents.put(Component.VIDEO, mVideo);
+ mResult.mComponents.put(Component.WIFI, mWifi);
+
+ return mResult;
+ }
+
+ /**
+ * Handles an item tag in the power_profile.xml.
+ */
+ public void onItem(Locator locator, String name, float value) throws SAXParseException {
+ Integer index;
+ try {
+ if ("ambient.on".equals(name)) {
+ mScreen.ambientMa = value;
+ } else if ("audio".equals(name)) {
+ mAudio.onMa = value;
+ } else if ("bluetooth.controller.idle".equals(name)) {
+ mBluetooth.idleMa = value;
+ } else if ("bluetooth.controller.rx".equals(name)) {
+ mBluetooth.rxMa = value;
+ } else if ("bluetooth.controller.tx".equals(name)) {
+ mBluetooth.txMa = value;
+ } else if ("camera.avg".equals(name)) {
+ mCamera.onMa = value;
+ } else if ("camera.flashlight".equals(name)) {
+ mFlashlight.onMa = value;
+ } else if ("cpu.suspend".equals(name)) {
+ mCpuBuilder.setSuspendMa(value);
+ } else if ("cpu.idle".equals(name)) {
+ mCpuBuilder.setIdleMa(value);
+ } else if ("cpu.active".equals(name)) {
+ mCpuBuilder.setActiveMa(value);
+ } else if ((index = matchIndexedRegex(locator, RE_CLUSTER_POWER, name)) != null) {
+ mCpuBuilder.setClusterPower(index, value);
+ } else if ("gps.on".equals(name)) {
+ mGpsBuilder.setOnMa(value);
+ } else if ("modem.controller.sleep".equals(name)) {
+ mModemBuilder.setSleepMa(value);
+ } else if ("modem.controller.idle".equals(name)) {
+ mModemBuilder.setIdleMa(value);
+ } else if ("modem.controller.rx".equals(name)) {
+ mModemBuilder.setRxMa(value);
+ } else if ("radio.scanning".equals(name)) {
+ mModemBuilder.setScanningMa(value);
+ } else if ("screen.on".equals(name)) {
+ mScreen.onMa = value;
+ } else if ("screen.full".equals(name)) {
+ mScreen.fullMa = value;
+ } else if ("video".equals(name)) {
+ mVideo.onMa = value;
+ } else if ("wifi.controller.idle".equals(name)) {
+ mWifi.idleMa = value;
+ } else if ("wifi.controller.rx".equals(name)) {
+ mWifi.rxMa = value;
+ } else if ("wifi.controller.tx".equals(name)) {
+ mWifi.txMa = value;
+ } else {
+ // TODO: Uncomment this when we have all of the items parsed.
+ // throw new SAXParseException("Unhandled <item name=\"" + name + "\"> element",
+ // locator, ex);
+
+ }
+ } catch (ParseException ex) {
+ throw new SAXParseException(ex.getMessage(), locator, ex);
+ }
+ }
+
+ /**
+ * Handles an array tag in the power_profile.xml.
+ */
+ public void onArray(Locator locator, String name, float[] value) throws SAXParseException {
+ Integer index;
+ try {
+ if ("cpu.clusters.cores".equals(name)) {
+ mCpuBuilder.setCoreCount(Conversion.toIntArray(value));
+ } else if ((index = matchIndexedRegex(locator, RE_CORE_SPEEDS, name)) != null) {
+ mCpuBuilder.setCoreSpeeds(index, Conversion.toIntArray(value));
+ } else if ((index = matchIndexedRegex(locator, RE_CORE_POWER, name)) != null) {
+ mCpuBuilder.setCorePower(index, value);
+ } else if ("gps.signalqualitybased".equals(name)) {
+ mGpsBuilder.setSignalMa(value);
+ } else if ("modem.controller.tx".equals(name)) {
+ mModemBuilder.setTxMa(value);
+ } else {
+ // TODO: Uncomment this when we have all of the items parsed.
+ // throw new SAXParseException("Unhandled <item name=\"" + name + "\"> element",
+ // locator, ex);
+ }
+ } catch (ParseException ex) {
+ throw new SAXParseException(ex.getMessage(), locator, ex);
+ }
+ }
+ }
+
+ /**
+ * SAX XML handler that can parse the android resource files.
+ * In our case, all elements are floats.
+ */
+ abstract static class AndroidResourceHandler extends DefaultHandler {
+ /**
+ * The set of names already processed. Map of name to line number.
+ */
+ private HashMap<String,Integer> mAlreadySeen = new HashMap<String,Integer>();
+
+ /**
+ * Where in the document we are parsing.
+ */
+ private Locator mLocator;
+
+ /**
+ * Which element we are currently parsing.
+ */
+ private ElementState mState = ElementState.BEGIN;
+
+ /**
+ * Saved name from item and array elements.
+ */
+ private String mName;
+
+ /**
+ * The text that is currently being captured, or null if {@link #startCapturingText()}
+ * has not been called.
+ */
+ private StringBuilder mText;
+
+ /**
+ * The array values that have been parsed so for for this array. Null if we are
+ * not inside an array tag.
+ */
+ private ArrayList<Float> mArray;
+
+ /**
+ * Called when an item tag is encountered.
+ */
+ public abstract void onItem(Locator locator, String name, float value)
+ throws SAXParseException;
+
+ /**
+ * Called when an array is encountered.
+ */
+ public abstract void onArray(Locator locator, String name, float[] value)
+ throws SAXParseException;
+
+ /**
+ * If we have a Locator set, return the line number, otherwise return 0.
+ */
+ public int getLineNumber() {
+ return mLocator != null ? mLocator.getLineNumber() : 0;
+ }
+
+ /**
+ * Handle setting the parse location object.
+ */
+ public void setDocumentLocator(Locator locator) {
+ mLocator = locator;
+ }
+
+ /**
+ * Handle beginning of an element.
+ *
+ * @param ns Namespace uri
+ * @param ln Local name (inside namespace)
+ * @param element Tag name
+ */
+ @Override
+ public void startElement(String ns, String ln, String element,
+ Attributes attr) throws SAXException {
+ switch (mState) {
+ case BEGIN:
+ // Outer element, we don't care the tag name.
+ mState = ElementState.TOP;
+ return;
+ case TOP:
+ if ("item".equals(element)) {
+ mState = ElementState.ITEM;
+ saveNameAttribute(attr);
+ startCapturingText();
+ return;
+ } else if ("array".equals(element)) {
+ mState = ElementState.ARRAY;
+ mArray = new ArrayList<Float>();
+ saveNameAttribute(attr);
+ return;
+ }
+ break;
+ case ARRAY:
+ if ("value".equals(element)) {
+ mState = ElementState.VALUE;
+ startCapturingText();
+ return;
+ }
+ break;
+ }
+ throw new SAXParseException("unexpected element: '" + element + "'", mLocator);
+ }
+
+ /**
+ * Handle end of an element.
+ *
+ * @param ns Namespace uri
+ * @param ln Local name (inside namespace)
+ * @param element Tag name
+ */
+ @Override
+ public void endElement(String ns, String ln, String element) throws SAXException {
+ switch (mState) {
+ case ITEM: {
+ float value = parseFloat(finishCapturingText());
+ mState = ElementState.TOP;
+ onItem(mLocator, mName, value);
+ break;
+ }
+ case ARRAY: {
+ final int N = mArray.size();
+ float[] values = new float[N];
+ for (int i=0; i<N; i++) {
+ values[i] = mArray.get(i);
+ }
+ mArray = null;
+ mState = ElementState.TOP;
+ onArray(mLocator, mName, values);
+ break;
+ }
+ case VALUE: {
+ mArray.add(parseFloat(finishCapturingText()));
+ mState = ElementState.ARRAY;
+ break;
+ }
+ }
+ }
+
+ /**
+ * Interstitial text received.
+ *
+ * @throws SAXException if there shouldn't be non-whitespace text here
+ */
+ @Override
+ public void characters(char text[], int start, int length) throws SAXException {
+ if (mText == null && length > 0 && !isWhitespace(text, start, length)) {
+ throw new SAXParseException("unexpected text: '"
+ + firstLine(text, start, length).trim() + "'", mLocator);
+ }
+ if (mText != null) {
+ mText.append(text, start, length);
+ }
+ }
+
+ /**
+ * Begin collecting text from inside an element.
+ */
+ private void startCapturingText() {
+ if (mText != null) {
+ throw new RuntimeException("ASSERTION FAILED: Shouldn't be already capturing"
+ + " text. mState=" + mState.name()
+ + " line=" + mLocator.getLineNumber()
+ + " column=" + mLocator.getColumnNumber());
+ }
+ mText = new StringBuilder();
+ }
+
+ /**
+ * Stop capturing text from inside an element.
+ *
+ * @return the captured text
+ */
+ private String finishCapturingText() {
+ if (mText == null) {
+ throw new RuntimeException("ASSERTION FAILED: Should already be capturing"
+ + " text. mState=" + mState.name()
+ + " line=" + mLocator.getLineNumber()
+ + " column=" + mLocator.getColumnNumber());
+ }
+ final String result = mText.toString().trim();
+ mText = null;
+ return result;
+ }
+
+ /**
+ * Get the "name" attribute.
+ *
+ * @throws SAXParseException if the name attribute is not present or if
+ * the name has already been seen in the file.
+ */
+ private void saveNameAttribute(Attributes attr) throws SAXParseException {
+ final String name = attr.getValue("name");
+ if (name == null) {
+ throw new SAXParseException("expected 'name' attribute", mLocator);
+ }
+ Integer prev = mAlreadySeen.put(name, mLocator.getLineNumber());
+ if (prev != null) {
+ throw new SAXParseException("name '" + name + "' already seen on line: " + prev,
+ mLocator);
+ }
+ mName = name;
+ }
+
+ /**
+ * Gets the float value of the string.
+ *
+ * @throws SAXParseException if 'text' can't be parsed as a float.
+ */
+ private float parseFloat(String text) throws SAXParseException {
+ try {
+ return Float.parseFloat(text);
+ } catch (NumberFormatException ex) {
+ throw new SAXParseException("not a valid float value: '" + text + "'",
+ mLocator, ex);
+ }
+ }
+ }
+
+ /**
+ * Return whether the given substring is all whitespace.
+ */
+ private static boolean isWhitespace(char[] text, int start, int length) {
+ for (int i = start; i < (start + length); i++) {
+ if (!Character.isSpace(text[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Return the contents of text up to the first newline.
+ */
+ private static String firstLine(char[] text, int start, int length) {
+ // TODO: The line number will be wrong if we skip preceeding blank lines.
+ while (length > 0) {
+ if (Character.isSpace(text[start])) {
+ start++;
+ length--;
+ }
+ }
+ int newlen = 0;
+ for (; newlen < length; newlen++) {
+ final char c = text[newlen];
+ if (c == '\n' || c == '\r') {
+ break;
+ }
+ }
+ return new String(text, start, newlen);
+ }
+
+ /**
+ * If the pattern matches, return the first group of that as an Integer.
+ * If not return null.
+ */
+ private static Integer matchIndexedRegex(Locator locator, Pattern pattern, String text)
+ throws SAXParseException {
+ final Matcher m = pattern.matcher(text);
+ if (m.matches()) {
+ try {
+ return Integer.parseInt(m.group(1));
+ } catch (NumberFormatException ex) {
+ throw new SAXParseException("Invalid field name: '" + text + "'", locator, ex);
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public static PowerProfile parse(InputStream stream) throws ParseException {
+ return (new Parser(stream)).parse();
+ }
+
+ private PowerProfile() {
+ }
+
+ public ComponentProfile getComponent(Component component) {
+ return mComponents.get(component);
+ }
+
+}
diff --git a/tools/powermodel/src/com/android/powermodel/PowerReport.java b/tools/powermodel/src/com/android/powermodel/PowerReport.java
new file mode 100644
index 000000000000..76ba67235b0a
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/PowerReport.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * PowerReport contains the summary of all power used on a device
+ * as reported by batterystats or statsd, based on the power profile.
+ */
+public class PowerReport {
+ private AppList<AppPower> mApps;
+ private double mTotalPowerMah;
+
+ private PowerReport() {
+ }
+
+ /**
+ * The total power used by this device for this PowerReport.
+ */
+ public double getTotalPowerMah() {
+ return mTotalPowerMah;
+ }
+
+ public List<AppPower> getAllApps() {
+ return mApps.getAllApps();
+ }
+
+ public List<AppPower> getRegularApps() {
+ return mApps.getRegularApps();
+ }
+
+ public List<AppPower> findApp(String pkg) {
+ return mApps.findApp(pkg);
+ }
+
+ public AppPower findApp(SpecialApp specialApp) {
+ return mApps.findApp(specialApp);
+ }
+
+ public static PowerReport createReport(PowerProfile profile, ActivityReport activityReport) {
+ final PowerReport.Builder powerReport = new PowerReport.Builder();
+ for (final AppActivity appActivity: activityReport.getAllApps()) {
+ final AppPower.Builder appPower = new AppPower.Builder();
+ appPower.setAttribution(appActivity.getAttribution());
+
+ for (final ImmutableMap.Entry<Component,ComponentActivity> entry:
+ appActivity.getComponentActivities().entrySet()) {
+ final ComponentPower componentPower = entry.getValue()
+ .applyProfile(activityReport, profile);
+ if (componentPower != null) {
+ appPower.addComponentPower(entry.getKey(), componentPower);
+ }
+ }
+
+ powerReport.add(appPower);
+ }
+ return powerReport.build();
+ }
+
+ private static class Builder {
+ private AppList.Builder mApps = new AppList.Builder();
+
+ public Builder() {
+ }
+
+ public PowerReport build() {
+ final PowerReport report = new PowerReport();
+
+ report.mApps = mApps.build();
+
+ for (AppPower app: report.mApps.getAllApps()) {
+ report.mTotalPowerMah += app.getAppPowerMah();
+ }
+
+ return report;
+ }
+
+ public void add(AppPower.Builder app) {
+ mApps.put(app.getAttribution(), app);
+ }
+ }
+}
diff --git a/tools/powermodel/src/com/android/powermodel/RawBatteryStats.java b/tools/powermodel/src/com/android/powermodel/RawBatteryStats.java
new file mode 100644
index 000000000000..76c0482772f7
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/RawBatteryStats.java
@@ -0,0 +1,1175 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+public class RawBatteryStats {
+ /**
+ * The factory objects for the records. Initialized in the static block.
+ */
+ private static HashMap<String,RecordFactory> sFactories
+ = new HashMap<String,RecordFactory>();
+
+ /**
+ * The Record objects that have been parsed.
+ */
+ private ArrayList<Record> mRecords = new ArrayList<Record>();
+
+ /**
+ * The Record objects that have been parsed, indexed by type.
+ *
+ * Don't use this before {@link #indexRecords()} has been called.
+ */
+ private ImmutableMap<String,ImmutableList<Record>> mRecordsByType;
+
+ /**
+ * The attribution keys for which we have data (corresponding to UIDs we've seen).
+ * <p>
+ * Does not include the synthetic apps.
+ * <p>
+ * Don't use this before {@link #indexRecords()} has been called.
+ */
+ private ImmutableSet<AttributionKey> mApps;
+
+ /**
+ * The warnings that have been issued during parsing.
+ */
+ private ArrayList<Warning> mWarnings = new ArrayList<Warning>();
+
+ /**
+ * The version of the BatteryStats dumpsys that we are using. This value
+ * is set to -1 initially, and then when parsing the (hopefully) first
+ * line, 'vers', it is set to the correct version.
+ */
+ private int mDumpsysVersion = -1;
+
+ /**
+ * Enum used in the Line annotation to mark whether a field is expected to be
+ * system-wide or scoped to an app.
+ */
+ public enum Scope {
+ SYSTEM,
+ UID
+ }
+
+ /**
+ * Enum used to indicated the expected number of results.
+ */
+ public enum Count {
+ SINGLE,
+ MULTIPLE
+ }
+
+ /**
+ * Annotates classes that represent a line of CSV in the batterystats CSV
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.TYPE)
+ @interface Line {
+ String tag();
+ Scope scope();
+ Count count();
+ }
+
+ /**
+ * Annotates fields that should be parsed automatically from CSV
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.FIELD)
+ @interface Field {
+ /**
+ * The "column" of this field in the most recent version of the CSV.
+ * When parsing old versions, fields that were added will be automatically
+ * removed and the indices will be fixed up.
+ *
+ * The header fields (version, uid, category, type) will be automatically
+ * handled for the base Line type. The index 0 should start after those.
+ */
+ int index();
+
+ /**
+ * First version that this field appears in.
+ */
+ int added() default 0;
+ }
+
+ /**
+ * Each line in the BatteryStats CSV is tagged with a category, that says
+ * which of the time collection modes was used for the data.
+ */
+ public enum Category {
+ INFO("i"),
+ LAST("l"),
+ UNPLUGGED("u"),
+ CURRENT("c");
+
+ public final String tag;
+
+ Category(String tag) {
+ this.tag = tag;
+ }
+ }
+
+ /**
+ * Base class for all lines in a batterystats CSV file.
+ */
+ public static class Record {
+ /**
+ * Whether all of the fields for the indicated version of this record
+ * have been filled in.
+ */
+ public boolean complete;
+
+
+ @Field(index=-4)
+ public int lineVersion;
+
+ @Field(index=-3)
+ public int uid;
+
+ @Field(index=-2)
+ public Category category;
+
+ @Field(index=-1)
+ public String lineType;
+ }
+
+ @Line(tag="bt", scope=Scope.SYSTEM, count=Count.SINGLE)
+ public static class Battery extends Record {
+ // If which != STATS_SINCE_CHARGED, the csv will be "N/A" and we will get
+ // a parsing warning. Nobody uses anything other than STATS_SINCE_CHARGED.
+ @Field(index=0)
+ public int startCount;
+
+ @Field(index=1)
+ public long whichBatteryRealtimeMs;
+
+ @Field(index=2)
+ public long whichBatteryUptimeMs;
+
+ @Field(index=3)
+ public long totalRealtimeMs;
+
+ @Field(index=4)
+ public long totalUptimeMs;
+
+ @Field(index=5)
+ public long getStartClockTimeMs;
+
+ @Field(index=6)
+ public long whichBatteryScreenOffRealtimeMs;
+
+ @Field(index=7)
+ public long whichBatteryScreenOffUptimeMs;
+
+ @Field(index=8)
+ public long estimatedBatteryCapacityMah;
+
+ @Field(index=9)
+ public long minLearnedBatteryCapacityMah;
+
+ @Field(index=10)
+ public long maxLearnedBatteryCapacityMah;
+
+ @Field(index=11)
+ public long screenDozeTimeMs;
+ }
+
+ @Line(tag="gn", scope=Scope.SYSTEM, count=Count.SINGLE)
+ public static class GlobalNetwork extends Record {
+ @Field(index=0)
+ public long mobileRxTotalBytes;
+
+ @Field(index=1)
+ public long mobileTxTotalBytes;
+
+ @Field(index=2)
+ public long wifiRxTotalBytes;
+
+ @Field(index=3)
+ public long wifiTxTotalBytes;
+
+ @Field(index=4)
+ public long mobileRxTotalPackets;
+
+ @Field(index=5)
+ public long mobileTxTotalPackets;
+
+ @Field(index=6)
+ public long wifiRxTotalPackets;
+
+ @Field(index=7)
+ public long wifiTxTotalPackets;
+
+ @Field(index=8)
+ public long btRxTotalBytes;
+
+ @Field(index=9)
+ public long btTxTotalBytes;
+ }
+
+ @Line(tag="gmcd", scope=Scope.SYSTEM, count=Count.SINGLE)
+ public static class GlobalModemController extends Record {
+ @Field(index=0)
+ public long idleMs;
+
+ @Field(index=1)
+ public long rxTimeMs;
+
+ @Field(index=2)
+ public long powerMaMs;
+
+ @Field(index=3)
+ public long[] txTimeMs;
+ }
+
+ @Line(tag="m", scope=Scope.SYSTEM, count=Count.SINGLE)
+ public static class Misc extends Record {
+ @Field(index=0)
+ public long screenOnTimeMs;
+
+ @Field(index=1)
+ public long phoneOnTimeMs;
+
+ @Field(index=2)
+ public long fullWakeLockTimeTotalMs;
+
+ @Field(index=3)
+ public long partialWakeLockTimeTotalMs;
+
+ @Field(index=4)
+ public long mobileRadioActiveTimeMs;
+
+ @Field(index=5)
+ public long mobileRadioActiveAdjustedTimeMs;
+
+ @Field(index=6)
+ public long interactiveTimeMs;
+
+ @Field(index=7)
+ public long powerSaveModeEnabledTimeMs;
+
+ @Field(index=8)
+ public int connectivityChangeCount;
+
+ @Field(index=9)
+ public long deepDeviceIdleModeTimeMs;
+
+ @Field(index=10)
+ public long deepDeviceIdleModeCount;
+
+ @Field(index=11)
+ public long deepDeviceIdlingTimeMs;
+
+ @Field(index=12)
+ public long deepDeviceIdlingCount;
+
+ @Field(index=13)
+ public long mobileRadioActiveCount;
+
+ @Field(index=14)
+ public long mobileRadioActiveUnknownTimeMs;
+
+ @Field(index=15)
+ public long lightDeviceIdleModeTimeMs;
+
+ @Field(index=16)
+ public long lightDeviceIdleModeCount;
+
+ @Field(index=17)
+ public long lightDeviceIdlingTimeMs;
+
+ @Field(index=18)
+ public long lightDeviceIdlingCount;
+
+ @Field(index=19)
+ public long lightLongestDeviceIdleModeTimeMs;
+
+ @Field(index=20)
+ public long deepLongestDeviceIdleModeTimeMs;
+ }
+
+ @Line(tag="nt", scope=Scope.UID, count=Count.SINGLE)
+ public static class Network extends Record {
+ @Field(index=0)
+ public long mobileRxBytes;
+
+ @Field(index=1)
+ public long mobileTxBytes;
+
+ @Field(index=2)
+ public long wifiRxBytes;
+
+ @Field(index=3)
+ public long wifiTxBytes;
+
+ @Field(index=4)
+ public long mobileRxPackets;
+
+ @Field(index=5)
+ public long mobileTxPackets;
+
+ @Field(index=6)
+ public long wifiRxPackets;
+
+ @Field(index=7)
+ public long wifiTxPackets;
+
+ // This is microseconds, because... batterystats.
+ @Field(index=8)
+ public long mobileRadioActiveTimeUs;
+
+ @Field(index=9)
+ public long mobileRadioActiveCount;
+
+ @Field(index=10)
+ public long btRxBytes;
+
+ @Field(index=11)
+ public long btTxBytes;
+
+ @Field(index=12)
+ public long mobileWakeupCount;
+
+ @Field(index=13)
+ public long wifiWakeupCount;
+
+ @Field(index=14)
+ public long mobileBgRxBytes;
+
+ @Field(index=15)
+ public long mobileBgTxBytes;
+
+ @Field(index=16)
+ public long wifiBgRxBytes;
+
+ @Field(index=17)
+ public long wifiBgTxBytes;
+
+ @Field(index=18)
+ public long mobileBgRxPackets;
+
+ @Field(index=19)
+ public long mobileBgTxPackets;
+
+ @Field(index=20)
+ public long wifiBgRxPackets;
+
+ @Field(index=21)
+ public long wifiBgTxPackets;
+ }
+
+ @Line(tag="sgt", scope=Scope.SYSTEM, count=Count.SINGLE)
+ public static class SignalStrengthTime extends Record {
+ @Field(index=0)
+ public long[] phoneSignalStrengthTimeMs;
+ }
+
+ @Line(tag="sst", scope=Scope.SYSTEM, count=Count.SINGLE)
+ public static class SignalScanningTime extends Record {
+ @Field(index=0)
+ public long phoneSignalScanningTimeMs;
+ }
+
+ @Line(tag="uid", scope=Scope.UID, count=Count.MULTIPLE)
+ public static class Uid extends Record {
+ @Field(index=0)
+ public int uidKey;
+
+ @Field(index=1)
+ public String pkg;
+ }
+
+ @Line(tag="vers", scope=Scope.SYSTEM, count=Count.SINGLE)
+ public static class Version extends Record {
+ @Field(index=0)
+ public int dumpsysVersion;
+
+ @Field(index=1)
+ public int parcelVersion;
+
+ @Field(index=2)
+ public String startPlatformVersion;
+
+ @Field(index=3)
+ public String endPlatformVersion;
+ }
+
+ /**
+ * Codes for the warnings to classify warnings without parsing them.
+ */
+ public enum WarningId {
+ /**
+ * A row didn't have enough fields to match any records and let us extract
+ * a line type.
+ */
+ TOO_FEW_FIELDS_FOR_LINE_TYPE,
+
+ /**
+ * We couldn't find a Record for the given line type.
+ */
+ NO_MATCHING_LINE_TYPE,
+
+ /**
+ * Couldn't set the value of a field. Usually this is because the
+ * contents of a numeric type couldn't be parsed.
+ */
+ BAD_FIELD_TYPE,
+
+ /**
+ * There were extra field values in the input text.
+ */
+ TOO_MANY_FIELDS,
+
+ /**
+ * There were fields that we were expecting (for this version
+ * of the dumpsys) that weren't provided in the CSV data.
+ */
+ NOT_ENOUGH_FIELDS,
+
+ /**
+ * The dumpsys version in the 'vers' CSV line couldn't be parsed.
+ */
+ BAD_DUMPSYS_VERSION
+ }
+
+ /**
+ * A non-fatal problem detected during parsing.
+ */
+ public static class Warning {
+ private int mLineNumber;
+ private WarningId mId;
+ private ArrayList<String> mFields;
+ private String mMessage;
+ private String[] mExtras;
+
+ public Warning(int lineNumber, WarningId id, ArrayList<String> fields, String message,
+ String[] extras) {
+ mLineNumber = lineNumber;
+ mId = id;
+ mFields = fields;
+ mMessage = message;
+ mExtras = extras;
+ }
+
+ public int getLineNumber() {
+ return mLineNumber;
+ }
+
+ public ArrayList<String> getFields() {
+ return mFields;
+ }
+
+ public String getMessage() {
+ return mMessage;
+ }
+
+ public String[] getExtras() {
+ return mExtras;
+ }
+ }
+
+ /**
+ * Base class for classes to set fields on Record objects via reflection.
+ */
+ private abstract static class FieldSetter {
+ private int mIndex;
+ private int mAdded;
+ protected java.lang.reflect.Field mField;
+
+ FieldSetter(int index, int added, java.lang.reflect.Field field) {
+ mIndex = index;
+ mAdded = added;
+ mField = field;
+ }
+
+ String getName() {
+ return mField.getName();
+ }
+
+ int getIndex() {
+ return mIndex;
+ }
+
+ int getAdded() {
+ return mAdded;
+ }
+
+ boolean isArray() {
+ return mField.getType().isArray();
+ }
+
+ abstract void setField(int lineNumber, Record object, String value) throws ParseException;
+ abstract void setArray(int lineNumber, Record object, ArrayList<String> values,
+ int startIndex, int endIndex) throws ParseException;
+
+ @Override
+ public String toString() {
+ final String className = getClass().getName();
+ int startIndex = Math.max(className.lastIndexOf('.'), className.lastIndexOf('$'));
+ if (startIndex < 0) {
+ startIndex = 0;
+ } else {
+ startIndex++;
+ }
+ return className.substring(startIndex) + "(index=" + mIndex + " added=" + mAdded
+ + " field=" + mField.getName()
+ + " type=" + mField.getType().getSimpleName()
+ + ")";
+ }
+ }
+
+ /**
+ * Sets int fields on Record objects using reflection.
+ */
+ private static class IntFieldSetter extends FieldSetter {
+ IntFieldSetter(int index, int added, java.lang.reflect.Field field) {
+ super(index, added, field);
+ }
+
+ void setField(int lineNumber, Record object, String value) throws ParseException {
+ try {
+ mField.setInt(object, Integer.parseInt(value.trim()));
+ } catch (NumberFormatException ex) {
+ throw new ParseException(lineNumber, "can't parse as integer: " + value);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | ExceptionInInitializerError ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ void setArray(int lineNumber, Record object, ArrayList<String> values,
+ int startIndex, int endIndex) throws ParseException {
+ try {
+ final int[] array = new int[endIndex-startIndex];
+ for (int i=startIndex; i<endIndex; i++) {
+ final String value = values.get(startIndex+i);
+ try {
+ array[i] = Integer.parseInt(value.trim());
+ } catch (NumberFormatException ex) {
+ throw new ParseException(lineNumber, "can't parse field "
+ + i + " as integer: " + value);
+ }
+ }
+ mField.set(object, array);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | ExceptionInInitializerError ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ /**
+ * Sets long fields on Record objects using reflection.
+ */
+ private static class LongFieldSetter extends FieldSetter {
+ LongFieldSetter(int index, int added, java.lang.reflect.Field field) {
+ super(index, added, field);
+ }
+
+ void setField(int lineNumber, Record object, String value) throws ParseException {
+ try {
+ mField.setLong(object, Long.parseLong(value.trim()));
+ } catch (NumberFormatException ex) {
+ throw new ParseException(lineNumber, "can't parse as long: " + value);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | ExceptionInInitializerError ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ void setArray(int lineNumber, Record object, ArrayList<String> values,
+ int startIndex, int endIndex) throws ParseException {
+ try {
+ final long[] array = new long[endIndex-startIndex];
+ for (int i=0; i<(endIndex-startIndex); i++) {
+ final String value = values.get(startIndex+i);
+ try {
+ array[i] = Long.parseLong(value.trim());
+ } catch (NumberFormatException ex) {
+ throw new ParseException(lineNumber, "can't parse field "
+ + i + " as long: " + value);
+ }
+ }
+ mField.set(object, array);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | ExceptionInInitializerError ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ /**
+ * Sets String fields on Record objects using reflection.
+ */
+ private static class StringFieldSetter extends FieldSetter {
+ StringFieldSetter(int index, int added, java.lang.reflect.Field field) {
+ super(index, added, field);
+ }
+
+ void setField(int lineNumber, Record object, String value) throws ParseException {
+ try {
+ mField.set(object, value);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | ExceptionInInitializerError ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ void setArray(int lineNumber, Record object, ArrayList<String> values,
+ int startIndex, int endIndex) throws ParseException {
+ try {
+ final String[] array = new String[endIndex-startIndex];
+ for (int i=0; i<(endIndex-startIndex); i++) {
+ array[i] = values.get(startIndex+1);
+ }
+ mField.set(object, array);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | ExceptionInInitializerError ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ /**
+ * Sets enum fields on Record objects using reflection.
+ *
+ * To be parsed automatically, enums must have a public final String tag
+ * field, which is the string that will appear in the csv for that enum value.
+ */
+ private static class EnumFieldSetter extends FieldSetter {
+ private final HashMap<String,Enum> mTags = new HashMap<String,Enum>();
+
+ EnumFieldSetter(int index, int added, java.lang.reflect.Field field) {
+ super(index, added, field);
+
+ // Build the mapping of tags to values.
+ final Class<?> fieldType = field.getType();
+
+ java.lang.reflect.Field tagField = null;
+ try {
+ tagField = fieldType.getField("tag");
+ } catch (NoSuchFieldException ex) {
+ throw new RuntimeException("Missing tag field."
+ + " To be parsed automatically, enums must have"
+ + " a String field called tag. Enum class: " + fieldType.getName()
+ + " Containing class: " + field.getDeclaringClass().getName()
+ + " Field: " + field.getName());
+
+ }
+ if (!String.class.equals(tagField.getType())) {
+ throw new RuntimeException("Tag field is not string."
+ + " To be parsed automatically, enums must have"
+ + " a String field called tag. Enum class: " + fieldType.getName()
+ + " Containing class: " + field.getDeclaringClass().getName()
+ + " Field: " + field.getName()
+ + " Tag field type: " + tagField.getType().getName());
+ }
+
+ for (final Object enumValue: fieldType.getEnumConstants()) {
+ String tag = null;
+ try {
+ tag = (String)tagField.get(enumValue);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | ExceptionInInitializerError ex) {
+ throw new RuntimeException(ex);
+ }
+ mTags.put(tag, (Enum)enumValue);
+ }
+ }
+
+ void setField(int lineNumber, Record object, String value) throws ParseException {
+ final Enum enumValue = mTags.get(value);
+ if (enumValue == null) {
+ throw new ParseException(lineNumber, "Could not find enum for field "
+ + getName() + " for tag: " + value);
+ }
+ try {
+ mField.set(object, enumValue);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | ExceptionInInitializerError ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ void setArray(int lineNumber, Record object, ArrayList<String> values,
+ int startIndex, int endIndex) throws ParseException {
+ try {
+ final Object array = Array.newInstance(mField.getType().getComponentType(),
+ endIndex-startIndex);
+ for (int i=0; i<(endIndex-startIndex); i++) {
+ final String value = values.get(startIndex+i);
+ final Enum enumValue = mTags.get(value);
+ if (enumValue == null) {
+ throw new ParseException(lineNumber, "Could not find enum for field "
+ + getName() + " for tag: " + value);
+ }
+ Array.set(array, i, enumValue);
+ }
+ mField.set(object, array);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | ExceptionInInitializerError ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+
+ /**
+ * Factory for the record classes. Uses reflection to create
+ * the fields.
+ */
+ private static class RecordFactory {
+ private String mTag;
+ private Class<? extends Record> mSubclass;
+ private ArrayList<FieldSetter> mFieldSetters;
+
+ RecordFactory(String tag, Class<? extends Record> subclass,
+ ArrayList<FieldSetter> fieldSetters) {
+ mTag = tag;
+ mSubclass = subclass;
+ mFieldSetters = fieldSetters;
+ }
+
+ /**
+ * Create an object of one of the subclasses of Record, and fill
+ * in the fields marked with the Field annotation.
+ *
+ * @return a new Record with the fields filled in. If there are missing
+ * fields, the {@link Record.complete} field will be set to false.
+ */
+ Record create(RawBatteryStats bs, int dumpsysVersion, int lineNumber,
+ ArrayList<String> fieldValues) {
+ final boolean debug = false;
+ Record record = null;
+ try {
+ if (debug) {
+ System.err.println("Creating object: " + mSubclass.getSimpleName());
+ }
+ record = mSubclass.newInstance();
+ } catch (IllegalAccessException | InstantiationException
+ | ExceptionInInitializerError | SecurityException ex) {
+ throw new RuntimeException("Exception creating " + mSubclass.getName()
+ + " for '" + mTag + "' record.", ex);
+ }
+ record.complete = true;
+ int fieldIndex = 0;
+ int setterIndex = 0;
+ while (fieldIndex < fieldValues.size() && setterIndex < mFieldSetters.size()) {
+ final FieldSetter setter = mFieldSetters.get(setterIndex);
+
+ if (dumpsysVersion >= 0 && dumpsysVersion < setter.getAdded()) {
+ // The version being parsed doesn't have the field for this setter,
+ // so skip the setter but not the field.
+ setterIndex++;
+ continue;
+ }
+
+ final String value = fieldValues.get(fieldIndex);
+ try {
+ if (debug) {
+ System.err.println(" setting field " + setter + " to: " + value);
+ }
+ if (setter.isArray()) {
+ setter.setArray(lineNumber, record, fieldValues,
+ fieldIndex, fieldValues.size());
+ // The rest of the fields have been consumed.
+ fieldIndex = fieldValues.size();
+ setterIndex = mFieldSetters.size();
+ break;
+ } else {
+ setter.setField(lineNumber, record, value);
+ }
+ } catch (ParseException ex) {
+ bs.addWarning(lineNumber, WarningId.BAD_FIELD_TYPE, fieldValues,
+ ex.getMessage(), mTag, value);
+ record.complete = false;
+ }
+
+ fieldIndex++;
+ setterIndex++;
+ }
+
+ // If there are extra fields, this record is complete, there are just
+ // extra values, so we issue a warning but don't mark it incomplete.
+ if (fieldIndex < fieldValues.size()) {
+ bs.addWarning(lineNumber, WarningId.TOO_MANY_FIELDS, fieldValues,
+ "Line '" + mTag + "' has extra fields.",
+ mTag, Integer.toString(fieldIndex), Integer.toString(fieldValues.size()));
+ if (debug) {
+ for (int i=0; i<mFieldSetters.size(); i++) {
+ System.err.println(" setter: [" + i + "] " + mFieldSetters.get(i));
+ }
+ }
+ }
+
+ // If we have any fields that are missing, add a warning and return null.
+ for (; setterIndex < mFieldSetters.size(); setterIndex++) {
+ final FieldSetter setter = mFieldSetters.get(setterIndex);
+ if (dumpsysVersion >= 0 && dumpsysVersion >= setter.getAdded()) {
+ bs.addWarning(lineNumber, WarningId.NOT_ENOUGH_FIELDS, fieldValues,
+ "Line '" + mTag + "' missing field: index=" + setterIndex
+ + " name=" + setter.getName(),
+ mTag, Integer.toString(setterIndex));
+ record.complete = false;
+ }
+ }
+
+ return record;
+ }
+ }
+
+ /**
+ * Parse the input stream and return a RawBatteryStats object.
+ */
+ public static RawBatteryStats parse(InputStream input) throws ParseException, IOException {
+ final RawBatteryStats result = new RawBatteryStats();
+ result.parseImpl(input);
+ return result;
+ }
+
+ /**
+ * Get a record.
+ * <p>
+ * If multiple of that record are found, returns the first one. There will already
+ * have been a warning recorded if the count annotation did not match what was in the
+ * csv.
+ * <p>
+ * Returns null if there are no records of that type.
+ */
+ public <T extends Record> T getSingle(Class<T> cl) {
+ final List<Record> list = mRecordsByType.get(cl.getName());
+ if (list == null) {
+ return null;
+ }
+ // Notes:
+ // - List can never be empty because the list itself wouldn't have been added.
+ // - Cast is safe because list was populated based on class name (let's assume
+ // there's only one class loader involved here).
+ return (T)list.get(0);
+ }
+
+ /**
+ * Get a record.
+ * <p>
+ * If multiple of that record are found, returns the first one that matches that uid.
+ * <p>
+ * Returns null if there are no records of that type that match the given uid.
+ */
+ public <T extends Record> T getSingle(Class<T> cl, int uid) {
+ final List<Record> list = mRecordsByType.get(cl.getName());
+ if (list == null) {
+ return null;
+ }
+ for (final Record record: list) {
+ if (record.uid == uid) {
+ // Cast is safe because list was populated based on class name (let's assume
+ // there's only one class loader involved here).
+ return (T)record;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get all the records of the given type.
+ */
+ public <T extends Record> List<T> getMultiple(Class<T> cl) {
+ final List<Record> list = mRecordsByType.get(cl.getName());
+ if (list == null) {
+ return ImmutableList.<T>of();
+ }
+ // Cast is safe because list was populated based on class name (let's assume
+ // there's only one class loader involved here).
+ return ImmutableList.copyOf((List<T>)list);
+ }
+
+ /**
+ * Get the UIDs that are covered by this batterystats dump.
+ */
+ public Set<AttributionKey> getApps() {
+ return mApps;
+ }
+
+ /**
+ * No public constructor. Use {@link #parse}.
+ */
+ private RawBatteryStats() {
+ }
+
+ /**
+ * Get the list of Record objects that were parsed from the csv.
+ */
+ public List<Record> getRecords() {
+ return mRecords;
+ }
+
+ /**
+ * Gets the warnings that were encountered during parsing.
+ */
+ public List<Warning> getWarnings() {
+ return mWarnings;
+ }
+
+ /**
+ * Implementation of the csv parsing.
+ */
+ private void parseImpl(InputStream input) throws ParseException, IOException {
+ // Parse the csv
+ CsvParser.parse(input, new CsvParser.LineProcessor() {
+ @Override
+ public void onLine(int lineNumber, ArrayList<String> fields)
+ throws ParseException {
+ handleCsvLine(lineNumber, fields);
+ }
+ });
+
+ // Gather the records by class name for the getSingle() and getMultiple() functions.
+ indexRecords();
+
+ // Gather the uids from all the places UIDs come from, for getApps().
+ indexApps();
+ }
+
+ /**
+ * Handle a line of CSV input, creating the right Record object.
+ */
+ private void handleCsvLine(int lineNumber, ArrayList<String> fields) throws ParseException {
+ // The standard rows all have the 4 core fields. Anything less isn't what we're
+ // looking for.
+ if (fields.size() <= 4) {
+ addWarning(lineNumber, WarningId.TOO_FEW_FIELDS_FOR_LINE_TYPE, fields,
+ "Line with too few fields (" + fields.size() + ")",
+ Integer.toString(fields.size()));
+ return;
+ }
+
+ final String lineType = fields.get(3);
+
+ // Handle the vers line specially, because we need the version number
+ // to make the rest of the machinery work.
+ if ("vers".equals(lineType)) {
+ final String versionText = fields.get(4);
+ try {
+ mDumpsysVersion = Integer.parseInt(versionText);
+ } catch (NumberFormatException ex) {
+ addWarning(lineNumber, WarningId.BAD_DUMPSYS_VERSION, fields,
+ "Couldn't parse dumpsys version number: '" + versionText,
+ versionText);
+ }
+ }
+
+ // Find the right factory.
+ final RecordFactory factory = sFactories.get(lineType);
+ if (factory == null) {
+ addWarning(lineNumber, WarningId.NO_MATCHING_LINE_TYPE, fields,
+ "No Record for line type '" + lineType + "'",
+ lineType);
+ return;
+ }
+
+ // Create the record.
+ final Record record = factory.create(this, mDumpsysVersion, lineNumber, fields);
+ mRecords.add(record);
+ }
+
+ /**
+ * Add to the list of warnings.
+ */
+ private void addWarning(int lineNumber, WarningId id,
+ ArrayList<String> fields, String message, String... extras) {
+ mWarnings.add(new Warning(lineNumber, id, fields, message, extras));
+ final boolean debug = false;
+ if (debug) {
+ final StringBuilder text = new StringBuilder("line ");
+ text.append(lineNumber);
+ text.append(": WARNING: ");
+ text.append(message);
+ text.append("\n fields: ");
+ for (int i=0; i<fields.size(); i++) {
+ final String field = fields.get(i);
+ if (field.indexOf('"') >= 0) {
+ text.append('"');
+ text.append(field.replace("\"", "\"\""));
+ text.append('"');
+ } else {
+ text.append(field);
+ }
+ if (i != fields.size() - 1) {
+ text.append(',');
+ }
+ }
+ text.append('\n');
+ for (String extra: extras) {
+ text.append(" extra: ");
+ text.append(extra);
+ text.append('\n');
+ }
+ System.err.print(text.toString());
+ }
+ }
+
+ /**
+ * Group records by class name.
+ */
+ private void indexRecords() {
+ final HashMap<String,ArrayList<Record>> map = new HashMap<String,ArrayList<Record>>();
+
+ // Iterate over all of the records
+ for (Record record: mRecords) {
+ final String className = record.getClass().getName();
+
+ ArrayList<Record> list = map.get(className);
+ if (list == null) {
+ list = new ArrayList<Record>();
+ map.put(className, list);
+ }
+
+ list.add(record);
+ }
+
+ // Make it immutable
+ final HashMap<String,ImmutableList<Record>> result
+ = new HashMap<String,ImmutableList<Record>>();
+ for (HashMap.Entry<String,ArrayList<Record>> entry: map.entrySet()) {
+ result.put(entry.getKey(), ImmutableList.copyOf(entry.getValue()));
+ }
+
+ // Initialize here so uninitialized access will result in NPE.
+ mRecordsByType = ImmutableMap.copyOf(result);
+ }
+
+ /**
+ * Collect the UIDs from the csv.
+ *
+ * They come from two places.
+ * <ul>
+ * <li>The uid to package name map entries ({@link #Uid}) at the beginning.
+ * <li>The uid fields of the rest of the entries, some of which might not
+ * have package names associated with them.
+ * </ul>
+ *
+ * TODO: Is this where we should also do the logic about the special UIDs?
+ */
+ private void indexApps() {
+ final HashMap<Integer,HashSet<String>> uids = new HashMap<Integer,HashSet<String>>();
+
+ // The Uid rows, from which we get package names
+ for (Uid record: getMultiple(Uid.class)) {
+ HashSet<String> list = uids.get(record.uidKey);
+ if (list == null) {
+ list = new HashSet<String>();
+ uids.put(record.uidKey, list);
+ }
+ list.add(record.pkg);
+ }
+
+ // The uid fields of everything
+ for (Record record: mRecords) {
+ // The 0 in the INFO records isn't really root, it's just unfilled data.
+ // The root uid (0) will show up practically in every record, but don't force it.
+ if (record.category != Category.INFO) {
+ if (uids.get(record.uid) == null) {
+ // There is no other data about this UID, but it does exist!
+ uids.put(record.uid, new HashSet<String>());
+ }
+ }
+ }
+
+ // Turn our temporary lists of package names into AttributionKeys.
+ final HashSet<AttributionKey> result = new HashSet<AttributionKey>();
+ for (HashMap.Entry<Integer,HashSet<String>> entry: uids.entrySet()) {
+ result.add(new AttributionKey(entry.getKey(), entry.getValue()));
+ }
+
+ // Initialize here so uninitialized access will result in NPE.
+ mApps = ImmutableSet.copyOf(result);
+ }
+
+ /**
+ * Init the factory classes.
+ */
+ static {
+ for (Class<?> cl: RawBatteryStats.class.getClasses()) {
+ final Line lineAnnotation = cl.getAnnotation(Line.class);
+ if (lineAnnotation != null && Record.class.isAssignableFrom(cl)) {
+ final ArrayList<FieldSetter> fieldSetters = new ArrayList<FieldSetter>();
+
+ for (java.lang.reflect.Field field: cl.getFields()) {
+ final Field fa = field.getAnnotation(Field.class);
+ if (fa != null) {
+ final Class<?> fieldType = field.getType();
+ final Class<?> innerType = fieldType.isArray()
+ ? fieldType.getComponentType()
+ : fieldType;
+ if (Integer.TYPE.equals(innerType)) {
+ fieldSetters.add(new IntFieldSetter(fa.index(), fa.added(), field));
+ } else if (Long.TYPE.equals(innerType)) {
+ fieldSetters.add(new LongFieldSetter(fa.index(), fa.added(), field));
+ } else if (String.class.equals(innerType)) {
+ fieldSetters.add(new StringFieldSetter(fa.index(), fa.added(), field));
+ } else if (innerType.isEnum()) {
+ fieldSetters.add(new EnumFieldSetter(fa.index(), fa.added(), field));
+ } else {
+ throw new RuntimeException("Unsupported field type '"
+ + fieldType.getName() + "' on "
+ + cl.getName() + "." + field.getName());
+ }
+ }
+ }
+ // Sort by index
+ Collections.sort(fieldSetters, new Comparator<FieldSetter>() {
+ @Override
+ public int compare(FieldSetter a, FieldSetter b) {
+ return a.getIndex() - b.getIndex();
+ }
+ });
+ // Only the last one can be an array
+ for (int i=0; i<fieldSetters.size()-1; i++) {
+ if (fieldSetters.get(i).isArray()) {
+ throw new RuntimeException("Only the last (highest index) @Field"
+ + " in class " + cl.getName() + " can be an array: "
+ + fieldSetters.get(i).getName());
+ }
+ }
+ // Add to the map
+ sFactories.put(lineAnnotation.tag(), new RecordFactory(lineAnnotation.tag(),
+ (Class<Record>)cl, fieldSetters));
+ }
+ }
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/SpecialApp.java b/tools/powermodel/src/com/android/powermodel/SpecialApp.java
new file mode 100644
index 000000000000..df1e1fbda5f6
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/SpecialApp.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+/**
+ * Identifiers for well-known apps that have unique characteristics.
+ *
+ * @more
+ * This includes three categories:
+ * <ul>
+ * <li><b>Built-in system components</b> – These have predefined UIDs that are
+ * always the same. For example, the system UID is always 1000.</li>
+ * <li><b>Well known apps with shared UIDs</b> – These do not have predefined
+ * UIDs (i.e. are different on each device), but since they have shared UIDs
+ * with varying sets of package names (GmsCore is the canonical example), we
+ * have special logic to capture these into a single entity with a well defined
+ * key. These have the {@link #uid uid} field set to
+ * {@link Uid#UID_VARIES Uid.UID_VARIES}.</li>
+ * <li><b>Synthetic remainder app</b> – The {@link #REMAINDER REMAINDER} app doesn't
+ * represent a real app. It contains accounting for usage which is not attributed
+ * to any UID. This app has the {@link #uid uid} field set to
+ * {@link Uid#UID_SYNTHETIC Uid.UID_SYNTHETIC}.</li>
+ * </ul>
+ */
+public enum SpecialApp {
+
+ /**
+ * Synthetic app that accounts for the remaining amount of resources used
+ * that is unaccounted for by apps, or overcounted because of inaccuracies
+ * in the model.
+ */
+ REMAINDER(Uid.UID_SYNTHETIC),
+
+ /**
+ * Synthetic app that holds system-wide numbers, for example the total amount
+ * of various resources used, device-wide.
+ */
+ GLOBAL(Uid.UID_SYNTHETIC),
+
+ SYSTEM(1000),
+
+ GOOGLE_SERVICES(Uid.UID_VARIES);
+
+ /**
+ * Constants for SpecialApps where the uid is not actually a UID.
+ */
+ public static class Uid {
+ /**
+ * Constant to indicate that this special app does not have a fixed UID.
+ */
+ public static final int UID_VARIES = -1;
+
+ /**
+ * Constant to indicate that this special app is not actually an app with a UID.
+ *
+ * @see SpecialApp#REMAINDER
+ * @see SpecialApp#GLOBAL
+ */
+ public static final int UID_SYNTHETIC = -2;
+ }
+
+ /**
+ * The fixed UID value of this special app, or {@link #UID_VARIES} if there
+ * isn't one.
+ */
+ public final int uid;
+
+ private SpecialApp(int uid) {
+ this.uid = uid;
+ }
+}
diff --git a/tools/powermodel/src/com/android/powermodel/component/AudioProfile.java b/tools/powermodel/src/com/android/powermodel/component/AudioProfile.java
new file mode 100644
index 000000000000..63ff3a6b09fa
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/AudioProfile.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class AudioProfile extends ComponentProfile {
+ public float onMa;
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/BluetoothProfile.java b/tools/powermodel/src/com/android/powermodel/component/BluetoothProfile.java
new file mode 100644
index 000000000000..8f5e7d0ae1df
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/BluetoothProfile.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class BluetoothProfile extends ComponentProfile {
+ public float idleMa;
+ public float rxMa;
+ public float txMa;
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/CameraProfile.java b/tools/powermodel/src/com/android/powermodel/component/CameraProfile.java
new file mode 100644
index 000000000000..8ee22d03268c
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/CameraProfile.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class CameraProfile extends ComponentProfile {
+ public float onMa;
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/CpuProfile.java b/tools/powermodel/src/com/android/powermodel/component/CpuProfile.java
new file mode 100644
index 000000000000..0b34fc82622a
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/CpuProfile.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class CpuProfile extends ComponentProfile {
+ public float suspendMa;
+ public float idleMa;
+ public float activeMa;
+ public Cluster[] clusters;
+
+ public static class Cluster {
+ public int coreCount;
+ public float onMa;
+ public Frequency[] frequencies;
+ }
+
+ public static class Frequency {
+ public int speedHz;
+ public float onMa;
+ }
+
+ public static class Builder {
+ private float mSuspendMa;
+ private float mIdleMa;
+ private float mActiveMa;
+ private int[] mCoreCount;
+ private HashMap<Integer,Float> mClusterOnPower = new HashMap<Integer,Float>();
+ private HashMap<Integer,int[]> mCoreSpeeds = new HashMap<Integer,int[]>();
+ private HashMap<Integer,float[]> mCorePower = new HashMap<Integer,float[]>();
+
+ public Builder() {
+ }
+
+ public void setSuspendMa(float value) throws ParseException {
+ mSuspendMa = value;
+ }
+
+ public void setIdleMa(float value) throws ParseException {
+ mIdleMa = value;
+ }
+
+ public void setActiveMa(float value) throws ParseException {
+ mActiveMa = value;
+ }
+
+ public void setCoreCount(int[] value) throws ParseException {
+ mCoreCount = Arrays.copyOf(value, value.length);
+ }
+
+ public void setClusterPower(int cluster, float value) throws ParseException {
+ mClusterOnPower.put(cluster, value);
+ }
+
+ public void setCoreSpeeds(int cluster, int[] value) throws ParseException {
+ mCoreSpeeds.put(cluster, Arrays.copyOf(value, value.length));
+ float[] power = mCorePower.get(cluster);
+ if (power != null && value.length != power.length) {
+ throw new ParseException("length of cpu.core_speeds.cluster" + cluster
+ + " (" + value.length + ") is different from length of"
+ + " cpu.core_power.cluster" + cluster + " (" + power.length + ")");
+ }
+ if (mCoreCount != null && cluster >= mCoreCount.length) {
+ throw new ParseException("cluster " + cluster
+ + " in cpu.core_speeds.cluster" + cluster
+ + " is larger than the number of clusters specified in cpu.clusters.cores ("
+ + mCoreCount.length + ")");
+ }
+ }
+
+ public void setCorePower(int cluster, float[] value) throws ParseException {
+ mCorePower.put(cluster, Arrays.copyOf(value, value.length));
+ int[] speeds = mCoreSpeeds.get(cluster);
+ if (speeds != null && value.length != speeds.length) {
+ throw new ParseException("length of cpu.core_power.cluster" + cluster
+ + " (" + value.length + ") is different from length of"
+ + " cpu.clusters.cores" + cluster + " (" + speeds.length + ")");
+ }
+ if (mCoreCount != null && cluster >= mCoreCount.length) {
+ throw new ParseException("cluster " + cluster
+ + " in cpu.core_power.cluster" + cluster
+ + " is larger than the number of clusters specified in cpu.clusters.cores ("
+ + mCoreCount.length + ")");
+ }
+ }
+
+ public CpuProfile build() throws ParseException {
+ final CpuProfile result = new CpuProfile();
+
+ // Validate cluster count
+
+ // All null or none null
+ // TODO
+
+ // Same size
+ // TODO
+
+ // No gaps
+ // TODO
+
+ // Fill in values
+ result.suspendMa = mSuspendMa;
+ result.idleMa = mIdleMa;
+ result.activeMa = mActiveMa;
+ if (mCoreCount != null) {
+ result.clusters = new Cluster[mCoreCount.length];
+ for (int i = 0; i < result.clusters.length; i++) {
+ final Cluster cluster = result.clusters[i] = new Cluster();
+ cluster.coreCount = mCoreCount[i];
+ cluster.onMa = mClusterOnPower.get(i);
+ int[] speeds = mCoreSpeeds.get(i);
+ float[] power = mCorePower.get(i);
+ cluster.frequencies = new Frequency[speeds.length];
+ for (int j = 0; j < speeds.length; j++) {
+ final Frequency freq = cluster.frequencies[j] = new Frequency();
+ freq.speedHz = speeds[j];
+ freq.onMa = power[j];
+ }
+ }
+ }
+
+ return result;
+ }
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/FlashlightProfile.java b/tools/powermodel/src/com/android/powermodel/component/FlashlightProfile.java
new file mode 100644
index 000000000000..c85f3ff236fd
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/FlashlightProfile.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class FlashlightProfile extends ComponentProfile {
+ public float onMa;
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/GpsProfile.java b/tools/powermodel/src/com/android/powermodel/component/GpsProfile.java
new file mode 100644
index 000000000000..83c06a7881ca
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/GpsProfile.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class GpsProfile extends ComponentProfile {
+ public float onMa;
+ public float[] signalQualityMa;
+
+ public static class Builder {
+ private float onMa;
+ private float[] mSignalQualityMa;
+
+ public Builder() {
+ }
+
+ public void setOnMa(float value) throws ParseException {
+ onMa = value;
+ }
+
+ public void setSignalMa(float[] value) throws ParseException {
+ mSignalQualityMa = value;
+ }
+
+ public GpsProfile build() throws ParseException {
+ GpsProfile result = new GpsProfile();
+ result.onMa = onMa;
+ result.signalQualityMa = mSignalQualityMa == null
+ ? new float[0]
+ : Arrays.copyOf(mSignalQualityMa, mSignalQualityMa.length);
+ return result;
+ }
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/ModemAppActivity.java b/tools/powermodel/src/com/android/powermodel/component/ModemAppActivity.java
new file mode 100644
index 000000000000..cb70051f1ae6
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/ModemAppActivity.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import com.android.powermodel.ActivityReport;
+import com.android.powermodel.AttributionKey;
+import com.android.powermodel.Component;
+import com.android.powermodel.ComponentActivity;
+import com.android.powermodel.PowerProfile;
+import com.android.powermodel.util.Conversion;
+
+/**
+ * Encapsulates the work done by the celluar modem on behalf of an app.
+ */
+public class ModemAppActivity extends ComponentActivity {
+ /**
+ * Construct a new ModemAppActivity.
+ */
+ public ModemAppActivity(AttributionKey attribution) {
+ super(attribution);
+ }
+
+ /**
+ * The number of packets received by the app.
+ */
+ public long rxPacketCount;
+
+ /**
+ * The number of packets sent by the app.
+ */
+ public long txPacketCount;
+
+ @Override
+ public ModemAppPower applyProfile(ActivityReport activityReport, PowerProfile profile) {
+ // Profile
+ final ModemProfile modemProfile = (ModemProfile)profile.getComponent(Component.MODEM);
+ if (modemProfile == null) {
+ // TODO: This is kind of a big problem... Should this throw instead?
+ return null;
+ }
+
+ // Activity
+ final ModemGlobalActivity global
+ = (ModemGlobalActivity)activityReport.findGlobalComponent(Component.MODEM);
+ if (global == null) {
+ return null;
+ }
+
+ final double averageModemPowerMa = getAverageModemPowerMa(modemProfile);
+ final long totalPacketCount = global.rxPacketCount + global.txPacketCount;
+ final long appPacketCount = this.rxPacketCount + this.txPacketCount;
+
+ final ModemAppPower result = new ModemAppPower();
+ result.attribution = this.attribution;
+ result.activity = this;
+ result.powerMah = Conversion.msToHr(
+ (totalPacketCount > 0 ? (appPacketCount / (double)totalPacketCount) : 0)
+ * global.totalActiveTimeMs
+ * averageModemPowerMa);
+ return result;
+ }
+
+ static final double getAverageModemPowerMa(ModemProfile profile) {
+ double sumMa = profile.getRxMa();
+ for (float powerAtTxLevelMa: profile.getTxMa()) {
+ sumMa += powerAtTxLevelMa;
+ }
+ return sumMa / (profile.getTxMa().length + 1);
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/ModemAppPower.java b/tools/powermodel/src/com/android/powermodel/component/ModemAppPower.java
new file mode 100644
index 000000000000..f5531272d0b9
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/ModemAppPower.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import com.android.powermodel.Component;
+import com.android.powermodel.ComponentPower;
+
+public class ModemAppPower extends ComponentPower<ModemAppActivity> {
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/ModemBatteryStatsReader.java b/tools/powermodel/src/com/android/powermodel/component/ModemBatteryStatsReader.java
new file mode 100644
index 000000000000..6dbfbc24d1ef
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/ModemBatteryStatsReader.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.ArrayList;
+import java.util.List;
+import com.android.powermodel.AttributionKey;
+import com.android.powermodel.ComponentActivity;
+import com.android.powermodel.RawBatteryStats;
+import com.android.powermodel.SpecialApp;
+
+public class ModemBatteryStatsReader {
+ private ModemBatteryStatsReader() {
+ }
+
+ public static List<ComponentActivity> createActivities(RawBatteryStats bs) {
+ final List<ComponentActivity> result = new ArrayList<ComponentActivity>();
+
+ // The whole system
+ createGlobal(result, bs);
+
+ // The apps
+ createApps(result, bs);
+
+ // The synthetic "cell" app.
+ createRemainder(result, bs);
+
+ return result;
+ }
+
+ private static void createGlobal(List<ComponentActivity> result, RawBatteryStats bs) {
+ final ModemGlobalActivity global
+ = new ModemGlobalActivity(new AttributionKey(SpecialApp.GLOBAL));
+
+ final RawBatteryStats.GlobalNetwork gn = bs.getSingle(RawBatteryStats.GlobalNetwork.class);
+ final RawBatteryStats.Misc misc = bs.getSingle(RawBatteryStats.Misc.class);
+
+ // Null here just means no network activity.
+ if (gn != null && misc != null) {
+ global.rxPacketCount = gn.mobileRxTotalPackets;
+ global.txPacketCount = gn.mobileTxTotalPackets;
+
+ global.totalActiveTimeMs = misc.mobileRadioActiveTimeMs;
+ }
+
+ result.add(global);
+ }
+
+ private static void createApps(List<ComponentActivity> result, RawBatteryStats bs) {
+ for (AttributionKey key: bs.getApps()) {
+ final int uid = key.getUid();
+ final RawBatteryStats.Network network
+ = bs.getSingle(RawBatteryStats.Network.class, uid);
+
+ // Null here just means no network activity.
+ if (network != null) {
+ final ModemAppActivity app = new ModemAppActivity(key);
+
+ app.rxPacketCount = network.mobileRxPackets;
+ app.txPacketCount = network.mobileTxPackets;
+
+ result.add(app);
+ }
+ }
+ }
+
+ private static void createRemainder(List<ComponentActivity> result, RawBatteryStats bs) {
+ final RawBatteryStats.SignalStrengthTime strength
+ = bs.getSingle(RawBatteryStats.SignalStrengthTime.class);
+ final RawBatteryStats.SignalScanningTime scanning
+ = bs.getSingle(RawBatteryStats.SignalScanningTime.class);
+ final RawBatteryStats.Misc misc = bs.getSingle(RawBatteryStats.Misc.class);
+
+ if (strength != null && scanning != null && misc != null) {
+ final ModemRemainderActivity remainder
+ = new ModemRemainderActivity(new AttributionKey(SpecialApp.REMAINDER));
+
+ // Signal strength buckets
+ remainder.strengthTimeMs = strength.phoneSignalStrengthTimeMs;
+
+ // Time spent scanning
+ remainder.scanningTimeMs = scanning.phoneSignalScanningTimeMs;
+
+ // Unaccounted for active time
+ final long totalActiveTimeMs = misc.mobileRadioActiveTimeMs;
+ long appActiveTimeMs = 0;
+ for (RawBatteryStats.Network nw: bs.getMultiple(RawBatteryStats.Network.class)) {
+ appActiveTimeMs += nw.mobileRadioActiveTimeUs / 1000;
+ }
+ remainder.activeTimeMs = totalActiveTimeMs - appActiveTimeMs;
+
+ result.add(remainder);
+ }
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/ModemGlobalActivity.java b/tools/powermodel/src/com/android/powermodel/component/ModemGlobalActivity.java
new file mode 100644
index 000000000000..a53b53eede2b
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/ModemGlobalActivity.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import com.android.powermodel.ActivityReport;
+import com.android.powermodel.AttributionKey;
+import com.android.powermodel.ComponentActivity;
+import com.android.powermodel.ComponentPower;
+import com.android.powermodel.PowerProfile;
+
+/**
+ * Encapsulates total work done by the modem for the device.
+ */
+public class ModemGlobalActivity extends ComponentActivity {
+ /**
+ * Construct a new ModemGlobalActivity.
+ */
+ public ModemGlobalActivity(AttributionKey attribution) {
+ super(attribution);
+ }
+
+ /**
+ * Returns the total number of packets received in the whole device.
+ */
+ public long rxPacketCount;
+
+ /**
+ * Returns the total number of packets sent in the whole device.
+ */
+ public long txPacketCount;
+
+ /**
+ * Returns the total time the radio was active in the whole device.
+ */
+ public long totalActiveTimeMs;
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/ModemProfile.java b/tools/powermodel/src/com/android/powermodel/component/ModemProfile.java
new file mode 100644
index 000000000000..cda72ee205e3
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/ModemProfile.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class ModemProfile extends ComponentProfile {
+ public float sleepMa;
+ public float idleMa;
+ public float scanningMa;
+ public float rxMa;
+ public float[] txMa;
+
+ public float getSleepMa() {
+ return sleepMa;
+ }
+
+ public float getIdleMa() {
+ return idleMa;
+ }
+
+ public float getRxMa() {
+ return rxMa;
+ }
+
+ public float[] getTxMa() {
+ return Arrays.copyOf(txMa, txMa.length);
+ }
+
+ public float getScanningMa() {
+ return scanningMa;
+ }
+
+ public static class Builder {
+ private float mSleepMa;
+ private float mIdleMa;
+ private float mRxMa;
+ private float[] mTxMa;
+ private float mScanningMa;
+
+ public Builder() {
+ }
+
+ public void setSleepMa(float value) throws ParseException {
+ mSleepMa = value;
+ }
+
+ public void setIdleMa(float value) throws ParseException {
+ mIdleMa = value;
+ }
+
+ public void setRxMa(float value) throws ParseException {
+ mRxMa = value;
+ }
+
+ public void setTxMa(float[] value) throws ParseException {
+ mTxMa = Arrays.copyOf(value, value.length);
+ }
+
+ public void setScanningMa(float value) throws ParseException {
+ mScanningMa = value;
+ }
+
+ public ModemProfile build() throws ParseException {
+ ModemProfile result = new ModemProfile();
+ result.sleepMa = mSleepMa;
+ result.idleMa = mIdleMa;
+ result.rxMa = mRxMa;
+ result.txMa = mTxMa == null ? new float[0] : mTxMa;
+ result.scanningMa = mScanningMa;
+ return result;
+ }
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/ModemRemainderActivity.java b/tools/powermodel/src/com/android/powermodel/component/ModemRemainderActivity.java
new file mode 100644
index 000000000000..0e268c21d01d
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/ModemRemainderActivity.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import com.android.powermodel.ActivityReport;
+import com.android.powermodel.AttributionKey;
+import com.android.powermodel.Component;
+import com.android.powermodel.ComponentActivity;
+import com.android.powermodel.PowerProfile;
+import com.android.powermodel.util.Conversion;
+
+/**
+ * Encapsulates the work done by the remaining
+ */
+public class ModemRemainderActivity extends ComponentActivity {
+ /**
+ * Construct a new ModemRemainderActivity.
+ */
+ public ModemRemainderActivity(AttributionKey attribution) {
+ super(attribution);
+ }
+
+ /**
+ * Number of milliseconds spent at each of the signal strengths.
+ */
+ public long[] strengthTimeMs;
+
+ /**
+ * Number of milliseconds spent scanning for a network.
+ */
+ public long scanningTimeMs;
+
+ /**
+ * Number of milliseconds that the radio is active for reasons other
+ * than an app transmitting and receiving data.
+ */
+ public long activeTimeMs;
+
+ @Override
+ public ModemRemainderPower applyProfile(ActivityReport activityReport, PowerProfile profile) {
+ // Profile
+ final ModemProfile modemProfile = (ModemProfile)profile.getComponent(Component.MODEM);
+ if (modemProfile == null) {
+ return null;
+ }
+
+ // Activity
+ final ModemRemainderPower result = new ModemRemainderPower();
+ result.attribution = this.attribution;
+ result.activity = this;
+
+ // strengthMah
+ // TODO: If the array lengths don't match... then?
+ result.strengthMah = new double[this.strengthTimeMs.length];
+ for (int i=0; i<this.strengthTimeMs.length; i++) {
+ result.strengthMah[i] = Conversion.msToHr(
+ this.strengthTimeMs[i] * modemProfile.getTxMa()[i]);
+ result.powerMah += result.strengthMah[i];
+ }
+
+ // scanningMah
+ result.scanningMah = Conversion.msToHr(this.scanningTimeMs * modemProfile.getScanningMa());
+ result.powerMah += result.scanningMah;
+
+ // activeMah
+ result.activeMah = Conversion.msToHr(
+ this.activeTimeMs * ModemAppActivity.getAverageModemPowerMa(modemProfile));
+ result.powerMah += result.activeMah;
+
+ return result;
+ }
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/ModemRemainderPower.java b/tools/powermodel/src/com/android/powermodel/component/ModemRemainderPower.java
new file mode 100644
index 000000000000..7f38cd342e2f
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/ModemRemainderPower.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import com.android.powermodel.Component;
+import com.android.powermodel.ComponentPower;
+
+public class ModemRemainderPower extends ComponentPower<ModemRemainderActivity> {
+
+ public double[] strengthMah;
+
+ public double scanningMah;
+
+ public double activeMah;
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/ScreenProfile.java b/tools/powermodel/src/com/android/powermodel/component/ScreenProfile.java
new file mode 100644
index 000000000000..e1051c69dec6
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/ScreenProfile.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class ScreenProfile extends ComponentProfile {
+ public float onMa;
+ public float fullMa;
+ public float ambientMa;
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/VideoProfile.java b/tools/powermodel/src/com/android/powermodel/component/VideoProfile.java
new file mode 100644
index 000000000000..515279552245
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/VideoProfile.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class VideoProfile extends ComponentProfile {
+ public float onMa;
+}
+
+
diff --git a/tools/powermodel/src/com/android/powermodel/component/WifiProfile.java b/tools/powermodel/src/com/android/powermodel/component/WifiProfile.java
new file mode 100644
index 000000000000..6f424bf0837d
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/component/WifiProfile.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.component;
+
+import java.util.Arrays;
+
+import com.android.powermodel.ComponentProfile;
+import com.android.powermodel.ParseException;
+
+public class WifiProfile extends ComponentProfile {
+ public float idleMa;
+ public float rxMa;
+ public float txMa;
+}
+
diff --git a/tools/powermodel/src/com/android/powermodel/util/Conversion.java b/tools/powermodel/src/com/android/powermodel/util/Conversion.java
new file mode 100644
index 000000000000..e556c251a1c9
--- /dev/null
+++ b/tools/powermodel/src/com/android/powermodel/util/Conversion.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel.util;
+
+public class Conversion {
+
+ /**
+ * Convert the the float[] to an int[].
+ * <p>
+ * Values are rounded to the nearest integral value. Null input
+ * results in null output.
+ */
+ public static int[] toIntArray(float[] value) {
+ if (value == null) {
+ return null;
+ }
+ int[] result = new int[value.length];
+ for (int i=0; i<result.length; i++) {
+ result[i] = (int)(value[i] + 0.5f);
+ }
+ return result;
+ }
+
+ public static double msToHr(double ms) {
+ return ms / 3600.0 / 1000.0;
+ }
+
+ /**
+ * No public constructor.
+ */
+ private Conversion() {
+ }
+}
diff --git a/tools/powermodel/test-resource/bs.csv b/tools/powermodel/test-resource/bs.csv
new file mode 100644
index 000000000000..6e84120168ce
--- /dev/null
+++ b/tools/powermodel/test-resource/bs.csv
@@ -0,0 +1,7 @@
+9,0,i,vers,32,177,PPR1.180326.002,PQ1A.181105.015
+9,0,i,uid,10139,com.google.android.gm
+9,0,l,gn,108060756,17293456,4896592,3290614,97840,72941,6903,8107,390,105
+9,0,l,m,2590630,0,384554,3943868,5113727,265,2565483,0,16,0,0,0,0,192,25331,3472068,17,3543323,14,614050,0
+9,10139,l,nt,13688501,534571,13842,7792,9925,5577,30,67,190051799,27,0,0,5,3,126020,42343,13842,7792,207,167,30,67
+9,0,l,sgt,3066958,0,34678,1643364,7045084
+9,0,l,sst,2443805
diff --git a/tools/powermodel/test-resource/power_profile.xml b/tools/powermodel/test-resource/power_profile.xml
new file mode 100644
index 000000000000..8e388eadc608
--- /dev/null
+++ b/tools/powermodel/test-resource/power_profile.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- Test power profile that parses correctly. -->
+<device>
+ <item name="battery.capacity">2915</item>
+
+ <!-- Number of cores each CPU cluster contains -->
+ <array name="cpu.clusters.cores">
+ <value>4</value>
+ <value>2</value>
+ </array>
+
+ <!-- Power consumption when CPU is suspended -->
+ <item name="cpu.suspend">1.3</item>
+
+ <!-- Additional power consumption when CPU is in a kernel idle loop -->
+ <item name="cpu.idle">3.9</item>
+
+ <!-- Additional power consumption by CPU excluding cluster and core when
+ running -->
+ <item name="cpu.active">18.33</item>
+
+ <!-- Additional power consumption by CPU cluster0 itself when running
+ excluding cores in it -->
+ <item name="cpu.cluster_power.cluster0">2.41</item>
+
+ <!-- Additional power consumption by CPU cluster1 itself when running
+ excluding cores in it -->
+ <item name="cpu.cluster_power.cluster1">5.29</item>
+
+ <!-- Different CPU speeds as reported in
+ /sys/devices/system/cpu/cpu0/cpufreq/stats/scaling_available_frequencies -->
+ <array name="cpu.core_speeds.cluster0">
+ <value>100000</value>
+ <value>303200</value>
+ <value>380000</value>
+ <value>476000</value>
+ <value>552800</value>
+ <value>648800</value>
+ <value>725600</value>
+ <value>802400</value>
+ <value>879200</value>
+ </array>
+
+ <!-- Different CPU speeds as reported in
+ /sys/devices/system/cpu/cpu4/cpufreq/stats/scaling_available_frequencies -->
+ <array name="cpu.core_speeds.cluster1">
+ <value>825600</value>
+ <value>902400</value>
+ <value>979200</value>
+ <value>1056000</value>
+ <value>1209600</value>
+ <value>1286400</value>
+ <value>1363200</value>
+ </array>
+
+ <!-- Additional power used by a CPU core from cluster 0 when running at
+ different speeds, excluding cluster and active cost -->
+ <array name="cpu.core_power.cluster0">
+ <value>0.29</value>
+ <value>0.63</value>
+ <value>1.23</value>
+ <value>1.24</value>
+ <value>2.47</value>
+ <value>2.54</value>
+ <value>3.60</value>
+ <value>3.64</value>
+ <value>4.42</value>
+ </array>
+
+ <!-- Additional power used by a CPU core from cluster 1 when running at
+ different speeds, excluding cluster and active cost -->
+ <array name="cpu.core_power.cluster1">
+ <value>28.98</value>
+ <value>31.40</value>
+ <value>33.33</value>
+ <value>40.12</value>
+ <value>44.10</value>
+ <value>90.14</value>
+ <value>100</value>
+ </array>
+
+ <!-- Additional power used when screen is ambient mode -->
+ <item name="ambient.on">12</item>
+
+ <!-- Additional power used when screen is turned on at minimum brightness -->
+ <item name="screen.on">102.4</item>
+ <!-- Additional power used when screen is at maximum brightness, compared to
+ screen at minimum brightness -->
+ <item name="screen.full">1234</item>
+
+ <!-- Average power used by the camera flash module when on -->
+ <item name="camera.flashlight">1233.47</item>
+
+ <!-- Average power use by the camera subsystem for a typical camera
+ application. Intended as a rough estimate for an application running a
+ preview and capturing approximately 10 full-resolution pictures per
+ minute. -->
+ <item name="camera.avg">941</item>
+
+ <!-- Additional power used when video is playing -->
+ <item name="video">123</item>
+
+ <!-- Additional power used when audio is playing -->
+ <item name="audio">12</item>
+
+ <!-- Cellular modem related values.-->
+ <item name="modem.controller.sleep">1</item>
+ <item name="modem.controller.idle">44</item>
+ <item name="modem.controller.rx">11</item>
+ <array name="modem.controller.tx"> <!-- Strength 0 to 4 -->
+ <value>16</value>
+ <value>19</value>
+ <value>22</value>
+ <value>73</value>
+ <value>132</value>
+ </array>
+ <item name="modem.controller.voltage">1400</item>
+ <item name="radio.scanning">12</item>
+
+ <!-- GPS related values.-->
+ <item name="gps.on">1</item>
+ <array name="gps.signalqualitybased"> <!-- Strength 0 to 1 -->
+ <value>88</value>
+ <value>07</value>
+ </array>
+ <item name="gps.voltage">1500</item>
+
+ <!-- Idle Receive current for wifi radio in mA.-->
+ <item name="wifi.controller.idle">2</item>
+
+ <!-- Rx current for wifi radio in mA.-->
+ <item name="wifi.controller.rx">123</item>
+
+ <!-- Tx current for wifi radio in mA-->
+ <item name="wifi.controller.tx">333</item>
+
+ <!-- Operating volatage for wifi radio in mV.-->
+ <item name="wifi.controller.voltage">3700</item>
+
+ <!-- Idle current for bluetooth in mA.-->
+ <item name="bluetooth.controller.idle">0.02</item>
+
+ <!-- Rx current for bluetooth in mA.-->
+ <item name="bluetooth.controller.rx">3</item>
+
+ <!-- Tx current for bluetooth in mA-->
+ <item name="bluetooth.controller.tx">5</item>
+
+ <!-- Operating voltage for bluetooth in mV.-->
+ <item name="bluetooth.controller.voltage">3300</item>
+
+</device>
+
+
diff --git a/tools/powermodel/test/com/android/powermodel/BatteryStatsReaderTest.java b/tools/powermodel/test/com/android/powermodel/BatteryStatsReaderTest.java
new file mode 100644
index 000000000000..e7b2c3746c85
--- /dev/null
+++ b/tools/powermodel/test/com/android/powermodel/BatteryStatsReaderTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import org.junit.Test;
+import org.junit.Assert;
+
+import com.android.powermodel.component.ModemAppActivity;
+import com.android.powermodel.component.ModemGlobalActivity;
+import com.android.powermodel.component.ModemRemainderActivity;
+
+/**
+ * Tests {@link BatteryStatsReader}.
+ */
+public class BatteryStatsReaderTest {
+ private static InputStream loadCsvStream() {
+ return BatteryStatsReaderTest.class.getResourceAsStream("/bs.csv");
+ }
+
+ @Test public void testModemGlobal() throws Exception {
+ final ActivityReport report = BatteryStatsReader.parse(loadCsvStream());
+
+ final AppActivity global = report.findApp(SpecialApp.GLOBAL);
+ Assert.assertNotNull(global);
+
+ final ModemGlobalActivity modem
+ = (ModemGlobalActivity)global.getComponentActivity(Component.MODEM);
+ Assert.assertNotNull(modem);
+ Assert.assertEquals(97840, modem.rxPacketCount);
+ Assert.assertEquals(72941, modem.txPacketCount);
+ Assert.assertEquals(5113727, modem.totalActiveTimeMs);
+ }
+
+ @Test public void testModemApp() throws Exception {
+ final ActivityReport report = BatteryStatsReader.parse(loadCsvStream());
+
+ final List<AppActivity> gmailList = report.findApp("com.google.android.gm");
+ Assert.assertEquals(1, gmailList.size());
+ final AppActivity gmail = gmailList.get(0);
+
+ final ModemAppActivity modem
+ = (ModemAppActivity)gmail.getComponentActivity(Component.MODEM);
+ Assert.assertNotNull(modem);
+ Assert.assertEquals(9925, modem.rxPacketCount);
+ Assert.assertEquals(5577, modem.txPacketCount);
+ }
+
+ @Test public void testModemRemainder() throws Exception {
+ final ActivityReport report = BatteryStatsReader.parse(loadCsvStream());
+
+ final AppActivity remainder = report.findApp(SpecialApp.REMAINDER);
+ Assert.assertNotNull(remainder);
+
+ final ModemRemainderActivity modem
+ = (ModemRemainderActivity)remainder.getComponentActivity(Component.MODEM);
+ Assert.assertNotNull(modem);
+ Assert.assertArrayEquals(new long[] { 3066958, 0, 34678, 1643364, 7045084 },
+ modem.strengthTimeMs);
+ Assert.assertEquals(2443805, modem.scanningTimeMs);
+ Assert.assertEquals(4923676, modem.activeTimeMs);
+ }
+}
diff --git a/tools/powermodel/test/com/android/powermodel/CsvParserTest.java b/tools/powermodel/test/com/android/powermodel/CsvParserTest.java
new file mode 100644
index 000000000000..55dde412b78e
--- /dev/null
+++ b/tools/powermodel/test/com/android/powermodel/CsvParserTest.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests {@link PowerProfile}
+ */
+public class CsvParserTest {
+
+ class LineCollector implements CsvParser.LineProcessor {
+ ArrayList<ArrayList<String>> results = new ArrayList<ArrayList<String>>();
+
+ @Override
+ public void onLine(int lineNumber, ArrayList<String> fields) {
+ System.out.println(lineNumber);
+ for (String str: fields) {
+ System.out.println("-->" + str + "<--");
+ }
+ results.add(fields);
+ }
+ }
+
+ private void assertEquals(String[][] expected, ArrayList<ArrayList<String>> results) {
+ final String[][] resultArray = new String[results.size()][];
+ for (int i=0; i<results.size(); i++) {
+ final ArrayList<String> list = results.get(i);
+ resultArray[i] = list.toArray(new String[list.size()]);
+ }
+ Assert.assertArrayEquals(expected, resultArray);
+ }
+
+ private String makeString(int length) {
+ final StringBuilder str = new StringBuilder();
+ for (int i=0; i<length; i++) {
+ str.append('a');
+ }
+ return str.toString();
+ }
+
+ @Test public void testEmpty() throws Exception {
+ final String text = "";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ }, collector.results);
+ }
+
+ @Test public void testOnlyNewline() throws Exception {
+ final String text = "\n";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ }, collector.results);
+ }
+
+ @Test public void testTwoLines() throws Exception {
+ final String text = "one,twoo,3\nfour,5,six\n";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { "one", "twoo", "3", },
+ { "four", "5", "six", },
+ }, collector.results);
+ }
+
+
+ @Test public void testEscapedEmpty() throws Exception {
+ final String text = "\"\",\"\",\"\"\n";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { "", "", "", },
+ }, collector.results);
+ }
+
+ @Test public void testEscapedText() throws Exception {
+ final String text = "\"one\",\"twoo\",\"3\"\n";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { "one", "twoo", "3", },
+ }, collector.results);
+ }
+
+ @Test public void testEscapedQuotes() throws Exception {
+ final String text = "\"\"\"\",\"\"\"\"\"\",\"\"\"\"\n";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { "\"", "\"\"", "\"", },
+ }, collector.results);
+ }
+
+ @Test public void testEscapedCommas() throws Exception {
+ final String text = "\",\",\",\",\",\"\n";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { ",", ",", ",", },
+ }, collector.results);
+ }
+
+ @Test public void testEscapedQuotesAndCommas() throws Exception {
+ final String text = "\"\"\",\",\"\"\",\",\"\"\",\"\n";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { "\",", "\",", "\",", },
+ }, collector.results);
+ }
+
+ @Test public void testNoNewline() throws Exception {
+ final String text = "a,b,c";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { "a", "b", "c", }
+ }, collector.results);
+ }
+
+ @Test public void testNoNewlineWithCommas() throws Exception {
+ final String text = "a,b,,";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { "a", "b", "", "" }
+ }, collector.results);
+ }
+
+ @Test public void testNoNewlineWithQuote() throws Exception {
+ final String text = "a,b,\",\"";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { "a", "b", "," }
+ }, collector.results);
+ }
+
+ @Test public void testNoCommas() throws Exception {
+ final String text = "aasdfadfadfad";
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { "aasdfadfadfad", }
+ }, collector.results);
+ }
+
+ @Test public void testMaxLength() throws Exception {
+ final String text = makeString(CsvParser.MAX_FIELD_SIZE);
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { text, }
+ }, collector.results);
+ }
+
+ @Test public void testMaxLengthTwice() throws Exception {
+ String big = makeString(CsvParser.MAX_FIELD_SIZE);
+ final String text = big + "," + big;
+ System.out.println("Test: [" + text + "]");
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { big, big, }
+ }, collector.results);
+ }
+
+ @Test public void testTooLong() throws Exception {
+ final String text = makeString(CsvParser.MAX_FIELD_SIZE+1);
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ try {
+ CsvParser.parse(is, collector);
+ throw new RuntimeException("Expected CsvParser.parse to throw ParseException");
+ } catch (ParseException ex) {
+ // good
+ }
+ }
+
+ @Test public void testBufferBoundary() throws Exception {
+ final String big = makeString(CsvParser.MAX_FIELD_SIZE-3);
+ final String text = big + ",b,c,d,e,f,g";
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { big, "b", "c", "d", "e", "f", "g", }
+ }, collector.results);
+ }
+
+ @Test public void testBufferBoundaryEmpty() throws Exception {
+ final String big = makeString(CsvParser.MAX_FIELD_SIZE-3);
+ final String text = big + ",,,,,,";
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { big, "", "", "", "", "", "", }
+ }, collector.results);
+ }
+
+ // Checks that the escaping and sawQuote behavior is correct at the buffer boundary
+ @Test public void testBufferBoundaryEscapingEven() throws Exception {
+ final String big = makeString(CsvParser.MAX_FIELD_SIZE-2);
+ final String text = big + ",\"\"\"\"\"\"\"\"\"\"\"\"," + big;
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { big, "\"\"\"\"\"", big }
+ }, collector.results);
+ }
+
+ // Checks that the escaping and sawQuote behavior is correct at the buffer boundary
+ @Test public void testBufferBoundaryEscapingOdd() throws Exception {
+ final String big = makeString(CsvParser.MAX_FIELD_SIZE-3);
+ final String text = big + ",\"\"\"\"\"\"\"\"\"\"\"\"," + big;
+ final InputStream is = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
+ LineCollector collector = new LineCollector();
+
+ CsvParser.parse(is, collector);
+
+ assertEquals(new String[][] {
+ { big, "\"\"\"\"\"", big }
+ }, collector.results);
+ }
+
+}
diff --git a/tools/powermodel/test/com/android/powermodel/PowerProfileTest.java b/tools/powermodel/test/com/android/powermodel/PowerProfileTest.java
new file mode 100644
index 000000000000..ab458311a98e
--- /dev/null
+++ b/tools/powermodel/test/com/android/powermodel/PowerProfileTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.io.InputStream;
+
+import com.android.powermodel.component.CpuProfile;
+import com.android.powermodel.component.AudioProfile;
+import com.android.powermodel.component.BluetoothProfile;
+import com.android.powermodel.component.CameraProfile;
+import com.android.powermodel.component.FlashlightProfile;
+import com.android.powermodel.component.GpsProfile;
+import com.android.powermodel.component.ModemProfile;
+import com.android.powermodel.component.ScreenProfile;
+import com.android.powermodel.component.VideoProfile;
+import com.android.powermodel.component.WifiProfile;
+import org.junit.Assert;
+import org.junit.Test;
+
+/*
+ * Additional tests needed:
+ * - CPU clusters with mismatching counts of speeds and coefficients
+ * - Extra fields
+ * - Name listed twice
+ */
+
+/**
+ * Tests {@link PowerProfile}
+ */
+public class PowerProfileTest {
+ private static final float EPSILON = 0.00001f;
+
+ private static InputStream loadPowerProfileStream() {
+ return PowerProfileTest.class.getResourceAsStream("/power_profile.xml");
+ }
+
+ @Test public void testReadGood() throws Exception {
+ final InputStream is = loadPowerProfileStream();
+
+ final PowerProfile profile = PowerProfile.parse(is);
+
+ // Audio
+ final AudioProfile audio = (AudioProfile)profile.getComponent(Component.AUDIO);
+ Assert.assertEquals(12.0f, audio.onMa, EPSILON);
+
+ // Bluetooth
+ final BluetoothProfile bluetooth
+ = (BluetoothProfile)profile.getComponent(Component.BLUETOOTH);
+ Assert.assertEquals(0.02f, bluetooth.idleMa, EPSILON);
+ Assert.assertEquals(3.0f, bluetooth.rxMa, EPSILON);
+ Assert.assertEquals(5.0f, bluetooth.txMa, EPSILON);
+
+ // Camera
+ final CameraProfile camera = (CameraProfile)profile.getComponent(Component.CAMERA);
+ Assert.assertEquals(941.0f, camera.onMa, EPSILON);
+
+ // CPU
+ final CpuProfile cpu = (CpuProfile)profile.getComponent(Component.CPU);
+ Assert.assertEquals(1.3f, cpu.suspendMa, EPSILON);
+ Assert.assertEquals(3.9f, cpu.idleMa, EPSILON);
+ Assert.assertEquals(18.33f, cpu.activeMa, EPSILON);
+ Assert.assertEquals(2, cpu.clusters.length);
+ // Cluster 0
+ Assert.assertEquals(4, cpu.clusters[0].coreCount);
+ Assert.assertEquals(2.41f, cpu.clusters[0].onMa, EPSILON);
+ Assert.assertEquals(9, cpu.clusters[0].frequencies.length, EPSILON);
+ Assert.assertEquals(100000, cpu.clusters[0].frequencies[0].speedHz);
+ Assert.assertEquals(0.29f, cpu.clusters[0].frequencies[0].onMa, EPSILON);
+ Assert.assertEquals(303200, cpu.clusters[0].frequencies[1].speedHz);
+ Assert.assertEquals(0.63f, cpu.clusters[0].frequencies[1].onMa, EPSILON);
+ Assert.assertEquals(380000, cpu.clusters[0].frequencies[2].speedHz);
+ Assert.assertEquals(1.23f, cpu.clusters[0].frequencies[2].onMa, EPSILON);
+ Assert.assertEquals(476000, cpu.clusters[0].frequencies[3].speedHz);
+ Assert.assertEquals(1.24f, cpu.clusters[0].frequencies[3].onMa, EPSILON);
+ Assert.assertEquals(552800, cpu.clusters[0].frequencies[4].speedHz);
+ Assert.assertEquals(2.47f, cpu.clusters[0].frequencies[4].onMa, EPSILON);
+ Assert.assertEquals(648800, cpu.clusters[0].frequencies[5].speedHz);
+ Assert.assertEquals(2.54f, cpu.clusters[0].frequencies[5].onMa, EPSILON);
+ Assert.assertEquals(725600, cpu.clusters[0].frequencies[6].speedHz);
+ Assert.assertEquals(3.60f, cpu.clusters[0].frequencies[6].onMa, EPSILON);
+ Assert.assertEquals(802400, cpu.clusters[0].frequencies[7].speedHz);
+ Assert.assertEquals(3.64f, cpu.clusters[0].frequencies[7].onMa, EPSILON);
+ Assert.assertEquals(879200, cpu.clusters[0].frequencies[8].speedHz);
+ Assert.assertEquals(4.42f, cpu.clusters[0].frequencies[8].onMa, EPSILON);
+ // Cluster 1
+ Assert.assertEquals(2, cpu.clusters[1].coreCount);
+ Assert.assertEquals(5.29f, cpu.clusters[1].onMa, EPSILON);
+ Assert.assertEquals(7, cpu.clusters[1].frequencies.length, EPSILON);
+ Assert.assertEquals(825600, cpu.clusters[1].frequencies[0].speedHz);
+ Assert.assertEquals(28.98f, cpu.clusters[1].frequencies[0].onMa, EPSILON);
+ Assert.assertEquals(902400, cpu.clusters[1].frequencies[1].speedHz);
+ Assert.assertEquals(31.40f, cpu.clusters[1].frequencies[1].onMa, EPSILON);
+ Assert.assertEquals(979200, cpu.clusters[1].frequencies[2].speedHz);
+ Assert.assertEquals(33.33f, cpu.clusters[1].frequencies[2].onMa, EPSILON);
+ Assert.assertEquals(1056000, cpu.clusters[1].frequencies[3].speedHz);
+ Assert.assertEquals(40.12f, cpu.clusters[1].frequencies[3].onMa, EPSILON);
+ Assert.assertEquals(1209600, cpu.clusters[1].frequencies[4].speedHz);
+ Assert.assertEquals(44.10f, cpu.clusters[1].frequencies[4].onMa, EPSILON);
+ Assert.assertEquals(1286400, cpu.clusters[1].frequencies[5].speedHz);
+ Assert.assertEquals(90.14f, cpu.clusters[1].frequencies[5].onMa, EPSILON);
+ Assert.assertEquals(1363200, cpu.clusters[1].frequencies[6].speedHz);
+ Assert.assertEquals(100f, cpu.clusters[1].frequencies[6].onMa, EPSILON);
+
+ // Flashlight
+ final FlashlightProfile flashlight
+ = (FlashlightProfile)profile.getComponent(Component.FLASHLIGHT);
+ Assert.assertEquals(1233.47f, flashlight.onMa, EPSILON);
+
+ // GPS
+ final GpsProfile gps = (GpsProfile)profile.getComponent(Component.GPS);
+ Assert.assertEquals(1.0f, gps.onMa, EPSILON);
+ Assert.assertEquals(2, gps.signalQualityMa.length);
+ Assert.assertEquals(88.0f, gps.signalQualityMa[0], EPSILON);
+ Assert.assertEquals(7.0f, gps.signalQualityMa[1], EPSILON);
+
+ // Modem
+ final ModemProfile modem = (ModemProfile)profile.getComponent(Component.MODEM);
+ Assert.assertEquals(1.0f, modem.sleepMa, EPSILON);
+ Assert.assertEquals(44.0f, modem.idleMa, EPSILON);
+ Assert.assertEquals(12.0f, modem.scanningMa, EPSILON);
+ Assert.assertEquals(11.0f, modem.rxMa, EPSILON);
+ Assert.assertEquals(5, modem.txMa.length);
+ Assert.assertEquals(16.0f, modem.txMa[0], EPSILON);
+ Assert.assertEquals(19.0f, modem.txMa[1], EPSILON);
+ Assert.assertEquals(22.0f, modem.txMa[2], EPSILON);
+ Assert.assertEquals(73.0f, modem.txMa[3], EPSILON);
+ Assert.assertEquals(132.0f, modem.txMa[4], EPSILON);
+
+ // Screen
+ final ScreenProfile screen = (ScreenProfile)profile.getComponent(Component.SCREEN);
+ Assert.assertEquals(102.4f, screen.onMa, EPSILON);
+ Assert.assertEquals(1234.0f, screen.fullMa, EPSILON);
+ Assert.assertEquals(12.0f, screen.ambientMa, EPSILON);
+
+ // Video
+ final VideoProfile video = (VideoProfile)profile.getComponent(Component.VIDEO);
+ Assert.assertEquals(123.0f, video.onMa, EPSILON);
+
+ // Wifi
+ final WifiProfile wifi = (WifiProfile)profile.getComponent(Component.WIFI);
+ Assert.assertEquals(2.0f, wifi.idleMa, EPSILON);
+ Assert.assertEquals(123.0f, wifi.rxMa, EPSILON);
+ Assert.assertEquals(333.0f, wifi.txMa, EPSILON);
+ }
+}
diff --git a/tools/powermodel/test/com/android/powermodel/PowerReportTest.java b/tools/powermodel/test/com/android/powermodel/PowerReportTest.java
new file mode 100644
index 000000000000..1a61737a4b2f
--- /dev/null
+++ b/tools/powermodel/test/com/android/powermodel/PowerReportTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import org.junit.Test;
+import org.junit.Assert;
+
+import com.android.powermodel.component.ModemAppPower;
+import com.android.powermodel.component.ModemRemainderPower;
+
+/**
+ * Tests {@link PowerReport}.
+ */
+public class PowerReportTest {
+ private static final double EPSILON = 0.001;
+ private static final double MS_PER_HR = 3600000.0;
+
+ private static final double AVERAGE_MODEM_POWER = ((11+16+19+22+73+132) / 6.0);
+ private static final double GMAIL_MODEM_MAH = ((9925+5577) / (double)(97840+72941))
+ * 5113727 * AVERAGE_MODEM_POWER * (1.0 / 3600 / 1000);
+ private static final double GMAIL_MAH
+ = GMAIL_MODEM_MAH;
+
+ private static final double REMAINDER_MODEM_MAH
+ = (1.0 / 3600 / 1000)
+ * ((3066958 * 16) + (0 * 19) + (34678 * 22) + (1643364 * 73) + (7045084 * 132)
+ + (2443805 * 12)
+ + (4923676 * AVERAGE_MODEM_POWER));
+ private static final double REMAINDER_MAH
+ = REMAINDER_MODEM_MAH;
+
+ private static final double TOTAL_MAH
+ = GMAIL_MAH
+ + REMAINDER_MAH;
+
+ private static InputStream loadPowerProfileStream() {
+ return PowerProfileTest.class.getResourceAsStream("/power_profile.xml");
+ }
+
+ private static InputStream loadCsvStream() {
+ return BatteryStatsReaderTest.class.getResourceAsStream("/bs.csv");
+ }
+
+ private static PowerReport loadPowerReport() throws Exception {
+ final PowerProfile profile = PowerProfile.parse(loadPowerProfileStream());
+ final ActivityReport activity = BatteryStatsReader.parse(loadCsvStream());
+ return PowerReport.createReport(profile, activity);
+ }
+
+ @Test public void testModemApp() throws Exception {
+ final PowerReport report = loadPowerReport();
+
+ final List<AppPower> gmailList = report.findApp("com.google.android.gm");
+ Assert.assertEquals(1, gmailList.size());
+ final AppPower gmail = gmailList.get(0);
+
+ final ModemAppPower modem = (ModemAppPower)gmail.getComponentPower(Component.MODEM);
+ Assert.assertNotNull(modem);
+ Assert.assertEquals(GMAIL_MODEM_MAH, modem.powerMah, EPSILON);
+ }
+
+ @Test public void testModemRemainder() throws Exception {
+ final PowerReport report = loadPowerReport();
+
+ final AppPower remainder = report.findApp(SpecialApp.REMAINDER);
+ Assert.assertNotNull(remainder);
+
+ final ModemRemainderPower modem
+ = (ModemRemainderPower)remainder.getComponentPower(Component.MODEM);
+ Assert.assertNotNull(modem);
+
+ Assert.assertArrayEquals(new double[] {
+ 3066958 * 16.0 / MS_PER_HR,
+ 0 * 19.0 / MS_PER_HR,
+ 34678 * 22.0 / MS_PER_HR,
+ 1643364 * 73.0 / MS_PER_HR,
+ 7045084 * 132.0 / MS_PER_HR },
+ modem.strengthMah, EPSILON);
+ Assert.assertEquals(2443805 * 12 / MS_PER_HR, modem.scanningMah, EPSILON);
+ Assert.assertEquals(4923676 * AVERAGE_MODEM_POWER / MS_PER_HR, modem.activeMah, EPSILON);
+
+ Assert.assertEquals(REMAINDER_MODEM_MAH, modem.powerMah, EPSILON);
+ }
+
+ @Test public void testAppTotal() throws Exception {
+ final PowerReport report = loadPowerReport();
+
+ final List<AppPower> gmailList = report.findApp("com.google.android.gm");
+ Assert.assertEquals(1, gmailList.size());
+ final AppPower gmail = gmailList.get(0);
+
+ Assert.assertEquals(GMAIL_MAH, gmail.getAppPowerMah(), EPSILON);
+ }
+
+ @Test public void testRemainderTotal() throws Exception {
+ final PowerReport report = loadPowerReport();
+
+ final AppPower remainder = report.findApp(SpecialApp.REMAINDER);
+ Assert.assertNotNull(remainder);
+
+ Assert.assertEquals(REMAINDER_MAH, remainder.getAppPowerMah(), EPSILON);
+ }
+
+ @Test public void testTotal() throws Exception {
+ final PowerReport report = loadPowerReport();
+
+ Assert.assertEquals(TOTAL_MAH, report.getTotalPowerMah(), EPSILON);
+ }
+}
+
diff --git a/tools/powermodel/test/com/android/powermodel/RawBatteryStatsTest.java b/tools/powermodel/test/com/android/powermodel/RawBatteryStatsTest.java
new file mode 100644
index 000000000000..fbcac41a9e1c
--- /dev/null
+++ b/tools/powermodel/test/com/android/powermodel/RawBatteryStatsTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.powermodel;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import org.junit.Test;
+import org.junit.Assert;
+
+/**
+ * Tests {@link RawBatteryStats}.
+ */
+public class RawBatteryStatsTest {
+ private static final int BS_VERSION = 32;
+
+ private static InputStream makeCsv(String... lines) {
+ return makeCsv(BS_VERSION, lines);
+ }
+
+ private static InputStream makeCsv(int version, String... lines) {
+ final StringBuilder result = new StringBuilder("9,0,i,vers,");
+ result.append(version);
+ result.append(",177,PPR1.180326.002,PQ1A.181105.015\n");
+ for (String line: lines) {
+ result.append(line);
+ result.append('\n');
+ }
+ return new ByteArrayInputStream(result.toString().getBytes(StandardCharsets.UTF_8));
+ }
+
+ @Test public void testVersion() throws Exception {
+ final InputStream is = makeCsv();
+
+ final RawBatteryStats bs = RawBatteryStats.parse(is);
+ final List<RawBatteryStats.Record> records = bs.getRecords();
+ final RawBatteryStats.Version line = (RawBatteryStats.Version)records.get(0);
+
+ Assert.assertEquals(0, bs.getWarnings().size());
+ Assert.assertEquals(true, line.complete);
+
+ Assert.assertEquals(9, line.lineVersion);
+ Assert.assertEquals(0, line.uid);
+ Assert.assertEquals(RawBatteryStats.Category.INFO, line.category);
+ Assert.assertEquals("vers", line.lineType);
+
+ Assert.assertEquals(BS_VERSION, line.dumpsysVersion);
+ Assert.assertEquals(177, line.parcelVersion);
+ Assert.assertEquals("PPR1.180326.002", line.startPlatformVersion);
+ Assert.assertEquals("PQ1A.181105.015", line.endPlatformVersion);
+ }
+
+ @Test public void testUid() throws Exception {
+ final InputStream is = makeCsv("9,0,i,uid,1000,com.example.app");
+
+ final RawBatteryStats bs = RawBatteryStats.parse(is);
+ final List<RawBatteryStats.Record> records = bs.getRecords();
+ final RawBatteryStats.Uid line = (RawBatteryStats.Uid)records.get(1);
+
+ Assert.assertEquals(1000, line.uidKey);
+ Assert.assertEquals("com.example.app", line.pkg);
+ }
+
+ @Test public void testVarargs() throws Exception {
+ final InputStream is = makeCsv("9,0,i,gmcd,1,2,3,4,5,6,7");
+
+ final RawBatteryStats bs = RawBatteryStats.parse(is);
+ final List<RawBatteryStats.Record> records = bs.getRecords();
+ final RawBatteryStats.GlobalModemController line
+ = (RawBatteryStats.GlobalModemController)records.get(1);
+
+ Assert.assertEquals(1, line.idleMs);
+ Assert.assertEquals(2, line.rxTimeMs);
+ Assert.assertEquals(3, line.powerMaMs);
+ Assert.assertEquals(4, line.txTimeMs.length);
+ Assert.assertEquals(4, line.txTimeMs[0]);
+ Assert.assertEquals(5, line.txTimeMs[1]);
+ Assert.assertEquals(6, line.txTimeMs[2]);
+ Assert.assertEquals(7, line.txTimeMs[3]);
+ }
+}
diff --git a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
index 1d4c435939db..d368136c7081 100644
--- a/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
+++ b/tools/processors/unsupportedappusage/src/android/processor/unsupportedappusage/UnsupportedAppUsageProcessor.java
@@ -28,6 +28,7 @@ import com.sun.tools.javac.util.Position;
import java.io.IOException;
import java.io.PrintStream;
+import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
@@ -38,7 +39,9 @@ import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
/**
@@ -108,10 +111,25 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor {
"startline",
"startcol",
"endline",
- "endcol"
+ "endcol",
+ "properties"
);
}
+ private String encodeAnnotationProperties(AnnotationMirror annotation) {
+ StringBuilder sb = new StringBuilder();
+ for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> e
+ : annotation.getElementValues().entrySet()) {
+ if (sb.length() > 0) {
+ sb.append("&");
+ }
+ sb.append(e.getKey().getSimpleName())
+ .append("=")
+ .append(URLEncoder.encode(e.getValue().toString()));
+ }
+ return sb.toString();
+ }
+
/**
* Maps an annotated element to the source position of the @UnsupportedAppUsage annotation
* attached to it. It returns CSV in the format:
@@ -137,7 +155,8 @@ public class UnsupportedAppUsageProcessor extends AbstractProcessor {
lines.getLineNumber(pair.fst.pos().getStartPosition()),
lines.getColumnNumber(pair.fst.pos().getStartPosition()),
lines.getLineNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions)),
- lines.getColumnNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions)));
+ lines.getColumnNumber(pair.fst.pos().getEndPosition(pair.snd.endPositions)),
+ encodeAnnotationProperties(unsupportedAppUsage));
}
/**
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 8585ae9f3f61..88b7e2e9de21 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -1128,7 +1128,10 @@ write_stats_log_jni(FILE* out, const string& java_method_name, const string& cpp
hadStringOrChain = true;
fprintf(out, " jbyte* jbyte_array%d;\n", argIndex);
fprintf(out, " const char* str%d;\n", argIndex);
- fprintf(out, " if (arg%d != NULL) {\n", argIndex);
+ fprintf(out,
+ " if (arg%d != NULL && env->GetArrayLength(arg%d) > "
+ "0) {\n",
+ argIndex, argIndex);
fprintf(out,
" jbyte_array%d = "
"env->GetByteArrayElements(arg%d, NULL);\n",
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 3ec8a4155292..c6acd026bd39 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -58,7 +58,7 @@ interface IWifiManager
*/
oneway void requestActivityInfo(in ResultReceiver result);
- ParceledListSlice getConfiguredNetworks();
+ ParceledListSlice getConfiguredNetworks(String packageName);
ParceledListSlice getPrivilegedConfiguredNetworks();
@@ -90,11 +90,11 @@ interface IWifiManager
List<ScanResult> getScanResults(String callingPackage);
- void disconnect(String packageName);
+ boolean disconnect(String packageName);
- void reconnect(String packageName);
+ boolean reconnect(String packageName);
- void reassociate(String packageName);
+ boolean reassociate(String packageName);
WifiInfo getConnectionInfo(String callingPackage);
@@ -190,8 +190,8 @@ interface IWifiManager
void unregisterNetworkRequestMatchCallback(int callbackIdentifier);
- boolean addNetworkSuggestions(in List<WifiNetworkSuggestion> networkSuggestions, in String packageName);
+ int addNetworkSuggestions(in List<WifiNetworkSuggestion> networkSuggestions, in String packageName);
- boolean removeNetworkSuggestions(in List<WifiNetworkSuggestion> networkSuggestions, in String packageName);
+ int removeNetworkSuggestions(in List<WifiNetworkSuggestion> networkSuggestions, in String packageName);
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7aff03c00dd3..9789319ed6b9 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -25,6 +25,7 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.net.ConnectivityManager;
@@ -137,6 +138,55 @@ public class WifiManager {
public static final int ERROR_AUTH_FAILURE_EAP_FAILURE = 3;
/**
+ * Maximum number of active network suggestions allowed per app.
+ * @hide
+ */
+ public static final int NETWORK_SUGGESTIONS_MAX_PER_APP =
+ ActivityManager.isLowRamDeviceStatic() ? 256 : 1024;
+
+ /**
+ * Reason code if all of the network suggestions were successfully added or removed.
+ */
+ public static final int STATUS_NETWORK_SUGGESTIONS_SUCCESS = 0;
+
+ /**
+ * Reason code if there was an internal error in the platform while processing the addition or
+ * removal of suggestions.
+ */
+ public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL = 1;
+
+ /**
+ * Reason code if one or more of the network suggestions added already exists in platform's
+ * database.
+ * @see WifiNetworkSuggestion#equals(Object)
+ */
+ public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE = 2;
+
+ /**
+ * Reason code if the number of network suggestions provided by the app crosses the max
+ * threshold set per app.
+ * @see #getMaxNumberOfNetworkSuggestionsPerApp()
+ */
+ public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP = 3;
+
+ /**
+ * Reason code if one or more of the network suggestions removed does not exist in platform's
+ * database.
+ */
+ public static final int STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID = 4;
+
+ @IntDef(prefix = { "STATUS_NETWORK_SUGGESTIONS_" }, value = {
+ STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+ STATUS_NETWORK_SUGGESTIONS_ERROR_INTERNAL,
+ STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE,
+ STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_EXCEEDS_MAX_PER_APP,
+ STATUS_NETWORK_SUGGESTIONS_ERROR_REMOVE_INVALID,
+ })
+
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NetworkSuggestionsStatusCode {}
+
+ /**
* Broadcast intent action indicating whether Wi-Fi scanning is allowed currently
* @hide
*/
@@ -1067,7 +1117,7 @@ public class WifiManager {
public List<WifiConfiguration> getConfiguredNetworks() {
try {
ParceledListSlice<WifiConfiguration> parceledList =
- mService.getConfiguredNetworks();
+ mService.getConfiguredNetworks(mContext.getOpPackageName());
if (parceledList == null) {
return Collections.emptyList();
}
@@ -1126,7 +1176,6 @@ public class WifiManager {
* @throws UnsupportedOperationException if Passpoint is not enabled on the device.
* @hide
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public List<OsuProvider> getMatchingOsuProviders(List<ScanResult> scanResults) {
try {
@@ -1497,12 +1546,13 @@ public class WifiManager {
* suggestion back using this API.</li>
*
* @param networkSuggestions List of network suggestions provided by the app.
- * @return true on success, false if any of the suggestions match (See
+ * @return Status code corresponding to the values in {@link NetworkSuggestionsStatusCode}.
* {@link WifiNetworkSuggestion#equals(Object)} any previously provided suggestions by the app.
* @throws {@link SecurityException} if the caller is missing required permissions.
*/
@RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
- public boolean addNetworkSuggestions(@NonNull List<WifiNetworkSuggestion> networkSuggestions) {
+ public @NetworkSuggestionsStatusCode int addNetworkSuggestions(
+ @NonNull List<WifiNetworkSuggestion> networkSuggestions) {
try {
return mService.addNetworkSuggestions(networkSuggestions, mContext.getOpPackageName());
} catch (RemoteException e) {
@@ -1510,21 +1560,20 @@ public class WifiManager {
}
}
-
/**
- * Remove a subset of or all of networks from previously provided suggestions by the app to the
- * device.
+ * Remove some or all of the network suggestions that were previously provided by the app.
* See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters.
* See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used.
*
* @param networkSuggestions List of network suggestions to be removed. Pass an empty list
* to remove all the previous suggestions provided by the app.
- * @return true on success, false if any of the suggestions do not match any suggestions
- * previously provided by the app. Any matching suggestions are removed from the device and
- * will not be considered for any further connection attempts.
+ * @return Status code corresponding to the values in
+ * {@link NetworkSuggestionsStatusCode}.
+ * Any matching suggestions are removed from the device and will not be considered for any
+ * further connection attempts.
*/
@RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
- public boolean removeNetworkSuggestions(
+ public @NetworkSuggestionsStatusCode int removeNetworkSuggestions(
@NonNull List<WifiNetworkSuggestion> networkSuggestions) {
try {
return mService.removeNetworkSuggestions(
@@ -1535,6 +1584,15 @@ public class WifiManager {
}
/**
+ * Returns the max number of network suggestions that are allowed per app on the device.
+ * @see #addNetworkSuggestions(List)
+ * @see #removeNetworkSuggestions(List)
+ */
+ public int getMaxNumberOfNetworkSuggestionsPerApp() {
+ return NETWORK_SUGGESTIONS_MAX_PER_APP;
+ }
+
+ /**
* Add or update a Passpoint configuration. The configuration provides a credential
* for connecting to Passpoint networks that are operated by the Passpoint
* service provider specified in the configuration.
@@ -1761,8 +1819,7 @@ public class WifiManager {
@Deprecated
public boolean disconnect() {
try {
- mService.disconnect(mContext.getOpPackageName());
- return true;
+ return mService.disconnect(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1786,8 +1843,7 @@ public class WifiManager {
@Deprecated
public boolean reconnect() {
try {
- mService.reconnect(mContext.getOpPackageName());
- return true;
+ return mService.reconnect(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1811,8 +1867,7 @@ public class WifiManager {
@Deprecated
public boolean reassociate() {
try {
- mService.reassociate(mContext.getOpPackageName());
- return true;
+ return mService.reassociate(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2132,14 +2187,14 @@ public class WifiManager {
* existing networks. You should assume the network IDs can be different
* after calling this method.
*
- * @return {@code false} Will always return true.
+ * @return {@code false}.
* @deprecated There is no need to call this method -
* {@link #addNetwork(WifiConfiguration)}, {@link #updateNetwork(WifiConfiguration)}
* and {@link #removeNetwork(int)} already persist the configurations automatically.
*/
@Deprecated
public boolean saveConfiguration() {
- return true;
+ return false;
}
/**
@@ -3406,6 +3461,11 @@ public class WifiManager {
* @hide
*/
@SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void connect(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
// Use INVALID_NETWORK_ID for arg1 when passing a config object
@@ -3426,7 +3486,12 @@ public class WifiManager {
* initialized again
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void connect(int networkId, ActionListener listener) {
if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
@@ -3452,7 +3517,12 @@ public class WifiManager {
* initialized again
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void save(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
@@ -3471,7 +3541,12 @@ public class WifiManager {
* initialized again
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void forget(int netId, ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener));
@@ -3486,7 +3561,12 @@ public class WifiManager {
* initialized again
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void disable(int netId, ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener));
@@ -3498,6 +3578,12 @@ public class WifiManager {
* @param SSID, in the format of WifiConfiguration's SSID.
* @hide
*/
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK
+ })
public void disableEphemeralNetwork(String SSID) {
if (SSID == null) throw new IllegalArgumentException("SSID cannot be null");
try {
diff --git a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
index 87706b936f03..f73b9e5e2a00 100644
--- a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
+++ b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java
@@ -42,8 +42,10 @@ import java.util.List;
public class WifiNetworkConfigBuilder {
private static final String MATCH_ALL_SSID_PATTERN_PATH = ".*";
private static final String MATCH_EMPTY_SSID_PATTERN_PATH = "";
- private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN =
+ private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN1 =
new Pair(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS);
+ private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN2 =
+ new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.BROADCAST_ADDRESS);
private static final Pair<MacAddress, MacAddress> MATCH_ALL_BSSID_PATTERN =
new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
private static final MacAddress MATCH_EXACT_BSSID_PATTERN_MASK =
@@ -189,7 +191,13 @@ public class WifiNetworkConfigBuilder {
* Set the BSSID to use for filtering networks from scan results. Will only match network whose
* BSSID is identical to the specified value.
* <p>
- * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li>
+ * <li>For network requests ({@link NetworkSpecifier}), built using
+ * {@link #buildNetworkSpecifier}, sets the BSSID to use for filtering networks from scan
+ * results. Will only match networks whose BSSID is identical to specified value.</li>
+ * <li>For network suggestions ({@link WifiNetworkSuggestion}), built using
+ * {@link #buildNetworkSuggestion()}, sets a specific BSSID for the network suggestion.
+ * If set, only the specified BSSID with the specified SSID will be considered for connection.
+ * If not set, all BSSIDs with the specified SSID will be considered for connection.</li>
* <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or
* {@link #setBssidPattern(MacAddress, MacAddress)}.</li>
*
@@ -432,6 +440,9 @@ public class WifiNetworkConfigBuilder {
if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) {
wifiConfiguration.SSID = "\"" + mSsidPatternMatcher.getPath() + "\"";
}
+ if (mBssidPatternMatcher.second == MATCH_EXACT_BSSID_PATTERN_MASK) {
+ wifiConfiguration.BSSID = mBssidPatternMatcher.first.toString();
+ }
setSecurityParamsInWifiConfiguration(wifiConfiguration);
wifiConfiguration.hiddenSSID = mIsHiddenSSID;
wifiConfiguration.priority = mPriority;
@@ -460,7 +471,10 @@ public class WifiNetworkConfigBuilder {
&& mSsidPatternMatcher.getPath().equals(MATCH_EMPTY_SSID_PATTERN_PATH)) {
return true;
}
- if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN)) {
+ if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN1)) {
+ return true;
+ }
+ if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN2)) {
return true;
}
return false;
@@ -474,6 +488,16 @@ public class WifiNetworkConfigBuilder {
return false;
}
+ private boolean hasSetMatchExactPattern() {
+ // exact ssid match with either match-all bssid or match-exact bssid.
+ if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL
+ && (mBssidPatternMatcher.equals(MATCH_ALL_BSSID_PATTERN)
+ || mBssidPatternMatcher.second.equals(MATCH_EXACT_BSSID_PATTERN_MASK))) {
+ return true;
+ }
+ return false;
+ }
+
private void validateSecurityParams() {
int numSecurityTypes = 0;
numSecurityTypes += mIsEnhancedOpen ? 1 : 0;
@@ -566,9 +590,42 @@ public class WifiNetworkConfigBuilder {
}
/**
- * Create a network suggestion object use in
- * {@link WifiManager#addNetworkSuggestions(List)}.
+ * Create a network suggestion object use in {@link WifiManager#addNetworkSuggestions(List)}.
* See {@link WifiNetworkSuggestion}.
+ *<p>
+ * Note: Apps can set a combination of SSID using {@link #setSsid(String)} and BSSID
+ * using {@link #setBssid(MacAddress)} to provide more fine grained network suggestions to the
+ * platform.
+ * </p>
+ *
+ * For example:
+ * To provide credentials for one open, one WPA2 and one WPA3 network with their
+ * corresponding SSID's:
+ * {@code
+ * final WifiNetworkSuggestion suggestion1 =
+ * new WifiNetworkConfigBuilder()
+ * .setSsid("test111111")
+ * .buildNetworkSuggestion()
+ * final WifiNetworkSuggestion suggestion2 =
+ * new WifiNetworkConfigBuilder()
+ * .setSsid("test222222")
+ * .setWpa2Passphrase("test123456")
+ * .buildNetworkSuggestion()
+ * final WifiNetworkSuggestion suggestion3 =
+ * new WifiNetworkConfigBuilder()
+ * .setSsid("test333333")
+ * .setWpa3Passphrase("test6789")
+ * .buildNetworkSuggestion()
+ * final List<WifiNetworkSuggestion> suggestionsList = new ArrayList<WifiNetworkSuggestion> {{
+ * add(suggestion1);
+ * add(suggestion2);
+ * add(suggestion3);
+ * }};
+ * final WifiManager wifiManager =
+ * context.getSystemService(Context.WIFI_SERVICE);
+ * wifiManager.addNetworkSuggestions(suggestionsList);
+ * ...
+ * }
*
* @return Instance of {@link WifiNetworkSuggestion}.
* @throws IllegalStateException on invalid params set.
@@ -577,11 +634,14 @@ public class WifiNetworkConfigBuilder {
if (mSsidPatternMatcher == null) {
throw new IllegalStateException("setSsid should be invoked for suggestion");
}
- if (mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL
- || mBssidPatternMatcher != null) {
- throw new IllegalStateException("none of setSsidPattern/setBssidPattern/setBssid are"
+ setMatchAnyPatternIfUnset();
+ if (!hasSetMatchExactPattern()) {
+ throw new IllegalStateException("none of setSsidPattern/setBssidPattern are"
+ " allowed for suggestion");
}
+ if (hasSetMatchNonePattern()) {
+ throw new IllegalStateException("cannot set match-none for suggestion");
+ }
validateSecurityParams();
return new WifiNetworkSuggestion(
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 25121e2dc8c7..760f1e6bc5e2 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -104,8 +104,8 @@ public final class WifiNetworkSuggestion implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.allowedKeyManagement,
- suggestorUid);
+ return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.BSSID,
+ wifiConfiguration.allowedKeyManagement, suggestorUid);
}
/**
@@ -121,6 +121,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
}
WifiNetworkSuggestion lhs = (WifiNetworkSuggestion) obj;
return Objects.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID)
+ && Objects.equals(this.wifiConfiguration.BSSID, lhs.wifiConfiguration.BSSID)
&& Objects.equals(this.wifiConfiguration.allowedKeyManagement,
lhs.wifiConfiguration.allowedKeyManagement)
&& suggestorUid == lhs.suggestorUid;
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 529548f1d2b8..fc5caf0a47d7 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -184,6 +184,9 @@ public class WifiScanner {
public static final String SCAN_PARAMS_SCAN_SETTINGS_KEY = "ScanSettings";
/** {@hide} */
public static final String SCAN_PARAMS_WORK_SOURCE_KEY = "WorkSource";
+ /** {@hide} */
+ public static final String REQUEST_PACKAGE_NAME_KEY = "PackageName";
+
/**
* scan configuration parameters to be sent to {@link #startBackgroundScan}
*/
@@ -250,6 +253,14 @@ public class WifiScanner {
*/
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
public int type = TYPE_LOW_LATENCY;
+ /**
+ * This scan request may ignore location settings while receiving scans. This should only
+ * be used in emergency situations.
+ * {@hide}
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
+ public boolean ignoreLocationSettings;
/** Implement the Parcelable interface {@hide} */
public int describeContents() {
@@ -267,6 +278,7 @@ public class WifiScanner {
dest.writeInt(stepCount);
dest.writeInt(isPnoScan ? 1 : 0);
dest.writeInt(type);
+ dest.writeInt(ignoreLocationSettings ? 1 : 0);
if (channels != null) {
dest.writeInt(channels.length);
for (int i = 0; i < channels.length; i++) {
@@ -301,6 +313,7 @@ public class WifiScanner {
settings.stepCount = in.readInt();
settings.isPnoScan = in.readInt() == 1;
settings.type = in.readInt();
+ settings.ignoreLocationSettings = in.readInt() == 1;
int num_channels = in.readInt();
settings.channels = new ChannelSpec[num_channels];
for (int i = 0; i < num_channels; i++) {
@@ -798,6 +811,7 @@ public class WifiScanner {
Bundle scanParams = new Bundle();
scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
mAsyncChannel.sendMessage(CMD_START_BACKGROUND_SCAN, 0, key, scanParams);
}
@@ -812,8 +826,11 @@ public class WifiScanner {
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- mAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key);
+ Bundle scanParams = new Bundle();
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+ mAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, key, scanParams);
}
+
/**
* reports currently available scan results on appropriate listeners
* @return true if all scan results were reported correctly
@@ -821,7 +838,10 @@ public class WifiScanner {
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public boolean getScanResults() {
validateChannel();
- Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
+ Bundle scanParams = new Bundle();
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+ Message reply =
+ mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0, 0, scanParams);
return reply.what == CMD_OP_SUCCEEDED;
}
@@ -856,6 +876,7 @@ public class WifiScanner {
Bundle scanParams = new Bundle();
scanParams.putParcelable(SCAN_PARAMS_SCAN_SETTINGS_KEY, settings);
scanParams.putParcelable(SCAN_PARAMS_WORK_SOURCE_KEY, workSource);
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams);
}
@@ -870,7 +891,9 @@ public class WifiScanner {
int key = removeListener(listener);
if (key == INVALID_KEY) return;
validateChannel();
- mAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key);
+ Bundle scanParams = new Bundle();
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+ mAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, key, scanParams);
}
/**
@@ -879,7 +902,10 @@ public class WifiScanner {
*/
public List<ScanResult> getSingleScanResults() {
validateChannel();
- Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SINGLE_SCAN_RESULTS, 0);
+ Bundle scanParams = new Bundle();
+ scanParams.putString(REQUEST_PACKAGE_NAME_KEY, mContext.getOpPackageName());
+ Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SINGLE_SCAN_RESULTS, 0, 0,
+ scanParams);
if (reply.what == WifiScanner.CMD_OP_SUCCEEDED) {
return Arrays.asList(((ParcelableScanResults) reply.obj).getResults());
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index 67720961f8ed..6631fa806fc6 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -16,10 +16,16 @@
package android.net.wifi.p2p;
+import android.annotation.IntDef;
import android.annotation.UnsupportedAppUsage;
+import android.net.MacAddress;
import android.net.wifi.WpsInfo;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* A class representing a Wi-Fi P2p configuration for setting up a connection
@@ -38,12 +44,46 @@ public class WifiP2pConfig implements Parcelable {
*/
public WpsInfo wps;
+ /**
+ * The network name of a group, should be configured by helper method
+ */
+ /** @hide */
+ public String networkName = "";
+
+ /**
+ * The passphrase of a group, should be configured by helper method
+ */
+ /** @hide */
+ public String passphrase = "";
+
+ /**
+ * The required band for Group Owner
+ */
+ /** @hide */
+ public int groupOwnerBand = GROUP_OWNER_BAND_AUTO;
+
/** @hide */
public static final int MAX_GROUP_OWNER_INTENT = 15;
/** @hide */
@UnsupportedAppUsage
public static final int MIN_GROUP_OWNER_INTENT = 0;
+ /** @hide */
+ @IntDef(flag = false, prefix = { "GROUP_OWNER_BAND_" }, value = {
+ GROUP_OWNER_BAND_AUTO,
+ GROUP_OWNER_BAND_2GHZ,
+ GROUP_OWNER_BAND_5GHZ
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface GroupOwnerBandType {}
+
+ /**
+ * Recognized Group Owner required band.
+ */
+ public static final int GROUP_OWNER_BAND_AUTO = 0;
+ public static final int GROUP_OWNER_BAND_2GHZ = 1;
+ public static final int GROUP_OWNER_BAND_5GHZ = 2;
+
/**
* This is an integer value between 0 and 15 where 0 indicates the least
* inclination to be a group owner and 15 indicates the highest inclination
@@ -115,6 +155,10 @@ public class WifiP2pConfig implements Parcelable {
sbuf.append("\n wps: ").append(wps);
sbuf.append("\n groupOwnerIntent: ").append(groupOwnerIntent);
sbuf.append("\n persist: ").append(netId);
+ sbuf.append("\n networkName: ").append(networkName);
+ sbuf.append("\n passphrase: ").append(
+ TextUtils.isEmpty(passphrase) ? "<empty>" : "<non-empty>");
+ sbuf.append("\n groupOwnerBand: ").append(groupOwnerBand);
return sbuf.toString();
}
@@ -130,6 +174,9 @@ public class WifiP2pConfig implements Parcelable {
wps = new WpsInfo(source.wps);
groupOwnerIntent = source.groupOwnerIntent;
netId = source.netId;
+ networkName = source.networkName;
+ passphrase = source.passphrase;
+ groupOwnerBand = source.groupOwnerBand;
}
}
@@ -139,6 +186,9 @@ public class WifiP2pConfig implements Parcelable {
dest.writeParcelable(wps, flags);
dest.writeInt(groupOwnerIntent);
dest.writeInt(netId);
+ dest.writeString(networkName);
+ dest.writeString(passphrase);
+ dest.writeInt(groupOwnerBand);
}
/** Implement the Parcelable interface */
@@ -150,6 +200,9 @@ public class WifiP2pConfig implements Parcelable {
config.wps = (WpsInfo) in.readParcelable(null);
config.groupOwnerIntent = in.readInt();
config.netId = in.readInt();
+ config.networkName = in.readString();
+ config.passphrase = in.readString();
+ config.groupOwnerBand = in.readInt();
return config;
}
@@ -157,4 +210,140 @@ public class WifiP2pConfig implements Parcelable {
return new WifiP2pConfig[size];
}
};
+
+ /**
+ * Builder used to build {@link WifiP2pConfig} objects for
+ * creating or joining a group.
+ */
+ public static final class Builder {
+
+ private static final MacAddress MAC_ANY_ADDRESS =
+ MacAddress.fromString("00:00:00:00:00:00");
+
+ private MacAddress mDeviceAddress = MAC_ANY_ADDRESS;
+ private String mNetworkName = "";
+ private String mPassphrase = "";
+ private int mGroupOwnerBand = GROUP_OWNER_BAND_AUTO;
+ private int mNetId = WifiP2pGroup.TEMPORARY_NET_ID;
+
+ /**
+ * Specify the peer's MAC address. If not set, the device will
+ * try to find a peer whose SSID matches the network name as
+ * specified by {@link #setNetworkName(String)}. Specifying null will
+ * reset the peer's MAC address to "00:00:00:00:00:00".
+ * <p>
+ * Optional. "00:00:00:00:00:00" by default.
+ *
+ * @param deviceAddress the peer's MAC address.
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder setDeviceAddress(MacAddress deviceAddress) {
+ if (deviceAddress == null) {
+ mDeviceAddress = MAC_ANY_ADDRESS;
+ } else {
+ mDeviceAddress = deviceAddress;
+ }
+ return this;
+ }
+
+ /**
+ * Specify the network name, a.k.a. group name,
+ * for creating or joining a group.
+ * <p>
+ * Must be called - an empty network name is not valid.
+ *
+ * @param networkName network name of a group.
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder setNetworkName(String networkName) {
+ if (TextUtils.isEmpty(networkName)) {
+ throw new IllegalArgumentException(
+ "network name must be non-empty.");
+ }
+ mNetworkName = networkName;
+ return this;
+ }
+
+ /**
+ * Specify the passphrase for creating or joining a group.
+ * <p>
+ * Must be called - an empty passphrase is not valid.
+ *
+ * @param passphrase the passphrase of a group.
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder setPassphrase(String passphrase) {
+ if (TextUtils.isEmpty(passphrase)) {
+ throw new IllegalArgumentException(
+ "passphrase must be non-empty.");
+ }
+ mPassphrase = passphrase;
+ return this;
+ }
+
+ /**
+ * Specify the band to use for creating the group. This method only applies when
+ * creating a group as Group Owner using {@link WifiP2pManager#createGroup}.
+ * The band should be {@link #GROUP_OWNER_BAND_2GHZ} or {@link #GROUP_OWNER_BAND_5GHZ},
+ * or allow the system to pick the band by specifying {@link #GROUP_OWNER_BAND_AUTO}.
+ * If the Group Owner cannot create a group in the specified band, the operation will fail.
+ * <p>
+ * Optional. {@link #GROUP_OWNER_BAND_AUTO} by default.
+ *
+ * @param band the required band of group owner.
+ * This should be one of {@link #GROUP_OWNER_BAND_AUTO},
+ * {@link #GROUP_OWNER_BAND_2GHZ}, {@link #GROUP_OWNER_BAND_5GHZ}.
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder setGroupOwnerBand(int band) {
+ mGroupOwnerBand = band;
+ return this;
+ }
+
+ /**
+ * Specify that the group configuration be persisted (i.e. saved).
+ * By default the group configuration will not be saved.
+ * <p>
+ * Optional. false by default.
+ *
+ * @param persistent is this group persistent group.
+ * @return The builder to facilitate chaining
+ * {@code builder.setXXX(..).setXXX(..)}.
+ */
+ public Builder enablePersistentMode(boolean persistent) {
+ if (persistent) {
+ mNetId = WifiP2pGroup.PERSISTENT_NET_ID;
+ } else {
+ mNetId = WifiP2pGroup.TEMPORARY_NET_ID;
+ }
+ return this;
+ }
+
+ /**
+ * Build {@link WifiP2pConfig} given the current requests made on the builder.
+ * @return {@link WifiP2pConfig} constructed based on builder method calls.
+ */
+ public WifiP2pConfig build() {
+ if (TextUtils.isEmpty(mNetworkName)) {
+ throw new IllegalStateException(
+ "network name must be non-empty.");
+ }
+ if (TextUtils.isEmpty(mPassphrase)) {
+ throw new IllegalStateException(
+ "passphrase must be non-empty.");
+ }
+
+ WifiP2pConfig config = new WifiP2pConfig();
+ config.deviceAddress = mDeviceAddress.toString();
+ config.networkName = mNetworkName;
+ config.passphrase = mPassphrase;
+ config.groupOwnerBand = mGroupOwnerBand;
+ config.netId = mNetId;
+ return config;
+ }
+ }
}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index d0efbcffd0ae..b0ed11034810 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -1216,6 +1216,38 @@ public class WifiP2pManager {
}
/**
+ * Create a p2p group with the current device as the group owner. This essentially creates
+ * an access point that can accept connections from legacy clients as well as other p2p
+ * devices.
+ *
+ * <p> An app should use {@link WifiP2pConfig.Builder} to build the configuration
+ * for a group.
+ *
+ * <p class="note"><strong>Note:</strong>
+ * This function would normally not be used unless the current device needs
+ * to form a p2p group as a Group Owner and allow peers to join it as either
+ * Group Clients or legacy Wi-Fi STAs.
+ *
+ * <p> The function call immediately returns after sending a group creation request
+ * to the framework. The application is notified of a success or failure to initiate
+ * group creation through listener callbacks {@link ActionListener#onSuccess} or
+ * {@link ActionListener#onFailure}.
+ *
+ * <p> Application can request for the group details with {@link #requestGroupInfo}.
+ *
+ * @param c is the channel created at {@link #initialize}.
+ * @param config the configuration of a p2p group.
+ * @param listener for callbacks on success or failure. Can be null.
+ */
+ public void createGroup(@NonNull Channel c,
+ @Nullable WifiP2pConfig config,
+ @Nullable ActionListener listener) {
+ checkChannel(c);
+ c.mAsyncChannel.sendMessage(CREATE_GROUP, 0,
+ c.putListener(listener), config);
+ }
+
+ /**
* Remove the current p2p group.
*
* <p> The function call immediately returns after sending a group removal request
diff --git a/wifi/java/com/android/server/wifi/AbstractWifiService.java b/wifi/java/com/android/server/wifi/AbstractWifiService.java
index 04bc55710dfd..0f4e3a8ba20f 100644
--- a/wifi/java/com/android/server/wifi/AbstractWifiService.java
+++ b/wifi/java/com/android/server/wifi/AbstractWifiService.java
@@ -73,7 +73,7 @@ public abstract class AbstractWifiService extends IWifiManager.Stub {
}
@Override
- public ParceledListSlice getConfiguredNetworks() {
+ public ParceledListSlice getConfiguredNetworks(String packageName) {
throw new UnsupportedOperationException();
}
@@ -188,17 +188,17 @@ public abstract class AbstractWifiService extends IWifiManager.Stub {
}
@Override
- public void disconnect(String packageName) {
+ public boolean disconnect(String packageName) {
throw new UnsupportedOperationException();
}
@Override
- public void reconnect(String packageName) {
+ public boolean reconnect(String packageName) {
throw new UnsupportedOperationException();
}
@Override
- public void reassociate(String packageName) {
+ public boolean reassociate(String packageName) {
throw new UnsupportedOperationException();
}
@@ -442,13 +442,13 @@ public abstract class AbstractWifiService extends IWifiManager.Stub {
}
@Override
- public boolean addNetworkSuggestions(
+ public int addNetworkSuggestions(
List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName) {
throw new UnsupportedOperationException();
}
@Override
- public boolean removeNetworkSuggestions(
+ public int removeNetworkSuggestions(
List<WifiNetworkSuggestion> networkSuggestions, String callingPackageName) {
throw new UnsupportedOperationException();
}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 8fe5af998dcf..13c8c9ea7ead 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -1298,13 +1298,26 @@ i * Verify that a call to cancel WPS immediately returns a failure.
*/
@Test
public void addRemoveNetworkSuggestions() throws Exception {
- when(mWifiService.addNetworkSuggestions(any(List.class), anyString())).thenReturn(true);
- when(mWifiService.removeNetworkSuggestions(any(List.class), anyString())).thenReturn(true);
+ when(mWifiService.addNetworkSuggestions(any(List.class), anyString()))
+ .thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS);
+ when(mWifiService.removeNetworkSuggestions(any(List.class), anyString()))
+ .thenReturn(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS);
- assertTrue(mWifiManager.addNetworkSuggestions(new ArrayList<>()));
+ assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+ mWifiManager.addNetworkSuggestions(new ArrayList<>()));
verify(mWifiService).addNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME));
- assertTrue(mWifiManager.removeNetworkSuggestions(new ArrayList<>()));
+ assertEquals(WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS,
+ mWifiManager.removeNetworkSuggestions(new ArrayList<>()));
verify(mWifiService).removeNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME));
}
+
+ /**
+ * Verify call to {@link WifiManager#getMaxNumberOfNetworkSuggestionsPerApp()}.
+ */
+ @Test
+ public void getMaxNumberOfNetworkSuggestionsPerApp() {
+ assertEquals(WifiManager.NETWORK_SUGGESTIONS_MAX_PER_APP,
+ mWifiManager.getMaxNumberOfNetworkSuggestionsPerApp());
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java
index c455c6f0836d..2505499c85d7 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkConfigBuilderTest.java
@@ -244,7 +244,7 @@ public class WifiNetworkConfigBuilderTest {
* when match-none SSID pattern is set.
*/
@Test(expected = IllegalStateException.class)
- public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern() {
+ public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern1() {
new WifiNetworkConfigBuilder()
.setSsidPattern(new PatternMatcher("", PatternMatcher.PATTERN_LITERAL))
.buildNetworkSpecifier();
@@ -252,10 +252,21 @@ public class WifiNetworkConfigBuilderTest {
/**
* Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+ * when match-none SSID pattern is set.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testWifiNetworkSpecifierBuilderWithMatchNoneSsidPattern2() {
+ new WifiNetworkConfigBuilder()
+ .setSsid("")
+ .buildNetworkSpecifier();
+ }
+
+ /**
+ * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
* when match-none BSSID pattern is set.
*/
@Test(expected = IllegalStateException.class)
- public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern() {
+ public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern1() {
new WifiNetworkConfigBuilder()
.setBssidPattern(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS)
.buildNetworkSpecifier();
@@ -263,6 +274,28 @@ public class WifiNetworkConfigBuilderTest {
/**
* Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+ * when match-none BSSID pattern is set.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern2() {
+ new WifiNetworkConfigBuilder()
+ .setBssid(MacAddress.BROADCAST_ADDRESS)
+ .buildNetworkSpecifier();
+ }
+
+ /**
+ * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
+ * when match-none BSSID pattern is set.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testWifiNetworkSpecifierBuilderWithMatchNoneBssidPattern3() {
+ new WifiNetworkConfigBuilder()
+ .setBssid(MacAddress.ALL_ZEROS_ADDRESS)
+ .buildNetworkSpecifier();
+ }
+
+ /**
+ * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} throws an exception
* when SSID pattern is set for hidden network.
*/
@Test(expected = IllegalStateException.class)
@@ -429,13 +462,15 @@ public class WifiNetworkConfigBuilderTest {
* {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} for OWE network.
*/
@Test
- public void testWifiNetworkSuggestionBuilderForEnhancedOpenNetwork() {
+ public void testWifiNetworkSuggestionBuilderForEnhancedOpenNetworkWithBssid() {
WifiNetworkSuggestion suggestion = new WifiNetworkConfigBuilder()
.setSsid(TEST_SSID)
+ .setBssid(MacAddress.fromString(TEST_BSSID))
.setIsEnhancedOpen()
.buildNetworkSuggestion();
assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertEquals(TEST_BSSID, suggestion.wifiConfiguration.BSSID);
assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
.get(WifiConfiguration.KeyMgmt.OWE));
assertNull(suggestion.wifiConfiguration.preSharedKey);
@@ -505,7 +540,7 @@ public class WifiNetworkConfigBuilderTest {
/**
* Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
- * when {@link WifiNetworkConfigBuilder#setBssid(MacAddress)} is set.
+ * when {@link WifiNetworkConfigBuilder#setBssidPattern(MacAddress, MacAddress)} is set.
*/
@Test(expected = IllegalStateException.class)
public void testWifiNetworkSuggestionBuilderWithBssidPattern() {
@@ -518,23 +553,46 @@ public class WifiNetworkConfigBuilderTest {
/**
* Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
- * when {@link WifiNetworkConfigBuilder#setBssidPattern(MacAddress, MacAddress)} is set.
+ * when {@link WifiNetworkConfigBuilder#setSsid(String)} is not set.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testWifiNetworkSuggestionBuilderWithNoSsid() {
+ new WifiNetworkConfigBuilder()
+ .buildNetworkSuggestion();
+ }
+
+ /**
+ * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
+ * when {@link WifiNetworkConfigBuilder#setSsid(String)} is invoked with an invalid value.
*/
@Test(expected = IllegalStateException.class)
- public void testWifiNetworkSuggestionBuilderWithBssid() {
+ public void testWifiNetworkSuggestionBuilderWithInvalidSsid() {
+ new WifiNetworkConfigBuilder()
+ .setSsid("")
+ .buildNetworkSuggestion();
+ }
+
+ /**
+ * Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
+ * when {@link WifiNetworkConfigBuilder#setBssid(MacAddress)} is invoked with an invalid value.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testWifiNetworkSuggestionBuilderWithInvalidBroadcastBssid() {
new WifiNetworkConfigBuilder()
.setSsid(TEST_SSID)
- .setBssid(MacAddress.fromString(TEST_BSSID))
+ .setBssid(MacAddress.BROADCAST_ADDRESS)
.buildNetworkSuggestion();
}
/**
* Ensure {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} throws an exception
- * when {@link WifiNetworkConfigBuilder#setSsid(String)} is not set.
+ * when {@link WifiNetworkConfigBuilder#setBssid(MacAddress)} is invoked with an invalid value.
*/
@Test(expected = IllegalStateException.class)
- public void testWifiNetworkSuggestionBuilderWithNoSsid() {
+ public void testWifiNetworkSuggestionBuilderWithInvalidAllZeroBssid() {
new WifiNetworkConfigBuilder()
+ .setSsid(TEST_SSID)
+ .setBssid(MacAddress.ALL_ZEROS_ADDRESS)
.buildNetworkSuggestion();
}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 6bab60dd480b..5cc821717462 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -29,6 +29,7 @@ import org.junit.Test;
@SmallTest
public class WifiNetworkSuggestionTest {
private static final String TEST_SSID = "\"Test123\"";
+ private static final String TEST_BSSID = "12:12:12:12:12:12";
private static final String TEST_SSID_1 = "\"Test1234\"";
/**
@@ -38,6 +39,7 @@ public class WifiNetworkSuggestionTest {
public void testWifiNetworkSuggestionParcel() {
WifiConfiguration configuration = new WifiConfiguration();
configuration.SSID = TEST_SSID;
+ configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
WifiNetworkSuggestion suggestion =
new WifiNetworkSuggestion(configuration, false, true, 0);
@@ -65,18 +67,20 @@ public class WifiNetworkSuggestionTest {
/**
* Check NetworkSuggestion equals returns {@code true} for 2 network suggestions with the same
- * SSID, key mgmt and UID.
+ * SSID, BSSID, key mgmt and UID.
*/
@Test
public void testWifiNetworkSuggestionEqualsSame() {
WifiConfiguration configuration = new WifiConfiguration();
configuration.SSID = TEST_SSID;
+ configuration.BSSID = TEST_BSSID;
configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion =
new WifiNetworkSuggestion(configuration, true, false, 0);
WifiConfiguration configuration1 = new WifiConfiguration();
configuration1.SSID = TEST_SSID;
+ configuration1.BSSID = TEST_BSSID;
configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
WifiNetworkSuggestion suggestion1 =
new WifiNetworkSuggestion(configuration1, false, true, 0);
@@ -86,7 +90,7 @@ public class WifiNetworkSuggestionTest {
/**
* Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
- * key mgmt and UID, but different SSID.
+ * BSSID, key mgmt and UID, but different SSID.
*/
@Test
public void testWifiNetworkSuggestionEqualsFailsWhenSsidIsDifferent() {
@@ -107,7 +111,29 @@ public class WifiNetworkSuggestionTest {
/**
* Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
- * SSID and UID, but different key mgmt.
+ * SSID, key mgmt and UID, but different BSSID.
+ */
+ @Test
+ public void testWifiNetworkSuggestionEqualsFailsWhenBssidIsDifferent() {
+ WifiConfiguration configuration = new WifiConfiguration();
+ configuration.SSID = TEST_SSID;
+ configuration.BSSID = TEST_BSSID;
+ configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ WifiNetworkSuggestion suggestion =
+ new WifiNetworkSuggestion(configuration, false, false, 0);
+
+ WifiConfiguration configuration1 = new WifiConfiguration();
+ configuration1.SSID = TEST_SSID;
+ configuration1.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+ WifiNetworkSuggestion suggestion1 =
+ new WifiNetworkSuggestion(configuration1, false, false, 0);
+
+ assertNotEquals(suggestion, suggestion1);
+ }
+
+ /**
+ * Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
+ * SSID, BSSID and UID, but different key mgmt.
*/
@Test
public void testWifiNetworkSuggestionEqualsFailsWhenKeyMgmtIsDifferent() {
@@ -128,7 +154,7 @@ public class WifiNetworkSuggestionTest {
/**
* Check NetworkSuggestion equals returns {@code false} for 2 network suggestions with the same
- * SSID and key mgmt, but different UID.
+ * SSID, BSSID and key mgmt, but different UID.
*/
@Test
public void testWifiNetworkSuggestionEqualsFailsWhenUidIsDifferent() {