summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/removed.txt13
-rw-r--r--api/system-removed.txt9
-rw-r--r--api/test-current.txt6
-rw-r--r--cmds/statsd/src/atoms.proto3
-rw-r--r--cmds/statsd/src/external/GpuStatsPuller.cpp1
-rw-r--r--cmds/statsd/tests/external/GpuStatsPuller_test.cpp5
-rw-r--r--core/java/android/app/AppOpsManager.java31
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl9
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java78
-rw-r--r--core/java/android/content/Context.java2
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java3
-rw-r--r--core/java/android/content/pm/PackageManager.java3
-rw-r--r--core/java/android/content/res/AssetManager.java7
-rw-r--r--core/java/android/os/BatteryStats.java14
-rw-r--r--core/java/android/provider/DeviceConfig.java9
-rw-r--r--core/java/android/provider/Settings.java8
-rw-r--r--core/java/android/view/inputmethod/InputMethodSystemProperty.java26
-rw-r--r--core/java/android/view/textclassifier/ActionsModelParamsSupplier.java4
-rw-r--r--core/java/android/view/textclassifier/ConversationActions.java26
-rw-r--r--core/java/android/view/textclassifier/SelectionEvent.java22
-rw-r--r--core/java/android/view/textclassifier/SystemTextClassifier.java13
-rw-r--r--core/java/android/view/textclassifier/TextClassification.java26
-rw-r--r--core/java/android/view/textclassifier/TextClassificationContext.java29
-rw-r--r--core/java/android/view/textclassifier/TextLanguage.java26
-rw-r--r--core/java/android/view/textclassifier/TextLinks.java26
-rw-r--r--core/java/android/view/textclassifier/TextSelection.java26
-rw-r--r--core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java8
-rw-r--r--core/java/android/widget/AnalogClock.java38
-rw-r--r--core/java/android/widget/DateTimeView.java125
-rw-r--r--core/java/android/widget/TextView.java12
-rw-r--r--core/java/com/android/internal/app/PlatLogoActivity.java505
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java9
-rw-r--r--core/java/com/android/internal/policy/PipSnapAlgorithm.java10
-rw-r--r--core/jni/android_os_Debug.cpp2
-rw-r--r--core/jni/android_view_InputEventSender.cpp1
-rw-r--r--core/jni/android_view_MotionEvent.cpp1
-rw-r--r--core/res/AndroidManifest.xml99
-rw-r--r--core/res/res/drawable-nodpi/android_logotype.xml42
-rw-r--r--core/res/res/drawable-nodpi/platlogo.xml26
-rw-r--r--core/res/res/layout/platlogo_layout.xml50
-rw-r--r--core/res/res/values/config.xml12
-rw-r--r--core/res/res/values/symbols.xml9
-rw-r--r--core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java21
-rw-r--r--core/tests/coretests/src/android/view/textclassifier/logging/SmartSelectionEventTrackerTest.java43
-rw-r--r--data/etc/privapp-permissions-platform.xml2
-rw-r--r--libs/hwui/Android.bp2
-rw-r--r--libs/hwui/Animator.cpp2
-rw-r--r--libs/hwui/RootRenderNode.cpp20
-rw-r--r--libs/hwui/RootRenderNode.h2
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java2
-rw-r--r--media/java/android/media/ThumbnailUtils.java10
-rw-r--r--packages/CarSystemUI/Android.bp2
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java4
-rw-r--r--packages/EasterEgg/AndroidManifest.xml40
-rw-r--r--packages/EasterEgg/res/drawable/icon_bg.xml2
-rw-r--r--packages/EasterEgg/res/drawable/p_icon.xml (renamed from packages/EasterEgg/res/drawable/icon.xml)0
-rw-r--r--packages/EasterEgg/res/drawable/pixel_bg.xml27
-rw-r--r--packages/EasterEgg/res/drawable/q.xml27
-rw-r--r--packages/EasterEgg/res/drawable/q_icon.xml19
-rw-r--r--packages/EasterEgg/res/drawable/q_smaller.xml23
-rw-r--r--packages/EasterEgg/res/layout/activity_quares.xml46
-rw-r--r--packages/EasterEgg/res/values-night/q_colors.xml22
-rw-r--r--packages/EasterEgg/res/values/q_colors.xml31
-rw-r--r--packages/EasterEgg/res/values/q_puzzles.xml214
-rw-r--r--packages/EasterEgg/res/values/strings.xml11
-rw-r--r--packages/EasterEgg/res/values/styles.xml12
-rw-r--r--packages/EasterEgg/src/com/android/egg/quares/Quare.kt168
-rw-r--r--packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt312
-rw-r--r--packages/SettingsLib/AppPreference/res/layout/preference_app.xml1
-rw-r--r--packages/SettingsLib/OWNERS16
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java25
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java19
-rw-r--r--packages/Shell/AndroidManifest.xml2
-rw-r--r--packages/SystemUI/AndroidManifest.xml4
-rw-r--r--packages/SystemUI/docs/dagger.md9
-rw-r--r--packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java11
-rw-r--r--packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java5
-rw-r--r--packages/SystemUI/res/values/config.xml6
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/ImageWallpaper.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/ServiceBinder.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/CircularCornerPathRenderer.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/PathSpecCornerPathRenderer.java124
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/PerimeterPathGuide.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java242
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeService.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java11
-rw-r--r--packages/overlays/AccentColorBlackOverlay/Android.mk2
-rw-r--r--packages/overlays/AccentColorCinnamonOverlay/Android.mk2
-rw-r--r--packages/overlays/AccentColorGreenOverlay/Android.mk2
-rw-r--r--packages/overlays/AccentColorOceanOverlay/Android.mk2
-rw-r--r--packages/overlays/AccentColorOrchidOverlay/Android.mk2
-rw-r--r--packages/overlays/AccentColorPurpleOverlay/Android.mk2
-rw-r--r--packages/overlays/AccentColorSpaceOverlay/Android.mk2
-rw-r--r--packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.mk2
-rw-r--r--packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk2
-rw-r--r--packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.mk2
-rw-r--r--packages/overlays/DisplayCutoutEmulationTallOverlay/Android.mk2
-rw-r--r--packages/overlays/DisplayCutoutEmulationWideOverlay/Android.mk2
-rw-r--r--packages/overlays/FontNotoSerifSourceOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackCircularLauncherOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackCircularSystemUIOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackCircularThemePickerOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackFilledLauncherOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackFilledSystemUIOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackFilledThemePickerOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackRoundedLauncherOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/Android.mk2
-rw-r--r--packages/overlays/IconPackRoundedThemePickerOverlay/Android.mk2
-rw-r--r--packages/overlays/IconShapeRoundedRectOverlay/Android.mk2
-rw-r--r--packages/overlays/IconShapeSquareOverlay/Android.mk2
-rw-r--r--packages/overlays/IconShapeSquircleOverlay/Android.mk2
-rw-r--r--packages/overlays/IconShapeTeardropOverlay/Android.mk2
-rw-r--r--packages/overlays/NavigationBarMode2ButtonOverlay/Android.mk2
-rw-r--r--packages/overlays/NavigationBarMode3ButtonOverlay/Android.mk2
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlay/Android.mk2
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.mk2
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.mk2
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.mk2
-rw-r--r--services/autofill/java/com/android/server/autofill/RemoteFillService.java5
-rw-r--r--services/core/java/com/android/server/MmsServiceBroker.java22
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java10
-rw-r--r--services/core/java/com/android/server/Watchdog.java1
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java10
-rw-r--r--services/core/java/com/android/server/biometrics/face/FaceService.java28
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java10
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodUtils.java21
-rw-r--r--services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java11
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java89
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java32
-rw-r--r--services/core/java/com/android/server/notification/NotificationUsageStats.java18
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java722
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java15
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java30
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java11
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java14
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java12
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java14
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java4
-rw-r--r--services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java108
-rw-r--r--services/core/java/com/android/server/textservices/LazyIntToIntMap.java64
-rw-r--r--services/core/java/com/android/server/textservices/TextServicesManagerService.java54
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java12
-rw-r--r--services/core/java/com/android/server/wm/ActivityDisplay.java93
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java128
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java35
-rw-r--r--services/core/java/com/android/server/wm/DockedStackDividerController.java4
-rw-r--r--services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java100
-rw-r--r--services/core/java/com/android/server/wm/InputManagerCallback.java2
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java75
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java2
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java37
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java15
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java92
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java100
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java179
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java2
-rw-r--r--startop/apps/ColorChanging/.gitignore13
-rw-r--r--startop/apps/ColorChanging/.idea/encodings.xml4
-rw-r--r--startop/apps/ColorChanging/.idea/gradle.xml15
-rw-r--r--startop/apps/ColorChanging/.idea/misc.xml9
-rw-r--r--startop/apps/ColorChanging/.idea/runConfigurations.xml12
-rw-r--r--startop/apps/ColorChanging/README.md5
-rw-r--r--startop/apps/ColorChanging/app/.gitignore1
-rw-r--r--startop/apps/ColorChanging/app/build.gradle29
-rw-r--r--startop/apps/ColorChanging/app/proguard-rules.pro21
-rw-r--r--startop/apps/ColorChanging/app/src/androidTest/java/com/android/startop/colorchanging/ExampleInstrumentedTest.java27
-rw-r--r--startop/apps/ColorChanging/app/src/main/AndroidManifest.xml21
-rw-r--r--startop/apps/ColorChanging/app/src/main/java/com/android/startop/colorchanging/MainActivity.java91
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/drawable-v24/ic_launcher_foreground.xml34
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/drawable/ic_launcher_background.xml170
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/layout/activity_main.xml132
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml5
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml5
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher.pngbin0 -> 2963 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher_round.pngbin0 -> 4905 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher.pngbin0 -> 2060 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher_round.pngbin0 -> 2783 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher.pngbin0 -> 4490 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher_round.pngbin0 -> 6895 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher.pngbin0 -> 6387 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.pngbin0 -> 10413 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher.pngbin0 -> 9128 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.pngbin0 -> 15132 bytes
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/values/colors.xml16
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/values/strings.xml3
-rw-r--r--startop/apps/ColorChanging/app/src/main/res/values/styles.xml11
-rw-r--r--startop/apps/ColorChanging/app/src/test/java/com/android/startop/colorchanging/ExampleUnitTest.java17
-rw-r--r--startop/apps/ColorChanging/build.gradle24
-rw-r--r--startop/apps/ColorChanging/gradle.properties20
-rw-r--r--startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.jarbin0 -> 54329 bytes
-rw-r--r--startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xstartop/apps/ColorChanging/gradlew172
-rw-r--r--startop/apps/ColorChanging/gradlew.bat84
-rw-r--r--startop/apps/ColorChanging/settings.gradle1
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java20
-rw-r--r--test-mock/api/test-current.txt2
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java728
-rw-r--r--tools/aapt2/optimize/ResourcePathShortener.cpp5
-rw-r--r--tools/aapt2/optimize/ResourcePathShortener_test.cpp4
242 files changed, 5168 insertions, 2387 deletions
diff --git a/api/removed.txt b/api/removed.txt
index 8ebded13b5a4..7b1d241fdd6a 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -23,15 +23,6 @@ package android.app {
}
-package android.app.admin {
-
- public class DevicePolicyManager {
- method @Deprecated @Nullable public android.os.UserHandle createAndInitializeUser(@NonNull android.content.ComponentName, String, String, @NonNull android.content.ComponentName, android.os.Bundle);
- method @Deprecated @Nullable public android.os.UserHandle createUser(@NonNull android.content.ComponentName, String);
- }
-
-}
-
package android.app.slice {
public final class Slice implements android.os.Parcelable {
@@ -104,10 +95,6 @@ package android.content {
package android.content.pm {
- public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
- field @Deprecated public String volumeUuid;
- }
-
public class PackageInfo implements android.os.Parcelable {
field public static final int REQUESTED_PERMISSION_REQUIRED = 1; // 0x1
}
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 3e26a9baba19..07b896905986 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -23,15 +23,6 @@ package android.app {
}
-package android.app.admin {
-
- public class DevicePolicyManager {
- method @Deprecated @Nullable public String getDeviceInitializerApp();
- method @Deprecated @Nullable public android.content.ComponentName getDeviceInitializerComponent();
- }
-
-}
-
package android.app.backup {
public class RestoreSession {
diff --git a/api/test-current.txt b/api/test-current.txt
index 874c2162e42c..050ec520059c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -700,6 +700,7 @@ package android.content.pm {
}
public abstract class PackageManager {
+ method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void addOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
method public abstract boolean arePermissionsIndividuallyControlled();
method @Nullable @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL") public abstract String getDefaultBrowserPackageNameAsUser(int);
method @Nullable public String getIncidentReportApproverPackageName();
@@ -713,6 +714,7 @@ package android.content.pm {
method @NonNull public abstract String getSharedSystemSharedLibraryPackageName();
method @Nullable public String getWellbeingPackageName();
method @RequiresPermission("android.permission.GRANT_RUNTIME_PERMISSIONS") public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
+ method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void removeOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS"}) public abstract void updatePermissionFlags(@NonNull String, @NonNull String, int, int, @NonNull android.os.UserHandle);
field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
@@ -735,6 +737,10 @@ package android.content.pm {
field public static final String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared";
}
+ public static interface PackageManager.OnPermissionsChangedListener {
+ method public void onPermissionsChanged(int);
+ }
+
public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
field public static final int FLAG_REMOVED = 2; // 0x2
field public static final int PROTECTION_FLAG_APP_PREDICTOR = 2097152; // 0x200000
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index ee500d7c362e..ceabd39aee8b 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -6360,6 +6360,9 @@ message GpuStatsAppInfo {
// CPU Vulkan implementation is in use.
optional bool cpu_vulkan_in_use = 6;
+
+ // App is not doing pre-rotation correctly.
+ optional bool false_prerotation = 7;
}
/*
diff --git a/cmds/statsd/src/external/GpuStatsPuller.cpp b/cmds/statsd/src/external/GpuStatsPuller.cpp
index 0d3aca05e0e5..bbdb5405ca05 100644
--- a/cmds/statsd/src/external/GpuStatsPuller.cpp
+++ b/cmds/statsd/src/external/GpuStatsPuller.cpp
@@ -96,6 +96,7 @@ static bool pullGpuStatsAppInfo(const sp<IGpuService>& gpuService,
if (!event->write(int64VectorToProtoByteString(info.vkDriverLoadingTime))) return false;
if (!event->write(int64VectorToProtoByteString(info.angleDriverLoadingTime))) return false;
if (!event->write(info.cpuVulkanInUse)) return false;
+ if (!event->write(info.falsePrerotation)) return false;
event->init();
data->emplace_back(event);
}
diff --git a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
index bdc52b0af34c..e91fb0d4b27c 100644
--- a/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
+++ b/cmds/statsd/tests/external/GpuStatsPuller_test.cpp
@@ -56,8 +56,9 @@ static const int32_t VULKAN_VERSION = 1;
static const int32_t CPU_VULKAN_VERSION = 2;
static const int32_t GLES_VERSION = 3;
static const bool CPU_VULKAN_IN_USE = true;
+static const bool FALSE_PREROTATION = true;
static const size_t NUMBER_OF_VALUES_GLOBAL = 13;
-static const size_t NUMBER_OF_VALUES_APP = 6;
+static const size_t NUMBER_OF_VALUES_APP = 7;
// clang-format on
class MockGpuStatsPuller : public GpuStatsPuller {
@@ -150,6 +151,7 @@ TEST_F(GpuStatsPuller_test, PullGpuStatsAppInfo) {
EXPECT_TRUE(event->write(int64VectorToProtoByteString(vkDriverLoadingTime)));
EXPECT_TRUE(event->write(int64VectorToProtoByteString(angleDriverLoadingTime)));
EXPECT_TRUE(event->write(CPU_VULKAN_IN_USE));
+ EXPECT_TRUE(event->write(FALSE_PREROTATION));
event->init();
inData.emplace_back(event);
MockGpuStatsPuller mockPuller(android::util::GPU_STATS_APP_INFO, &inData);
@@ -168,6 +170,7 @@ TEST_F(GpuStatsPuller_test, PullGpuStatsAppInfo) {
EXPECT_EQ(int64VectorToProtoByteString(angleDriverLoadingTime),
outData[0]->getValues()[4].mValue.str_value);
EXPECT_EQ(CPU_VULKAN_IN_USE, outData[0]->getValues()[5].mValue.int_value);
+ EXPECT_EQ(FALSE_PREROTATION, outData[0]->getValues()[6].mValue.int_value);
}
} // namespace statsd
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 60f1424220f6..fb72e651cebd 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -240,7 +240,8 @@ public class AppOpsManager {
public @interface UidState {}
/**
- * Uid state: The UID is a foreground persistent app.
+ * Uid state: The UID is a foreground persistent app. The lower the UID
+ * state the more important the UID is for the user.
* @hide
*/
@TestApi
@@ -248,7 +249,8 @@ public class AppOpsManager {
public static final int UID_STATE_PERSISTENT = 100;
/**
- * Uid state: The UID is top foreground app.
+ * Uid state: The UID is top foreground app. The lower the UID
+ * state the more important the UID is for the user.
* @hide
*/
@TestApi
@@ -257,6 +259,7 @@ public class AppOpsManager {
/**
* Uid state: The UID is running a foreground service of location type.
+ * The lower the UID state the more important the UID is for the user.
* @hide
*/
@TestApi
@@ -264,7 +267,8 @@ public class AppOpsManager {
public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300;
/**
- * Uid state: The UID is running a foreground service.
+ * Uid state: The UID is running a foreground service. The lower the UID
+ * state the more important the UID is for the user.
* @hide
*/
@TestApi
@@ -279,7 +283,8 @@ public class AppOpsManager {
public static final int UID_STATE_MAX_LAST_NON_RESTRICTED = UID_STATE_FOREGROUND_SERVICE;
/**
- * Uid state: The UID is a foreground app.
+ * Uid state: The UID is a foreground app. The lower the UID
+ * state the more important the UID is for the user.
* @hide
*/
@TestApi
@@ -287,7 +292,8 @@ public class AppOpsManager {
public static final int UID_STATE_FOREGROUND = 500;
/**
- * Uid state: The UID is a background app.
+ * Uid state: The UID is a background app. The lower the UID
+ * state the more important the UID is for the user.
* @hide
*/
@TestApi
@@ -295,7 +301,8 @@ public class AppOpsManager {
public static final int UID_STATE_BACKGROUND = 600;
/**
- * Uid state: The UID is a cached app.
+ * Uid state: The UID is a cached app. The lower the UID
+ * state the more important the UID is for the user.
* @hide
*/
@TestApi
@@ -2507,7 +2514,7 @@ public class AppOpsManager {
}
/**
- * @return The duration of the operation in milliseconds.
+ * @return The duration of the operation in milliseconds. The duration is in wall time.
*/
public long getDuration() {
return getLastDuration(MAX_PRIORITY_UID_STATE, MIN_PRIORITY_UID_STATE, OP_FLAGS_ALL);
@@ -2515,7 +2522,7 @@ public class AppOpsManager {
/**
* Return the duration in milliseconds the app accessed this op while
- * in the foreground.
+ * in the foreground. The duration is in wall time.
*
* @param flags The flags which are any combination of
* {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
@@ -2534,7 +2541,7 @@ public class AppOpsManager {
/**
* Return the duration in milliseconds the app accessed this op while
- * in the background.
+ * in the background. The duration is in wall time.
*
* @param flags The flags which are any combination of
* {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
@@ -2553,7 +2560,7 @@ public class AppOpsManager {
/**
* Return the duration in milliseconds the app accessed this op for
- * a given range of UID states.
+ * a given range of UID states. The duration is in wall time.
*
* @param fromUidState The UID state for which to query. Could be one of
* {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
@@ -3968,6 +3975,7 @@ public class AppOpsManager {
/**
* Gets the total duration the app op was accessed (performed) in the foreground.
+ * The duration is in wall time.
*
* @param flags The flags which are any combination of
* {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
@@ -3986,6 +3994,7 @@ public class AppOpsManager {
/**
* Gets the total duration the app op was accessed (performed) in the background.
+ * The duration is in wall time.
*
* @param flags The flags which are any combination of
* {@link #OP_FLAG_SELF}, {@link #OP_FLAG_TRUSTED_PROXY},
@@ -4004,7 +4013,7 @@ public class AppOpsManager {
/**
* Gets the total duration the app op was accessed (performed) for a given
- * range of UID states.
+ * range of UID states. The duration is in wall time.
*
* @param fromUidState The UID state from which to query. Could be one of
* {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 26720fca4df8..2957309094f6 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -386,15 +386,6 @@ interface IActivityTaskManager {
*/
void resizePinnedStack(in Rect pinnedBounds, in Rect tempPinnedTaskBounds);
- /**
- * Updates override configuration applied to specific display.
- * @param values Update values for display configuration. If null is passed it will request the
- * Window Manager to compute new config for the specified display.
- * @param displayId Id of the display to apply the config to.
- * @throws RemoteException
- * @return Returns true if the configuration was updated.
- */
- boolean updateDisplayOverrideConfiguration(in Configuration values, int displayId);
void dismissKeyguard(in IBinder token, in IKeyguardDismissCallback callback,
in CharSequence message);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 441ff6ba4643..5624ba54077a 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -6066,30 +6066,6 @@ public class DevicePolicyManager {
/**
* @hide
- * @deprecated Do not use
- * @removed
- */
- @Deprecated
- @SystemApi
- @SuppressLint("Doclava125")
- public @Nullable String getDeviceInitializerApp() {
- return null;
- }
-
- /**
- * @hide
- * @deprecated Do not use
- * @removed
- */
- @Deprecated
- @SystemApi
- @SuppressLint("Doclava125")
- public @Nullable ComponentName getDeviceInitializerComponent() {
- return null;
- }
-
- /**
- * @hide
* @deprecated Use #ACTION_SET_PROFILE_OWNER
* Sets the given component as an active admin and registers the package as the profile
* owner for this user. The package must already be installed and there shouldn't be
@@ -7394,60 +7370,6 @@ public class DevicePolicyManager {
}
/**
- * Called by a device owner to create a user with the specified name. The UserHandle returned
- * by this method should not be persisted as user handles are recycled as users are removed and
- * created. If you need to persist an identifier for this user, use
- * {@link UserManager#getSerialNumberForUser}.
- *
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param name the user's name
- * @see UserHandle
- * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
- * user could not be created.
- *
- * @deprecated From {@link android.os.Build.VERSION_CODES#M}
- * @removed From {@link android.os.Build.VERSION_CODES#N}
- */
- @Deprecated
- public @Nullable UserHandle createUser(@NonNull ComponentName admin, String name) {
- return null;
- }
-
- /**
- * Called by a device owner to create a user with the specified name. The UserHandle returned
- * by this method should not be persisted as user handles are recycled as users are removed and
- * created. If you need to persist an identifier for this user, use
- * {@link UserManager#getSerialNumberForUser}. The new user will be started in the background
- * immediately.
- *
- * <p> profileOwnerComponent is the {@link DeviceAdminReceiver} to be the profile owner as well
- * as registered as an active admin on the new user. The profile owner package will be
- * installed on the new user if it already is installed on the device.
- *
- * <p>If the optionalInitializeData is not null, then the extras will be passed to the
- * profileOwnerComponent when onEnable is called.
- *
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param name the user's name
- * @param ownerName the human readable name of the organisation associated with this DPM.
- * @param profileOwnerComponent The {@link DeviceAdminReceiver} that will be an active admin on
- * the user.
- * @param adminExtras Extras that will be passed to onEnable of the admin receiver
- * on the new user.
- * @see UserHandle
- * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
- * user could not be created.
- *
- * @deprecated From {@link android.os.Build.VERSION_CODES#M}
- * @removed From {@link android.os.Build.VERSION_CODES#N}
- */
- @Deprecated
- public @Nullable UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name,
- String ownerName, @NonNull ComponentName profileOwnerComponent, Bundle adminExtras) {
- return null;
- }
-
- /**
* Flag used by {@link #createAndManageUser} to skip setup wizard after creating a new user.
*/
public static final int SKIP_SETUP_WIZARD = 0x0001;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c3dd82729d6d..341fc26e2b96 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3067,7 +3067,7 @@ public abstract class Context {
* @hide
*/
@RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 136728678)
public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
Handler handler, UserHandle user) {
throw new RuntimeException("Not implemented. Must override in a subclass.");
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 9bc5f8055617..f75cd236eb36 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -783,8 +783,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*/
public float minAspectRatio;
- /** @removed */
- @Deprecated
+ /** @hide */
public String volumeUuid;
/**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e08f4a28e77c..b845a37b0342 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -105,6 +105,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
public interface OnPermissionsChangedListener {
/**
@@ -6413,6 +6414,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
public abstract void addOnPermissionsChangeListener(
@NonNull OnPermissionsChangedListener listener);
@@ -6425,6 +6427,7 @@ public abstract class PackageManager {
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
public abstract void removeOnPermissionsChangeListener(
@NonNull OnPermissionsChangedListener listener);
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index e5ef67b7d4bd..2420a6109155 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -1157,8 +1157,11 @@ public final class AssetManager implements AutoCloseable {
}
}
- if (mObject != 0) {
- nativeDestroy(mObject);
+ synchronized (this) {
+ if (mObject != 0) {
+ nativeDestroy(mObject);
+ mObject = 0;
+ }
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index ecd16dd1f612..caa6a43e521c 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1554,7 +1554,10 @@ public abstract class BatteryStats implements Parcelable {
}
}
- public final static class HistoryItem implements Parcelable {
+ /**
+ * Battery history record.
+ */
+ public static final class HistoryItem {
public HistoryItem next;
// The time of this event in milliseconds, as per SystemClock.elapsedRealtime().
@@ -1789,16 +1792,10 @@ public abstract class BatteryStats implements Parcelable {
public HistoryItem() {
}
- public HistoryItem(long time, Parcel src) {
- this.time = time;
- numReadInts = 2;
+ public HistoryItem(Parcel src) {
readFromParcel(src);
}
- public int describeContents() {
- return 0;
- }
-
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(time);
int bat = (((int)cmd)&0xff)
@@ -1835,6 +1832,7 @@ public abstract class BatteryStats implements Parcelable {
public void readFromParcel(Parcel src) {
int start = src.dataPosition();
+ time = src.readLong();
int bat = src.readInt();
cmd = (byte)(bat&0xff);
batteryLevel = (byte)((bat>>8)&0xff);
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index d226716cdd49..d0401e38e927 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -344,6 +344,15 @@ public final class DeviceConfig {
@TestApi
String KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE =
"system_gestures_excluded_by_pre_q_sticky_immersive";
+
+ /**
+ * Key for controlling which packages are explicitly blocked from running at refresh rates
+ * higher than 90hz.
+ *
+ * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
+ * @hide
+ */
+ String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
}
private static final Object sLock = new Object();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2ee6b7df892d..5308cd3a0926 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -90,7 +90,6 @@ import android.util.ArraySet;
import android.util.Log;
import android.util.MemoryIntArray;
import android.view.Display;
-import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.widget.ILockSettings;
@@ -9298,13 +9297,6 @@ public final class Settings {
CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
CLONE_TO_MANAGED_PROFILE.add(LOCATION_PROVIDERS_ALLOWED);
CLONE_TO_MANAGED_PROFILE.add(SHOW_IME_WITH_HARD_KEYBOARD);
- if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
- CLONE_TO_MANAGED_PROFILE.add(DEFAULT_INPUT_METHOD);
- CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
- CLONE_TO_MANAGED_PROFILE.add(SELECTED_INPUT_METHOD_SUBTYPE);
- CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER);
- CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER_SUBTYPE);
- }
}
/** @hide */
diff --git a/core/java/android/view/inputmethod/InputMethodSystemProperty.java b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
index 05143a18415c..0689806bf832 100644
--- a/core/java/android/view/inputmethod/InputMethodSystemProperty.java
+++ b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
@@ -43,17 +43,6 @@ public class InputMethodSystemProperty {
*/
private static final String PROP_DEBUG_MULTI_CLIENT_IME = "persist.debug.multi_client_ime";
- /**
- * System property key for debugging purpose. The value must be empty, "1", or "0".
- *
- * <p>Values 'y', 'yes', '1', 'true' or 'on' are considered true.</p>
- *
- * <p>To set, run "adb root && adb shell setprop persist.debug.per_profile_ime 1".</p>
- *
- * <p>This value will be ignored when {@link Build#IS_DEBUGGABLE} returns {@code false}.</p>
- */
- private static final String PROP_DEBUG_PER_PROFILE_IME = "persist.debug.per_profile_ime";
-
@Nullable
private static ComponentName getMultiClientImeComponentName() {
if (Build.IS_DEBUGGABLE) {
@@ -91,19 +80,4 @@ public class InputMethodSystemProperty {
*/
@TestApi
public static final boolean MULTI_CLIENT_IME_ENABLED = (sMultiClientImeComponentName != null);
-
- /**
- * {@code true} when per-profile IME is enabled.
- * @hide
- */
- public static final boolean PER_PROFILE_IME_ENABLED;
- static {
- if (MULTI_CLIENT_IME_ENABLED) {
- PER_PROFILE_IME_ENABLED = true;
- } else if (Build.IS_DEBUGGABLE) {
- PER_PROFILE_IME_ENABLED = SystemProperties.getBoolean(PROP_DEBUG_PER_PROFILE_IME, true);
- } else {
- PER_PROFILE_IME_ENABLED = true;
- }
- }
}
diff --git a/core/java/android/view/textclassifier/ActionsModelParamsSupplier.java b/core/java/android/view/textclassifier/ActionsModelParamsSupplier.java
index 6b90588f8d25..31645672f049 100644
--- a/core/java/android/view/textclassifier/ActionsModelParamsSupplier.java
+++ b/core/java/android/view/textclassifier/ActionsModelParamsSupplier.java
@@ -60,7 +60,9 @@ public final class ActionsModelParamsSupplier implements
private boolean mParsed = true;
public ActionsModelParamsSupplier(Context context, @Nullable Runnable onChangedListener) {
- mAppContext = Preconditions.checkNotNull(context).getApplicationContext();
+ final Context appContext = Preconditions.checkNotNull(context).getApplicationContext();
+ // Some contexts don't have an app context.
+ mAppContext = appContext != null ? appContext : context;
mOnChangedListener = onChangedListener == null ? () -> {} : onChangedListener;
mSettingsObserver = new SettingsObserver(mAppContext, () -> {
synchronized (mLock) {
diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java
index aeb99b896b11..f7f503ab60ec 100644
--- a/core/java/android/view/textclassifier/ConversationActions.java
+++ b/core/java/android/view/textclassifier/ConversationActions.java
@@ -21,10 +21,12 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
+import android.annotation.UserIdInt;
import android.app.Person;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.text.SpannedString;
import com.android.internal.annotations.VisibleForTesting;
@@ -316,6 +318,8 @@ public final class ConversationActions implements Parcelable {
private final List<String> mHints;
@Nullable
private String mCallingPackageName;
+ @UserIdInt
+ private int mUserId = UserHandle.USER_NULL;
@NonNull
private Bundle mExtras;
@@ -340,6 +344,7 @@ public final class ConversationActions implements Parcelable {
List<String> hints = new ArrayList<>();
in.readStringList(hints);
String callingPackageName = in.readString();
+ int userId = in.readInt();
Bundle extras = in.readBundle();
Request request = new Request(
conversation,
@@ -348,6 +353,7 @@ public final class ConversationActions implements Parcelable {
hints,
extras);
request.setCallingPackageName(callingPackageName);
+ request.setUserId(userId);
return request;
}
@@ -358,6 +364,7 @@ public final class ConversationActions implements Parcelable {
parcel.writeInt(mMaxSuggestions);
parcel.writeStringList(mHints);
parcel.writeString(mCallingPackageName);
+ parcel.writeInt(mUserId);
parcel.writeBundle(mExtras);
}
@@ -428,6 +435,25 @@ public final class ConversationActions implements Parcelable {
}
/**
+ * Sets the id of the user that sent this request.
+ * <p>
+ * Package-private for SystemTextClassifier's use.
+ * @hide
+ */
+ void setUserId(@UserIdInt int userId) {
+ mUserId = userId;
+ }
+
+ /**
+ * Returns the id of the user that sent this request.
+ * @hide
+ */
+ @UserIdInt
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
* Returns the extended data related to this request.
*
* <p><b>NOTE: </b>Do not modify this bundle.
diff --git a/core/java/android/view/textclassifier/SelectionEvent.java b/core/java/android/view/textclassifier/SelectionEvent.java
index 374e66724ec6..80c728f662c6 100644
--- a/core/java/android/view/textclassifier/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/SelectionEvent.java
@@ -19,8 +19,10 @@ package android.view.textclassifier;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.view.textclassifier.TextClassifier.EntityType;
import android.view.textclassifier.TextClassifier.WidgetType;
@@ -127,6 +129,7 @@ public final class SelectionEvent implements Parcelable {
private String mWidgetType = TextClassifier.WIDGET_TYPE_UNKNOWN;
private @InvocationMethod int mInvocationMethod;
@Nullable private String mWidgetVersion;
+ private @UserIdInt int mUserId = UserHandle.USER_NULL;
@Nullable private String mResultId;
private long mEventTime;
private long mDurationSinceSessionStart;
@@ -158,6 +161,7 @@ public final class SelectionEvent implements Parcelable {
mEntityType = in.readString();
mWidgetVersion = in.readInt() > 0 ? in.readString() : null;
mPackageName = in.readString();
+ mUserId = in.readInt();
mWidgetType = in.readString();
mInvocationMethod = in.readInt();
mResultId = in.readString();
@@ -184,6 +188,7 @@ public final class SelectionEvent implements Parcelable {
dest.writeString(mWidgetVersion);
}
dest.writeString(mPackageName);
+ dest.writeInt(mUserId);
dest.writeString(mWidgetType);
dest.writeInt(mInvocationMethod);
dest.writeString(mResultId);
@@ -405,6 +410,15 @@ public final class SelectionEvent implements Parcelable {
}
/**
+ * Returns the id of this event's user.
+ * @hide
+ */
+ @UserIdInt
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
* Returns the type of widget that was involved in triggering this event.
*/
@WidgetType
@@ -430,6 +444,7 @@ public final class SelectionEvent implements Parcelable {
mPackageName = context.getPackageName();
mWidgetType = context.getWidgetType();
mWidgetVersion = context.getWidgetVersion();
+ mUserId = context.getUserId();
}
/**
@@ -616,7 +631,7 @@ public final class SelectionEvent implements Parcelable {
@Override
public int hashCode() {
return Objects.hash(mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
- mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod, mResultId,
+ mWidgetVersion, mPackageName, mUserId, mWidgetType, mInvocationMethod, mResultId,
mEventTime, mDurationSinceSessionStart, mDurationSincePreviousEvent,
mEventIndex, mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
}
@@ -637,6 +652,7 @@ public final class SelectionEvent implements Parcelable {
&& Objects.equals(mEntityType, other.mEntityType)
&& Objects.equals(mWidgetVersion, other.mWidgetVersion)
&& Objects.equals(mPackageName, other.mPackageName)
+ && mUserId == other.mUserId
&& Objects.equals(mWidgetType, other.mWidgetType)
&& mInvocationMethod == other.mInvocationMethod
&& Objects.equals(mResultId, other.mResultId)
@@ -656,12 +672,12 @@ public final class SelectionEvent implements Parcelable {
return String.format(Locale.US,
"SelectionEvent {absoluteStart=%d, absoluteEnd=%d, eventType=%d, entityType=%s, "
+ "widgetVersion=%s, packageName=%s, widgetType=%s, invocationMethod=%s, "
- + "resultId=%s, eventTime=%d, durationSinceSessionStart=%d, "
+ + "userId=%d, resultId=%s, eventTime=%d, durationSinceSessionStart=%d, "
+ "durationSincePreviousEvent=%d, eventIndex=%d,"
+ "sessionId=%s, start=%d, end=%d, smartStart=%d, smartEnd=%d}",
mAbsoluteStart, mAbsoluteEnd, mEventType, mEntityType,
mWidgetVersion, mPackageName, mWidgetType, mInvocationMethod,
- mResultId, mEventTime, mDurationSinceSessionStart,
+ mUserId, mResultId, mEventTime, mDurationSinceSessionStart,
mDurationSincePreviousEvent, mEventIndex,
mSessionId, mStart, mEnd, mSmartStart, mSmartEnd);
}
diff --git a/core/java/android/view/textclassifier/SystemTextClassifier.java b/core/java/android/view/textclassifier/SystemTextClassifier.java
index 8f8766e3f783..b5f972aea1d4 100644
--- a/core/java/android/view/textclassifier/SystemTextClassifier.java
+++ b/core/java/android/view/textclassifier/SystemTextClassifier.java
@@ -18,6 +18,7 @@ package android.view.textclassifier;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.content.Context;
import android.os.Bundle;
@@ -50,6 +51,10 @@ public final class SystemTextClassifier implements TextClassifier {
private final TextClassificationConstants mSettings;
private final TextClassifier mFallback;
private final String mPackageName;
+ // NOTE: Always set this before sending a request to the manager service otherwise the manager
+ // service will throw a remote exception.
+ @UserIdInt
+ private final int mUserId;
private TextClassificationSessionId mSessionId;
public SystemTextClassifier(Context context, TextClassificationConstants settings)
@@ -60,6 +65,7 @@ public final class SystemTextClassifier implements TextClassifier {
mFallback = context.getSystemService(TextClassificationManager.class)
.getTextClassifier(TextClassifier.LOCAL);
mPackageName = Preconditions.checkNotNull(context.getOpPackageName());
+ mUserId = context.getUserId();
}
/**
@@ -72,6 +78,7 @@ public final class SystemTextClassifier implements TextClassifier {
Utils.checkMainThread();
try {
request.setCallingPackageName(mPackageName);
+ request.setUserId(mUserId);
final BlockingCallback<TextSelection> callback =
new BlockingCallback<>("textselection");
mManagerService.onSuggestSelection(mSessionId, request, callback);
@@ -95,6 +102,7 @@ public final class SystemTextClassifier implements TextClassifier {
Utils.checkMainThread();
try {
request.setCallingPackageName(mPackageName);
+ request.setUserId(mUserId);
final BlockingCallback<TextClassification> callback =
new BlockingCallback<>("textclassification");
mManagerService.onClassifyText(mSessionId, request, callback);
@@ -123,6 +131,7 @@ public final class SystemTextClassifier implements TextClassifier {
try {
request.setCallingPackageName(mPackageName);
+ request.setUserId(mUserId);
final BlockingCallback<TextLinks> callback =
new BlockingCallback<>("textlinks");
mManagerService.onGenerateLinks(mSessionId, request, callback);
@@ -167,6 +176,7 @@ public final class SystemTextClassifier implements TextClassifier {
try {
request.setCallingPackageName(mPackageName);
+ request.setUserId(mUserId);
final BlockingCallback<TextLanguage> callback =
new BlockingCallback<>("textlanguage");
mManagerService.onDetectLanguage(mSessionId, request, callback);
@@ -187,6 +197,7 @@ public final class SystemTextClassifier implements TextClassifier {
try {
request.setCallingPackageName(mPackageName);
+ request.setUserId(mUserId);
final BlockingCallback<ConversationActions> callback =
new BlockingCallback<>("conversation-actions");
mManagerService.onSuggestConversationActions(mSessionId, request, callback);
@@ -228,6 +239,7 @@ public final class SystemTextClassifier implements TextClassifier {
printWriter.printPair("mFallback", mFallback);
printWriter.printPair("mPackageName", mPackageName);
printWriter.printPair("mSessionId", mSessionId);
+ printWriter.printPair("mUserId", mUserId);
printWriter.decreaseIndent();
printWriter.println();
}
@@ -243,6 +255,7 @@ public final class SystemTextClassifier implements TextClassifier {
@NonNull TextClassificationSessionId sessionId) {
mSessionId = Preconditions.checkNotNull(sessionId);
try {
+ classificationContext.setUserId(mUserId);
mManagerService.onCreateTextClassificationSession(classificationContext, mSessionId);
} catch (RemoteException e) {
Log.e(LOG_TAG, "Error starting a new classification session.", e);
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 63210516b3e1..93f7103c3d8d 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -21,6 +21,7 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.app.RemoteAction;
import android.content.Context;
@@ -35,6 +36,7 @@ import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.text.SpannedString;
import android.util.ArrayMap;
import android.view.View.OnClickListener;
@@ -551,6 +553,8 @@ public final class TextClassification implements Parcelable {
@Nullable private final ZonedDateTime mReferenceTime;
@NonNull private final Bundle mExtras;
@Nullable private String mCallingPackageName;
+ @UserIdInt
+ private int mUserId = UserHandle.USER_NULL;
private Request(
CharSequence text,
@@ -631,6 +635,25 @@ public final class TextClassification implements Parcelable {
}
/**
+ * Sets the id of the user that sent this request.
+ * <p>
+ * Package-private for SystemTextClassifier's use.
+ * @hide
+ */
+ void setUserId(@UserIdInt int userId) {
+ mUserId = userId;
+ }
+
+ /**
+ * Returns the id of the user that sent this request.
+ * @hide
+ */
+ @UserIdInt
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
* Returns the extended data.
*
* <p><b>NOTE: </b>Do not modify this bundle.
@@ -730,6 +753,7 @@ public final class TextClassification implements Parcelable {
dest.writeParcelable(mDefaultLocales, flags);
dest.writeString(mReferenceTime == null ? null : mReferenceTime.toString());
dest.writeString(mCallingPackageName);
+ dest.writeInt(mUserId);
dest.writeBundle(mExtras);
}
@@ -742,11 +766,13 @@ public final class TextClassification implements Parcelable {
final ZonedDateTime referenceTime = referenceTimeString == null
? null : ZonedDateTime.parse(referenceTimeString);
final String callingPackageName = in.readString();
+ final int userId = in.readInt();
final Bundle extras = in.readBundle();
final Request request = new Request(text, startIndex, endIndex,
defaultLocales, referenceTime, extras);
request.setCallingPackageName(callingPackageName);
+ request.setUserId(userId);
return request;
}
diff --git a/core/java/android/view/textclassifier/TextClassificationContext.java b/core/java/android/view/textclassifier/TextClassificationContext.java
index 3bf8e9bd2bf0..e4baaac9a300 100644
--- a/core/java/android/view/textclassifier/TextClassificationContext.java
+++ b/core/java/android/view/textclassifier/TextClassificationContext.java
@@ -18,8 +18,10 @@ package android.view.textclassifier;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.view.textclassifier.TextClassifier.WidgetType;
import com.android.internal.util.Preconditions;
@@ -35,6 +37,8 @@ public final class TextClassificationContext implements Parcelable {
private final String mPackageName;
private final String mWidgetType;
@Nullable private final String mWidgetVersion;
+ @UserIdInt
+ private int mUserId = UserHandle.USER_NULL;
private TextClassificationContext(
String packageName,
@@ -54,6 +58,25 @@ public final class TextClassificationContext implements Parcelable {
}
/**
+ * Sets the id of this context's user.
+ * <p>
+ * Package-private for SystemTextClassifier's use.
+ * @hide
+ */
+ void setUserId(@UserIdInt int userId) {
+ mUserId = userId;
+ }
+
+ /**
+ * Returns the id of this context's user.
+ * @hide
+ */
+ @UserIdInt
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
* Returns the widget type for this classification context.
*/
@NonNull
@@ -75,8 +98,8 @@ public final class TextClassificationContext implements Parcelable {
@Override
public String toString() {
return String.format(Locale.US, "TextClassificationContext{"
- + "packageName=%s, widgetType=%s, widgetVersion=%s}",
- mPackageName, mWidgetType, mWidgetVersion);
+ + "packageName=%s, widgetType=%s, widgetVersion=%s, userId=%d}",
+ mPackageName, mWidgetType, mWidgetVersion, mUserId);
}
/**
@@ -133,12 +156,14 @@ public final class TextClassificationContext implements Parcelable {
parcel.writeString(mPackageName);
parcel.writeString(mWidgetType);
parcel.writeString(mWidgetVersion);
+ parcel.writeInt(mUserId);
}
private TextClassificationContext(Parcel in) {
mPackageName = in.readString();
mWidgetType = in.readString();
mWidgetVersion = in.readString();
+ mUserId = in.readInt();
}
public static final @android.annotation.NonNull Parcelable.Creator<TextClassificationContext> CREATOR =
diff --git a/core/java/android/view/textclassifier/TextLanguage.java b/core/java/android/view/textclassifier/TextLanguage.java
index 6c75ffbea0cd..cc9109e6e9bb 100644
--- a/core/java/android/view/textclassifier/TextLanguage.java
+++ b/core/java/android/view/textclassifier/TextLanguage.java
@@ -20,10 +20,12 @@ import android.annotation.FloatRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.icu.util.ULocale;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.util.ArrayMap;
import com.android.internal.annotations.VisibleForTesting;
@@ -226,6 +228,8 @@ public final class TextLanguage implements Parcelable {
private final CharSequence mText;
private final Bundle mExtra;
@Nullable private String mCallingPackageName;
+ @UserIdInt
+ private int mUserId = UserHandle.USER_NULL;
private Request(CharSequence text, Bundle bundle) {
mText = text;
@@ -260,6 +264,25 @@ public final class TextLanguage implements Parcelable {
}
/**
+ * Sets the id of the user that sent this request.
+ * <p>
+ * Package-private for SystemTextClassifier's use.
+ * @hide
+ */
+ void setUserId(@UserIdInt int userId) {
+ mUserId = userId;
+ }
+
+ /**
+ * Returns the id of the user that sent this request.
+ * @hide
+ */
+ @UserIdInt
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
* Returns a bundle containing non-structured extra information about this request.
*
* <p><b>NOTE: </b>Do not modify this bundle.
@@ -278,16 +301,19 @@ public final class TextLanguage implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeCharSequence(mText);
dest.writeString(mCallingPackageName);
+ dest.writeInt(mUserId);
dest.writeBundle(mExtra);
}
private static Request readFromParcel(Parcel in) {
final CharSequence text = in.readCharSequence();
final String callingPackageName = in.readString();
+ final int userId = in.readInt();
final Bundle extra = in.readBundle();
final Request request = new Request(text, extra);
request.setCallingPackageName(callingPackageName);
+ request.setUserId(userId);
return request;
}
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index f3e0dc1ed843..bbb7f07e0fdc 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -20,11 +20,13 @@ import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.Context;
import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.text.Spannable;
import android.text.method.MovementMethod;
import android.text.style.ClickableSpan;
@@ -339,6 +341,8 @@ public final class TextLinks implements Parcelable {
private final boolean mLegacyFallback;
@Nullable private String mCallingPackageName;
private final Bundle mExtras;
+ @UserIdInt
+ private int mUserId = UserHandle.USER_NULL;
private Request(
CharSequence text,
@@ -410,6 +414,25 @@ public final class TextLinks implements Parcelable {
}
/**
+ * Sets the id of the user that sent this request.
+ * <p>
+ * Package-private for SystemTextClassifier's use.
+ * @hide
+ */
+ void setUserId(@UserIdInt int userId) {
+ mUserId = userId;
+ }
+
+ /**
+ * Returns the id of the user that sent this request.
+ * @hide
+ */
+ @UserIdInt
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
* Returns the extended data.
*
* <p><b>NOTE: </b>Do not modify this bundle.
@@ -509,6 +532,7 @@ public final class TextLinks implements Parcelable {
dest.writeParcelable(mDefaultLocales, flags);
dest.writeParcelable(mEntityConfig, flags);
dest.writeString(mCallingPackageName);
+ dest.writeInt(mUserId);
dest.writeBundle(mExtras);
}
@@ -517,11 +541,13 @@ public final class TextLinks implements Parcelable {
final LocaleList defaultLocales = in.readParcelable(null);
final EntityConfig entityConfig = in.readParcelable(null);
final String callingPackageName = in.readString();
+ final int userId = in.readInt();
final Bundle extras = in.readBundle();
final Request request = new Request(text, defaultLocales, entityConfig,
/* legacyFallback= */ true, extras);
request.setCallingPackageName(callingPackageName);
+ request.setUserId(userId);
return request;
}
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index 75c27bdbc1d5..0c8974956a7a 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -20,10 +20,12 @@ import android.annotation.FloatRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.os.Bundle;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
import android.text.SpannedString;
import android.util.ArrayMap;
import android.view.textclassifier.TextClassifier.EntityType;
@@ -211,6 +213,8 @@ public final class TextSelection implements Parcelable {
private final boolean mDarkLaunchAllowed;
private final Bundle mExtras;
@Nullable private String mCallingPackageName;
+ @UserIdInt
+ private int mUserId = UserHandle.USER_NULL;
private Request(
CharSequence text,
@@ -292,6 +296,25 @@ public final class TextSelection implements Parcelable {
}
/**
+ * Sets the id of the user that sent this request.
+ * <p>
+ * Package-private for SystemTextClassifier's use.
+ * @hide
+ */
+ void setUserId(@UserIdInt int userId) {
+ mUserId = userId;
+ }
+
+ /**
+ * Returns the id of the user that sent this request.
+ * @hide
+ */
+ @UserIdInt
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
* Returns the extended data.
*
* <p><b>NOTE: </b>Do not modify this bundle.
@@ -394,6 +417,7 @@ public final class TextSelection implements Parcelable {
dest.writeInt(mEndIndex);
dest.writeParcelable(mDefaultLocales, flags);
dest.writeString(mCallingPackageName);
+ dest.writeInt(mUserId);
dest.writeBundle(mExtras);
}
@@ -403,11 +427,13 @@ public final class TextSelection implements Parcelable {
final int endIndex = in.readInt();
final LocaleList defaultLocales = in.readParcelable(null);
final String callingPackageName = in.readString();
+ final int userId = in.readInt();
final Bundle extras = in.readBundle();
final Request request = new Request(text, startIndex, endIndex, defaultLocales,
/* darkLaunchAllowed= */ false, extras);
request.setCallingPackageName(callingPackageName);
+ request.setUserId(userId);
return request;
}
diff --git a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
index f5d6fcaae480..157c43597a44 100644
--- a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
+++ b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java
@@ -27,6 +27,7 @@ import android.view.textclassifier.TextClassification;
import android.view.textclassifier.TextClassifier;
import android.view.textclassifier.TextSelection;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.Preconditions;
@@ -551,10 +552,11 @@ public final class SmartSelectionEventTracker {
return new SelectionEvent(start, end, actionType, entityType, versionTag);
}
- private static String getVersionInfo(String signature) {
- final int start = signature.indexOf("|");
+ @VisibleForTesting
+ public static String getVersionInfo(String signature) {
+ final int start = signature.indexOf("|") + 1;
final int end = signature.indexOf("|", start);
- if (start >= 0 && end >= start) {
+ if (start >= 1 && end >= start) {
return signature.substring(start, end);
}
return "";
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 339947ac8d5a..67a70b48b534 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -26,12 +26,14 @@ import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.text.format.DateUtils;
-import android.text.format.Time;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RemoteViews.RemoteView;
-import java.util.TimeZone;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
/**
* This widget display an analogic clock with two hands for hours and
@@ -45,7 +47,7 @@ import java.util.TimeZone;
@RemoteView
@Deprecated
public class AnalogClock extends View {
- private Time mCalendar;
+ private Clock mClock;
@UnsupportedAppUsage
private Drawable mHourHand;
@@ -99,7 +101,7 @@ public class AnalogClock extends View {
mMinuteHand = context.getDrawable(com.android.internal.R.drawable.clock_hand_minute);
}
- mCalendar = new Time();
+ mClock = Clock.systemDefaultZone();
mDialWidth = mDial.getIntrinsicWidth();
mDialHeight = mDial.getIntrinsicHeight();
@@ -132,7 +134,7 @@ public class AnalogClock extends View {
// in the main thread, therefore the receiver can't run before this method returns.
// The time zone may have changed while the receiver wasn't registered, so update the Time
- mCalendar = new Time();
+ mClock = Clock.systemDefaultZone();
// Make sure we update to the current time
onTimeChanged();
@@ -241,17 +243,18 @@ public class AnalogClock extends View {
}
private void onTimeChanged() {
- mCalendar.setToNow();
+ long nowMillis = mClock.millis();
+ LocalDateTime localDateTime = toLocalDateTime(nowMillis, mClock.getZone());
- int hour = mCalendar.hour;
- int minute = mCalendar.minute;
- int second = mCalendar.second;
+ int hour = localDateTime.getHour();
+ int minute = localDateTime.getMinute();
+ int second = localDateTime.getSecond();
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
mChanged = true;
- updateContentDescription(mCalendar);
+ updateContentDescription(nowMillis);
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -259,7 +262,7 @@ public class AnalogClock extends View {
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
String tz = intent.getStringExtra("time-zone");
- mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
+ mClock = Clock.system(ZoneId.of(tz));
}
onTimeChanged();
@@ -268,10 +271,17 @@ public class AnalogClock extends View {
}
};
- private void updateContentDescription(Time time) {
+ private void updateContentDescription(long timeMillis) {
final int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_24HOUR;
- String contentDescription = DateUtils.formatDateTime(mContext,
- time.toMillis(false), flags);
+ String contentDescription = DateUtils.formatDateTime(mContext, timeMillis, flags);
setContentDescription(contentDescription);
}
+
+ private static LocalDateTime toLocalDateTime(long timeMillis, ZoneId zoneId) {
+ // java.time types like LocalDateTime / Instant can support the full range of "long millis"
+ // with room to spare so we do not need to worry about overflow / underflow and the
+ // resulting exceptions while the input to this class is a long.
+ Instant instant = Instant.ofEpochMilli(timeMillis);
+ return LocalDateTime.ofInstant(instant, zoneId);
+ }
}
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index 0469dbd00dc9..2864ad0b7932 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -20,7 +20,6 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.YEAR_IN_MILLIS;
-import static android.text.format.Time.getJulianDay;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
@@ -32,7 +31,6 @@ import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.os.Handler;
-import android.text.format.Time;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inspector.InspectableProperty;
@@ -41,10 +39,14 @@ import android.widget.RemoteViews.RemoteView;
import com.android.internal.R;
import java.text.DateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.temporal.JulianFields;
import java.util.ArrayList;
-import java.util.Calendar;
import java.util.Date;
-import java.util.TimeZone;
//
// TODO
@@ -63,8 +65,9 @@ public class DateTimeView extends TextView {
private static final int SHOW_TIME = 0;
private static final int SHOW_MONTH_DAY_YEAR = 1;
- Date mTime;
- long mTimeMillis;
+ private long mTimeMillis;
+ // The LocalDateTime equivalent of mTimeMillis but truncated to minute, i.e. no seconds / nanos.
+ private LocalDateTime mLocalTime;
int mLastDisplay = -1;
DateFormat mLastFormat;
@@ -128,11 +131,10 @@ public class DateTimeView extends TextView {
@android.view.RemotableViewMethod
@UnsupportedAppUsage
- public void setTime(long time) {
- Time t = new Time();
- t.set(time);
- mTimeMillis = t.toMillis(false);
- mTime = new Date(t.year-1900, t.month, t.monthDay, t.hour, t.minute, 0);
+ public void setTime(long timeMillis) {
+ mTimeMillis = timeMillis;
+ LocalDateTime dateTime = toLocalDateTime(timeMillis, ZoneId.systemDefault());
+ mLocalTime = dateTime.withSecond(0);
update();
}
@@ -165,7 +167,7 @@ public class DateTimeView extends TextView {
@UnsupportedAppUsage
void update() {
- if (mTime == null || getVisibility() == GONE) {
+ if (mLocalTime == null || getVisibility() == GONE) {
return;
}
if (mShowRelativeTime) {
@@ -174,31 +176,27 @@ public class DateTimeView extends TextView {
}
int display;
- Date time = mTime;
-
- Time t = new Time();
- t.set(mTimeMillis);
- t.second = 0;
-
- t.hour -= 12;
- long twelveHoursBefore = t.toMillis(false);
- t.hour += 12;
- long twelveHoursAfter = t.toMillis(false);
- t.hour = 0;
- t.minute = 0;
- long midnightBefore = t.toMillis(false);
- t.monthDay++;
- long midnightAfter = t.toMillis(false);
-
- long nowMillis = System.currentTimeMillis();
- t.set(nowMillis);
- t.second = 0;
- nowMillis = t.normalize(false);
+ ZoneId zoneId = ZoneId.systemDefault();
+
+ // localTime is the local time for mTimeMillis but at zero seconds past the minute.
+ LocalDateTime localTime = mLocalTime;
+ LocalDateTime localStartOfDay =
+ LocalDateTime.of(localTime.toLocalDate(), LocalTime.MIDNIGHT);
+ LocalDateTime localTomorrowStartOfDay = localStartOfDay.plusDays(1);
+ // now is current local time but at zero seconds past the minute.
+ LocalDateTime localNow = LocalDateTime.now(zoneId).withSecond(0);
+
+ long twelveHoursBefore = toEpochMillis(localTime.minusHours(12), zoneId);
+ long twelveHoursAfter = toEpochMillis(localTime.plusHours(12), zoneId);
+ long midnightBefore = toEpochMillis(localStartOfDay, zoneId);
+ long midnightAfter = toEpochMillis(localTomorrowStartOfDay, zoneId);
+ long time = toEpochMillis(localTime, zoneId);
+ long now = toEpochMillis(localNow, zoneId);
// Choose the display mode
choose_display: {
- if ((nowMillis >= midnightBefore && nowMillis < midnightAfter)
- || (nowMillis >= twelveHoursBefore && nowMillis < twelveHoursAfter)) {
+ if ((now >= midnightBefore && now < midnightAfter)
+ || (now >= twelveHoursBefore && now < twelveHoursAfter)) {
display = SHOW_TIME;
break choose_display;
}
@@ -227,7 +225,7 @@ public class DateTimeView extends TextView {
}
// Set the text
- String text = format.format(mTime);
+ String text = format.format(new Date(time));
setText(text);
// Schedule the next update
@@ -236,7 +234,7 @@ public class DateTimeView extends TextView {
mUpdateTimeMillis = twelveHoursAfter > midnightAfter ? twelveHoursAfter : midnightAfter;
} else {
// Currently showing the date
- if (mTimeMillis < nowMillis) {
+ if (mTimeMillis < now) {
// If the time is in the past, don't schedule an update
mUpdateTimeMillis = 0;
} else {
@@ -277,15 +275,18 @@ public class DateTimeView extends TextView {
millisIncrease = HOUR_IN_MILLIS;
} else if (duration < YEAR_IN_MILLIS) {
// In weird cases it can become 0 because of daylight savings
- TimeZone timeZone = TimeZone.getDefault();
- count = Math.max(Math.abs(dayDistance(timeZone, mTimeMillis, now)), 1);
+ LocalDateTime localDateTime = mLocalTime;
+ ZoneId zoneId = ZoneId.systemDefault();
+ LocalDateTime localNow = toLocalDateTime(now, zoneId);
+
+ count = Math.max(Math.abs(dayDistance(localDateTime, localNow)), 1);
result = String.format(getContext().getResources().getQuantityString(past
? com.android.internal.R.plurals.duration_days_shortest
: com.android.internal.R.plurals.duration_days_shortest_future,
count),
count);
if (past || count != 1) {
- mUpdateTimeMillis = computeNextMidnight(timeZone);
+ mUpdateTimeMillis = computeNextMidnight(localNow, zoneId);
millisIncrease = -1;
} else {
millisIncrease = DAY_IN_MILLIS;
@@ -311,18 +312,13 @@ public class DateTimeView extends TextView {
}
/**
- * @param timeZone the timezone we are in
- * @return the timepoint in millis at UTC at midnight in the current timezone
+ * Returns the epoch millis for the next midnight in the specified timezone.
*/
- private long computeNextMidnight(TimeZone timeZone) {
- Calendar c = Calendar.getInstance();
- c.setTimeZone(timeZone);
- c.add(Calendar.DAY_OF_MONTH, 1);
- c.set(Calendar.HOUR_OF_DAY, 0);
- c.set(Calendar.MINUTE, 0);
- c.set(Calendar.SECOND, 0);
- c.set(Calendar.MILLISECOND, 0);
- return c.getTimeInMillis();
+ private static long computeNextMidnight(LocalDateTime time, ZoneId zoneId) {
+ // This ignores the chance of overflow: it should never happen.
+ LocalDate tomorrow = time.toLocalDate().plusDays(1);
+ LocalDateTime nextMidnight = LocalDateTime.of(tomorrow, LocalTime.MIDNIGHT);
+ return toEpochMillis(nextMidnight, zoneId);
}
@Override
@@ -340,11 +336,10 @@ public class DateTimeView extends TextView {
com.android.internal.R.string.now_string_shortest);
}
- // Return the date difference for the two times in a given timezone.
- private static int dayDistance(TimeZone timeZone, long startTime,
- long endTime) {
- return getJulianDay(endTime, timeZone.getOffset(endTime) / 1000)
- - getJulianDay(startTime, timeZone.getOffset(startTime) / 1000);
+ // Return the number of days between the two dates.
+ private static int dayDistance(LocalDateTime start, LocalDateTime end) {
+ return (int) (end.getLong(JulianFields.JULIAN_DAY)
+ - start.getLong(JulianFields.JULIAN_DAY));
}
private DateFormat getTimeFormat() {
@@ -389,8 +384,11 @@ public class DateTimeView extends TextView {
count);
} else if (duration < YEAR_IN_MILLIS) {
// In weird cases it can become 0 because of daylight savings
- TimeZone timeZone = TimeZone.getDefault();
- count = Math.max(Math.abs(dayDistance(timeZone, mTimeMillis, now)), 1);
+ LocalDateTime localDateTime = mLocalTime;
+ ZoneId zoneId = ZoneId.systemDefault();
+ LocalDateTime localNow = toLocalDateTime(now, zoneId);
+
+ count = Math.max(Math.abs(dayDistance(localDateTime, localNow)), 1);
result = String.format(getContext().getResources().getQuantityString(past
? com.android.internal.
R.plurals.duration_days_relative
@@ -526,4 +524,17 @@ public class DateTimeView extends TextView {
}
}
}
+
+ private static LocalDateTime toLocalDateTime(long timeMillis, ZoneId zoneId) {
+ // java.time types like LocalDateTime / Instant can support the full range of "long millis"
+ // with room to spare so we do not need to worry about overflow / underflow and the rsulting
+ // exceptions while the input to this class is a long.
+ Instant instant = Instant.ofEpochMilli(timeMillis);
+ return LocalDateTime.ofInstant(instant, zoneId);
+ }
+
+ private static long toEpochMillis(LocalDateTime time, ZoneId zoneId) {
+ Instant instant = time.toInstant(zoneId.getRules().getOffset(time));
+ return instant.toEpochMilli();
+ }
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 95cf9a914854..a4844eaa612c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11283,6 +11283,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
@Nullable
+ final TextClassificationManager getTextClassificationManagerForUser() {
+ return getServiceManagerForUser(
+ getContext().getPackageName(), TextClassificationManager.class);
+ }
+
+ @Nullable
final <T> T getServiceManagerForUser(String packageName, Class<T> managerClazz) {
if (mTextOperationUser == null) {
return getContext().getSystemService(managerClazz);
@@ -12397,8 +12403,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@NonNull
public TextClassifier getTextClassifier() {
if (mTextClassifier == null) {
- final TextClassificationManager tcm =
- mContext.getSystemService(TextClassificationManager.class);
+ final TextClassificationManager tcm = getTextClassificationManagerForUser();
if (tcm != null) {
return tcm.getTextClassifier();
}
@@ -12414,8 +12419,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@NonNull
TextClassifier getTextClassificationSession() {
if (mTextClassificationSession == null || mTextClassificationSession.isDestroyed()) {
- final TextClassificationManager tcm =
- mContext.getSystemService(TextClassificationManager.class);
+ final TextClassificationManager tcm = getTextClassificationManagerForUser();
if (tcm != null) {
final String widgetType;
if (isTextEditable()) {
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 57785443919e..157e0a74712b 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -16,252 +16,167 @@
package com.android.internal.app;
+import android.animation.ObjectAnimator;
import android.animation.TimeAnimator;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.ColorFilter;
+import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
+import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
import android.view.View;
-import android.widget.FrameLayout;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.android.internal.R;
import org.json.JSONObject;
+/**
+ * @hide
+ */
public class PlatLogoActivity extends Activity {
- FrameLayout layout;
- TimeAnimator anim;
- PBackground bg;
-
- private class PBackground extends Drawable {
- private float maxRadius, radius, x, y, dp;
- private int[] palette;
- private int darkest;
- private float offset;
-
- public PBackground() {
- randomizePalette();
- }
-
- /**
- * set inner radius of "p" logo
- */
- public void setRadius(float r) {
- this.radius = Math.max(48*dp, r);
- }
-
- /**
- * move the "p"
- */
- public void setPosition(float x, float y) {
- this.x = x;
- this.y = y;
- }
-
- /**
- * for animating the "p"
- */
- public void setOffset(float o) {
- this.offset = o;
- }
-
- /**
- * rough luminance calculation
- * https://www.w3.org/TR/AERT/#color-contrast
- */
- public float lum(int rgb) {
- return ((Color.red(rgb) * 299f) + (Color.green(rgb) * 587f) + (Color.blue(rgb) * 114f)) / 1000f;
- }
-
- /**
- * create a random evenly-spaced color palette
- * guaranteed to contrast!
- */
- public void randomizePalette() {
- final int slots = 2 + (int)(Math.random() * 2);
- float[] color = new float[] { (float) Math.random() * 360f, 1f, 1f };
- palette = new int[slots];
- darkest = 0;
- for (int i=0; i<slots; i++) {
- palette[i] = Color.HSVToColor(color);
- color[0] = (color[0] + 360f/slots) % 360f;
- if (lum(palette[i]) < lum(palette[darkest])) darkest = i;
- }
-
- final StringBuilder str = new StringBuilder();
- for (int c : palette) {
- str.append(String.format("#%08x ", c));
- }
- Log.v("PlatLogoActivity", "color palette: " + str);
- }
-
- @Override
- public void draw(Canvas canvas) {
- if (dp == 0) dp = getResources().getDisplayMetrics().density;
- final float width = canvas.getWidth();
- final float height = canvas.getHeight();
- if (radius == 0) {
- setPosition(width / 2, height / 2);
- setRadius(width / 6);
- }
- final float inner_w = radius * 0.667f;
-
- final Paint paint = new Paint();
- paint.setStrokeCap(Paint.Cap.BUTT);
- canvas.translate(x, y);
-
- Path p = new Path();
- p.moveTo(-radius, height);
- p.lineTo(-radius, 0);
- p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
- p.lineTo(-radius, radius);
-
- float w = Math.max(canvas.getWidth(), canvas.getHeight()) * 1.414f;
- paint.setStyle(Paint.Style.FILL);
-
- int i=0;
- while (w > radius*2 + inner_w*2) {
- paint.setColor(0xFF000000 | palette[i % palette.length]);
- // for a slower but more complete version:
- // paint.setStrokeWidth(w);
- // canvas.drawPath(p, paint);
- canvas.drawOval(-w/2, -w/2, w/2, w/2, paint);
- w -= inner_w * (1.1f + Math.sin((i/20f + offset) * 3.14159f));
- i++;
- }
-
- // the innermost circle needs to be a constant color to avoid rapid flashing
- paint.setColor(0xFF000000 | palette[(darkest+1) % palette.length]);
- canvas.drawOval(-radius, -radius, radius, radius, paint);
-
- p.reset();
- p.moveTo(-radius, height);
- p.lineTo(-radius, 0);
- p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
- p.lineTo(-radius + inner_w, radius);
-
- paint.setStyle(Paint.Style.STROKE);
- paint.setStrokeWidth(inner_w*2);
- paint.setColor(palette[darkest]);
- canvas.drawPath(p, paint);
- paint.setStrokeWidth(inner_w);
- paint.setColor(0xFFFFFFFF);
- canvas.drawPath(p, paint);
- }
-
- @Override
- public void setAlpha(int alpha) {
-
- }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {
-
- }
+ ImageView mZeroView, mOneView;
+ BackslashDrawable mBackslash;
+ int mClicks;
+
+ static final Paint sPaint = new Paint();
+ static {
+ sPaint.setStyle(Paint.Style.STROKE);
+ sPaint.setStrokeWidth(4f);
+ sPaint.setStrokeCap(Paint.Cap.SQUARE);
+ }
- @Override
- public int getOpacity() {
- return 0;
+ @Override
+ protected void onPause() {
+ if (mBackslash != null) {
+ mBackslash.stopAnimating();
}
+ mClicks = 0;
+ super.onPause();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ final float dp = getResources().getDisplayMetrics().density;
- layout = new FrameLayout(this);
- setContentView(layout);
+ getWindow().getDecorView().setSystemUiVisibility(
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ getWindow().setNavigationBarColor(0);
+ getWindow().setStatusBarColor(0);
- bg = new PBackground();
- layout.setBackground(bg);
+ getActionBar().hide();
- final ContentResolver cr = getContentResolver();
+ setContentView(R.layout.platlogo_layout);
- layout.setOnTouchListener(new View.OnTouchListener() {
- final String TOUCH_STATS = "touch.stats";
+ mBackslash = new BackslashDrawable((int) (50 * dp));
- final PointerCoords pc0 = new PointerCoords();
- final PointerCoords pc1 = new PointerCoords();
+ mOneView = findViewById(R.id.one);
+ mOneView.setImageDrawable(new OneDrawable());
+ mZeroView = findViewById(R.id.zero);
+ mZeroView.setImageDrawable(new ZeroDrawable());
- double pressure_min, pressure_max;
- int maxPointers;
- int tapCount;
+ final ViewGroup root = (ViewGroup) mOneView.getParent();
+ root.setClipChildren(false);
+ root.setBackground(mBackslash);
+ root.getBackground().setAlpha(0x20);
+ View.OnTouchListener tl = new View.OnTouchListener() {
+ float mOffsetX, mOffsetY;
+ long mClickTime;
+ ObjectAnimator mRotAnim;
@Override
public boolean onTouch(View v, MotionEvent event) {
- final float pressure = event.getPressure();
+ measureTouchPressure(event);
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
- pressure_min = pressure_max = pressure;
- // fall through
- case MotionEvent.ACTION_MOVE:
- if (pressure < pressure_min) pressure_min = pressure;
- if (pressure > pressure_max) pressure_max = pressure;
- final int pc = event.getPointerCount();
- if (pc > maxPointers) maxPointers = pc;
- if (pc > 1) {
- event.getPointerCoords(0, pc0);
- event.getPointerCoords(1, pc1);
- bg.setRadius((float) Math.hypot(pc0.x - pc1.x, pc0.y - pc1.y) / 2f);
+ v.animate().scaleX(1.1f).scaleY(1.1f);
+ v.getParent().bringChildToFront(v);
+ mOffsetX = event.getRawX() - v.getX();
+ mOffsetY = event.getRawY() - v.getY();
+ long now = System.currentTimeMillis();
+ if (now - mClickTime < 350) {
+ mRotAnim = ObjectAnimator.ofFloat(v, View.ROTATION,
+ v.getRotation(), v.getRotation() + 3600);
+ mRotAnim.setDuration(10000);
+ mRotAnim.start();
+ mClickTime = 0;
+ } else {
+ mClickTime = now;
}
break;
- case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_MOVE:
+ v.setX(event.getRawX() - mOffsetX);
+ v.setY(event.getRawY() - mOffsetY);
+ v.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE);
+ break;
case MotionEvent.ACTION_UP:
- try {
- final String touchDataJson = Settings.System.getString(cr, TOUCH_STATS);
- final JSONObject touchData = new JSONObject(
- touchDataJson != null ? touchDataJson : "{}");
- if (touchData.has("min")) {
- pressure_min = Math.min(pressure_min, touchData.getDouble("min"));
- }
- if (touchData.has("max")) {
- pressure_max = Math.max(pressure_max, touchData.getDouble("max"));
- }
- touchData.put("min", pressure_min);
- touchData.put("max", pressure_max);
- Settings.System.putString(cr, TOUCH_STATS, touchData.toString());
- } catch (Exception e) {
- Log.e("PlatLogoActivity", "Can't write touch settings", e);
- }
-
- if (maxPointers == 1) {
- tapCount ++;
- if (tapCount < 7) {
- bg.randomizePalette();
- } else {
- launchNextStage();
- }
- } else {
- tapCount = 0;
- }
- maxPointers = 0;
+ v.performClick();
+ // fall through
+ case MotionEvent.ACTION_CANCEL:
+ v.animate().scaleX(1f).scaleY(1f);
+ if (mRotAnim != null) mRotAnim.cancel();
+ testOverlap();
break;
}
return true;
}
- });
+ };
+
+ findViewById(R.id.one).setOnTouchListener(tl);
+ findViewById(R.id.zero).setOnTouchListener(tl);
+ findViewById(R.id.text).setOnTouchListener(tl);
+ }
+
+ private void testOverlap() {
+ final float width = mZeroView.getWidth();
+ final float targetX = mZeroView.getX() + width * .2f;
+ final float targetY = mZeroView.getY() + width * .3f;
+ if (Math.hypot(targetX - mOneView.getX(), targetY - mOneView.getY()) < width * .2f
+ && Math.abs(mOneView.getRotation() % 360 - 315) < 15) {
+ mOneView.animate().x(mZeroView.getX() + width * .2f);
+ mOneView.animate().y(mZeroView.getY() + width * .3f);
+ mOneView.setRotation(mOneView.getRotation() % 360);
+ mOneView.animate().rotation(315);
+ mOneView.performHapticFeedback(HapticFeedbackConstants.CONFIRM);
+
+ mBackslash.startAnimating();
+
+ mClicks++;
+ if (mClicks >= 7) {
+ launchNextStage();
+ }
+ } else {
+ mBackslash.stopAnimating();
+ }
}
private void launchNextStage() {
final ContentResolver cr = getContentResolver();
- if (Settings.System.getLong(cr, Settings.System.EGG_MODE, 0) == 0) {
+ if (Settings.System.getLong(cr, "egg_mode" /* Settings.System.EGG_MODE */, 0) == 0) {
// For posterity: the moment this user unlocked the easter egg
try {
Settings.System.putLong(cr,
- Settings.System.EGG_MODE,
+ "egg_mode", // Settings.System.EGG_MODE,
System.currentTimeMillis());
} catch (RuntimeException e) {
- Log.e("PlatLogoActivity", "Can't write settings", e);
+ Log.e("com.android.internal.app.PlatLogoActivity", "Can't write settings", e);
}
}
try {
@@ -270,36 +185,206 @@ public class PlatLogoActivity extends Activity {
| Intent.FLAG_ACTIVITY_CLEAR_TASK)
.addCategory("com.android.internal.category.PLATLOGO"));
} catch (ActivityNotFoundException ex) {
- Log.e("PlatLogoActivity", "No more eggs.");
+ Log.e("com.android.internal.app.PlatLogoActivity", "No more eggs.");
}
finish();
}
+ static final String TOUCH_STATS = "touch.stats";
+ double mPressureMin = 0, mPressureMax = -1;
+
+ private void measureTouchPressure(MotionEvent event) {
+ final float pressure = event.getPressure();
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ if (mPressureMax < 0) {
+ mPressureMin = mPressureMax = pressure;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (pressure < mPressureMin) mPressureMin = pressure;
+ if (pressure > mPressureMax) mPressureMax = pressure;
+ break;
+ }
+ }
+
+ private void syncTouchPressure() {
+ try {
+ final String touchDataJson = Settings.System.getString(
+ getContentResolver(), TOUCH_STATS);
+ final JSONObject touchData = new JSONObject(
+ touchDataJson != null ? touchDataJson : "{}");
+ if (touchData.has("min")) {
+ mPressureMin = Math.min(mPressureMin, touchData.getDouble("min"));
+ }
+ if (touchData.has("max")) {
+ mPressureMax = Math.max(mPressureMax, touchData.getDouble("max"));
+ }
+ if (mPressureMax >= 0) {
+ touchData.put("min", mPressureMin);
+ touchData.put("max", mPressureMax);
+ Settings.System.putString(getContentResolver(), TOUCH_STATS, touchData.toString());
+ }
+ } catch (Exception e) {
+ Log.e("com.android.internal.app.PlatLogoActivity", "Can't write touch settings", e);
+ }
+ }
+
@Override
public void onStart() {
super.onStart();
+ syncTouchPressure();
+ }
- bg.randomizePalette();
+ @Override
+ public void onStop() {
+ syncTouchPressure();
+ super.onStop();
+ }
- anim = new TimeAnimator();
- anim.setTimeListener(
- new TimeAnimator.TimeListener() {
- @Override
- public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
- bg.setOffset((float) totalTime / 60000f);
- bg.invalidateSelf();
- }
- });
+ static class ZeroDrawable extends Drawable {
+ int mTintColor;
+
+ @Override
+ public void draw(Canvas canvas) {
+ sPaint.setColor(mTintColor | 0xFF000000);
+
+ canvas.save();
+ canvas.scale(canvas.getWidth() / 24f, canvas.getHeight() / 24f);
+
+ canvas.drawCircle(12f, 12f, 10f, sPaint);
+ canvas.restore();
+ }
- anim.start();
+ @Override
+ public void setAlpha(int alpha) { }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) { }
+
+ @Override
+ public void setTintList(ColorStateList tint) {
+ mTintColor = tint.getDefaultColor();
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
}
- @Override
- public void onStop() {
- if (anim != null) {
- anim.cancel();
- anim = null;
+ static class OneDrawable extends Drawable {
+ int mTintColor;
+
+ @Override
+ public void draw(Canvas canvas) {
+ sPaint.setColor(mTintColor | 0xFF000000);
+
+ canvas.save();
+ canvas.scale(canvas.getWidth() / 24f, canvas.getHeight() / 24f);
+
+ final Path p = new Path();
+ p.moveTo(12f, 21.83f);
+ p.rLineTo(0f, -19.67f);
+ p.rLineTo(-5f, 0f);
+ canvas.drawPath(p, sPaint);
+ canvas.restore();
+ }
+
+ @Override
+ public void setAlpha(int alpha) { }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) { }
+
+ @Override
+ public void setTintList(ColorStateList tint) {
+ mTintColor = tint.getDefaultColor();
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+ }
+
+ private static class BackslashDrawable extends Drawable implements TimeAnimator.TimeListener {
+ Bitmap mTile;
+ Paint mPaint = new Paint();
+ BitmapShader mShader;
+ TimeAnimator mAnimator = new TimeAnimator();
+ Matrix mMatrix = new Matrix();
+
+ public void draw(Canvas canvas) {
+ canvas.drawPaint(mPaint);
+ }
+
+ BackslashDrawable(int width) {
+ mTile = Bitmap.createBitmap(width, width, Bitmap.Config.ALPHA_8);
+ mAnimator.setTimeListener(this);
+
+ final Canvas tileCanvas = new Canvas(mTile);
+ final float w = tileCanvas.getWidth();
+ final float h = tileCanvas.getHeight();
+
+ final Path path = new Path();
+ path.moveTo(0, 0);
+ path.lineTo(w / 2, 0);
+ path.lineTo(w, h / 2);
+ path.lineTo(w, h);
+ path.close();
+
+ path.moveTo(0, h / 2);
+ path.lineTo(w / 2, h);
+ path.lineTo(0, h);
+ path.close();
+
+ final Paint slashPaint = new Paint();
+ slashPaint.setAntiAlias(true);
+ slashPaint.setStyle(Paint.Style.FILL);
+ slashPaint.setColor(0xFF000000);
+ tileCanvas.drawPath(path, slashPaint);
+
+ //mPaint.setColor(0xFF0000FF);
+ mShader = new BitmapShader(mTile, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
+ mPaint.setShader(mShader);
+ }
+
+ public void startAnimating() {
+ if (!mAnimator.isStarted()) {
+ mAnimator.start();
+ }
+ }
+
+ public void stopAnimating() {
+ if (mAnimator.isStarted()) {
+ mAnimator.cancel();
+ }
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mPaint.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ mPaint.setColorFilter(colorFilter);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+ if (mShader != null) {
+ mMatrix.postTranslate(deltaTime / 4f, 0);
+ mShader.setLocalMatrix(mMatrix);
+ invalidateSelf();
+ }
}
- super.onStop();
}
}
+
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 457308498398..88d0e8534a0a 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -3478,10 +3478,8 @@ public class BatteryStatsImpl extends BatteryStats {
if (deltaTimeToken < DELTA_TIME_ABS) {
cur.time += deltaTimeToken;
} else if (deltaTimeToken == DELTA_TIME_ABS) {
- cur.time = src.readLong();
- cur.numReadInts += 2;
- if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
cur.readFromParcel(src);
+ if (DEBUG) Slog.i(TAG, "READ DELTA: ABS time=" + cur.time);
return;
} else if (deltaTimeToken == DELTA_TIME_INT) {
int delta = src.readInt();
@@ -13459,9 +13457,8 @@ public class BatteryStatsImpl extends BatteryStats {
return;
}
mHistory = mHistoryEnd = mHistoryCache = null;
- long time;
- while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
- HistoryItem rec = new HistoryItem(time, in);
+ while (in.dataAvail() > 0) {
+ HistoryItem rec = new HistoryItem(in);
addHistoryRecordLocked(rec);
}
}
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index 5b6b619ed7d2..1afc67b3de9b 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -24,8 +24,6 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.util.Size;
import android.view.Gravity;
-import android.view.ViewConfiguration;
-import android.widget.Scroller;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -180,14 +178,6 @@ public class PipSnapAlgorithm {
// If we're not flinging along the current edge, find the closest point instead.
final double distanceVert = Math.hypot(vertPoint.x - x, vertPoint.y - y);
final double distanceHoriz = Math.hypot(horizPoint.x - x, horizPoint.y - y);
- // Ensure that we're actually going somewhere
- if (distanceVert == 0) {
- return horizPoint;
- }
- if (distanceHoriz == 0) {
- return vertPoint;
- }
- // Otherwise use the closest point
return Math.abs(distanceVert) > Math.abs(distanceHoriz) ? horizPoint : vertPoint;
}
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 14dbabb1ce02..c3e7a36bef78 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -575,7 +575,7 @@ static void android_os_Debug_getMemInfo(JNIEnv *env, jobject clazz, jlongArray o
if (outArray != NULL) {
outLen = MEMINFO_COUNT;
for (int i = 0; i < outLen; i++) {
- if (i == MEMINFO_VMALLOC_USED) {
+ if (i == MEMINFO_VMALLOC_USED && mem[i] == 0) {
outArray[i] = smi.ReadVmallocInfo() / 1024;
continue;
}
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 2542286635e6..f90d1cf27d7c 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -141,6 +141,7 @@ status_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent
event->getClassification(),
event->getXOffset(), event->getYOffset(),
event->getXPrecision(), event->getYPrecision(),
+ event->getRawXCursorPosition(), event->getRawYCursorPosition(),
event->getDownTime(), event->getHistoricalEventTime(i),
event->getPointerCount(), event->getPointerProperties(),
event->getHistoricalRawPointerCoords(0, i));
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 50cff5c46da3..8ddbe724217c 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -375,6 +375,7 @@ static jlong android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz
event->initialize(deviceId, source, displayId, action, 0, flags, edgeFlags, metaState,
buttonState, static_cast<MotionClassification>(classification),
xOffset, yOffset, xPrecision, yPrecision,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
downTimeNanos, eventTimeNanos, pointerCount, pointerProperties, rawPointerCoords);
return reinterpret_cast<jlong>(event);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index dea80920e11a..119d5ea33dc3 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -724,6 +724,10 @@
<!-- Allows an application to send SMS messages.
<p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.SEND_SMS"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -734,6 +738,10 @@
<!-- Allows an application to receive SMS messages.
<p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.RECEIVE_SMS"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -744,6 +752,10 @@
<!-- Allows an application to read SMS messages.
<p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.READ_SMS"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -754,6 +766,10 @@
<!-- Allows an application to receive WAP push messages.
<p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.RECEIVE_WAP_PUSH"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -763,7 +779,11 @@
android:protectionLevel="dangerous" />
<!-- Allows an application to monitor incoming MMS messages.
- <p>Protection level: dangerous
+ <p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.RECEIVE_MMS"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -783,6 +803,11 @@
when the alert is first received, and to delay presenting the info
to the user until after the initial alert dialog is dismissed.
<p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+
@hide Pending API council approval -->
<permission android:name="android.permission.READ_CELL_BROADCASTS"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -805,30 +830,35 @@
android:priority="900" />
<!-- Allows an application to read from external storage.
- <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
- granted this permission.</p>
- <p>This permission is enforced starting in API level 19. Before API level 19, this
- permission is not enforced and all apps still have access to read from external storage.
- You can test your app with the permission enforced by enabling <em>Protect USB
- storage</em> under Developer options in the Settings app on a device running Android 4.1 or
- higher.</p>
- <p>Also starting in API level 19, this permission is <em>not</em> required to
- read/write files in your application-specific directories returned by
- {@link android.content.Context#getExternalFilesDir} and
- {@link android.content.Context#getExternalCacheDir}.
- <p class="note"><strong>Note:</strong> If <em>both</em> your <a
- href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
- minSdkVersion}</a> and <a
- href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
- targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
- grants your app this permission. If you don't need this permission, be sure your <a
- href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
- targetSdkVersion}</a> is 4 or higher.
- <p>Is this permission is not whitelisted for an app that targets an API level before
- {@link android.os.Build.VERSION_CODES#Q} this permission cannot be granted to apps.</p>
- <p>Is this permission is not whitelisted for an app that targets an API level
- {@link android.os.Build.VERSION_CODES#Q} or later the app will be forced into isolated storage.
- </p>
+ <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
+ granted this permission.</p>
+ <p>This permission is enforced starting in API level 19. Before API level 19, this
+ permission is not enforced and all apps still have access to read from external storage.
+ You can test your app with the permission enforced by enabling <em>Protect USB
+ storage</em> under Developer options in the Settings app on a device running Android 4.1 or
+ higher.</p>
+ <p>Also starting in API level 19, this permission is <em>not</em> required to
+ read/write files in your application-specific directories returned by
+ {@link android.content.Context#getExternalFilesDir} and
+ {@link android.content.Context#getExternalCacheDir}.
+ <p class="note"><strong>Note:</strong> If <em>both</em> your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+ minSdkVersion}</a> and <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
+ grants your app this permission. If you don't need this permission, be sure your <a
+ href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+ targetSdkVersion}</a> is 4 or higher.
+
+ <p> This is a soft restricted permission which cannot be held by an app it its
+ full form until the installer on record did not whitelist the permission.
+ Specifically, if the permission is whitelisted the holder app can access
+ external storage and the visual and aural media collections while if the
+ permission is not whitelisted the holder app can only access to the visual
+ and aural medial collections. Also the permission is immutably restricted
+ meaning that the whitelist state can be specified only at install time and
+ cannot change until the app is installed. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -916,6 +946,10 @@
{@link #ACCESS_FINE_LOCATION}. Requesting this permission by itself doesn't give you
location access.
<p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -958,6 +992,10 @@
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
targetSdkVersion}</a> is 16 or higher.</p>
<p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.READ_CALL_LOG"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -978,6 +1016,10 @@
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
targetSdkVersion}</a> is 16 or higher.</p>
<p>Protection level: dangerous
+
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.WRITE_CALL_LOG"
android:permissionGroup="android.permission-group.UNDEFINED"
@@ -991,6 +1033,10 @@
abort the call altogether.
<p>Protection level: dangerous
+ <p> This is a hard restricted permission which cannot be held by an app until
+ the installer on record did not whitelist the permission. For more details see
+ {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
+
@deprecated Applications should use {@link android.telecom.CallRedirectionService} instead
of the {@link android.content.Intent#ACTION_NEW_OUTGOING_CALL} broadcast.
-->
@@ -4610,8 +4656,9 @@
android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.PlatLogoActivity"
- android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+ android:theme="@style/Theme.DeviceDefault.DayNight"
android:configChanges="orientation|keyboardHidden"
+ android:icon="@drawable/platlogo"
android:process=":ui">
</activity>
<activity android:name="com.android.internal.app.DisableCarModeActivity"
diff --git a/core/res/res/drawable-nodpi/android_logotype.xml b/core/res/res/drawable-nodpi/android_logotype.xml
new file mode 100644
index 000000000000..bd298e48ef34
--- /dev/null
+++ b/core/res/res/drawable-nodpi/android_logotype.xml
@@ -0,0 +1,42 @@
+<!--
+Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="290dp"
+ android:height="64dp"
+ android:viewportWidth="290.0"
+ android:viewportHeight="64.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M21.81,28.91c-7.44,0,-12.45,5.85,-12.45,13.37c0,7.52,5.01,13.37,12.45,13.37s12.45,-5.85,12.45,-13.37 C34.26,34.76,29.24,28.91,21.81,28.91 M20.13,20.55c6.02,0,11.03,3.09,13.37,6.43v-5.6l9.19,0l0,41.78l-6.24,0 c-1.63,0,-2.95,-1.32,-2.95,-2.95v-2.65C31.17,60.91,26.15,64,20.14,64C8.69,64,0,54.23,0,42.28C0,30.33,8.69,20.55,20.13,20.55"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M53.13,21.39l9.19,0l0,5.68c2.5,-4.18,7.27,-6.52,12.7,-6.52c9.69,0,15.96,6.85,15.96,17.46l0,25.15l-6.24,0 c-1.63,0,-2.95,-1.32,-2.95,-2.95l0,-20.7c0,-6.6,-3.34,-10.61,-8.69,-10.61c-6.1,0,-10.78,4.76,-10.78,13.7l0,20.55l-6.25,0 c-1.63,0,-2.95,-1.32,-2.95,-2.95L53.13,21.39z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M120.06,28.91c-7.43,0,-12.45,5.85,-12.45,13.37c0,7.52,5.01,13.37,12.45,13.37c7.43,0,12.45,-5.85,12.45,-13.37 C132.51,34.76,127.5,28.91,120.06,28.91 M118.39,20.55c6.02,0,11.03,3.09,13.37,6.43l0,-26.49l9.19,0l0,62.66h-6.24 c-1.63,0,-2.95,-1.32,-2.95,-2.95v-2.65c-2.34,3.34,-7.35,6.43,-13.37,6.43c-11.45,0,-20.14,-9.77,-20.14,-21.72 C98.25,30.33,106.94,20.55,118.39,20.55"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M151.39,21.39l9.19,0v7.44c1.59,-4.76,6.27,-7.86,11.03,-7.86c1.17,0,2.34,0.08,3.59,0.34v9.44c-1.59,-0.5,-2.92,-0.75,-4.59,-0.75 c-5.26,0,-10.03,4.43,-10.03,12.78l0,20.39l-6.24,0c-1.63,0,-2.95,-1.32,-2.95,-2.95L151.39,21.39z"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M199.98,55.48c7.35,0,12.53,-5.77,12.53,-13.2c0,-7.44,-5.18,-13.2,-12.53,-13.2c-7.44,0,-12.62,5.77,-12.62,13.2 C187.37,49.71,192.55,55.48,199.98,55.48 M199.98,64c-12.37,0,-21.89,-9.61,-21.89,-21.72c0,-12.12,9.52,-21.73,21.89,-21.73 c12.37,0,21.89,9.61,21.89,21.73C221.87,54.39,212.35,64,199.98,64"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M229.32,21.39l9.19,0l0,41.78l-6.24,0c-1.63,0,-2.95,-1.32,-2.95,-2.95L229.32,21.39z M233.92,12.28 c-3.34,0,-6.18,-2.76,-6.18,-6.18c0,-3.34,2.84,-6.1,6.18,-6.1c3.43,0,6.1,2.76,6.1,6.1C240.02,9.53,237.34,12.28,233.92,12.28"/>
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M267.87,28.91c-7.43,0,-12.45,5.85,-12.45,13.37c0,7.52,5.01,13.37,12.45,13.37c7.44,0,12.45,-5.85,12.45,-13.37 C280.32,34.76,275.31,28.91,267.87,28.91 M266.2,20.55c6.02,0,11.03,3.09,13.37,6.43l0,-26.49l9.19,0l0,62.66l-6.24,0 c-1.63,0,-2.95,-1.32,-2.95,-2.95v-2.65c-2.34,3.34,-7.35,6.43,-13.37,6.43c-11.44,0,-20.14,-9.77,-20.14,-21.72S254.76,20.55,266.2,20.55"/>
+</vector>
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index f5bbadcce06b..19a296a0e46b 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -1,5 +1,5 @@
<!--
-Copyright (C) 2018 The Android Open Source Project
+Copyright (C) 2015 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.
@@ -13,21 +13,15 @@ Copyright (C) 2018 The Android Open Source Project
See the License for the specific language governing permissions and
limitations under the License.
-->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:name="vector"
- android:width="640dp"
- android:height="640dp"
- android:viewportWidth="64"
- android:viewportHeight="64">
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
<path
- android:name="bg"
- android:pathData="M 27 43 L 32 43 C 38.075 43 43 38.075 43 32 C 43 25.925 38.075 21 32 21 C 25.925 21 21 25.925 21 32 L 21 64"
- android:strokeColor="#6823a1"
- android:strokeWidth="16"/>
+ android:fillColor="#FF000000"
+ android:pathData="M19.45,22.89l-10.250001,-10.249999l-2.6599998,2.6599998l-1.77,-1.7600002l4.43,-4.4300003l12.0199995,12.0199995l-1.7699986,1.7600002z"/>
<path
- android:name="fg"
- android:pathData="M 29 43 L 32 43 C 38.075 43 43 38.075 43 32 C 43 25.925 38.075 21 32 21 C 25.925 21 21 25.925 21 32 L 21 64"
- android:strokeColor="#ff0000"
- android:strokeWidth="8"/>
+ android:fillColor="#FF000000"
+ android:pathData="M12,6a6,6 0,1 1,-6 6,6 6,0 0,1 6,-6m0,-2.5A8.5,8.5 0,1 0,20.5 12,8.51 8.51,0 0,0 12,3.5Z"/>
</vector>
diff --git a/core/res/res/layout/platlogo_layout.xml b/core/res/res/layout/platlogo_layout.xml
new file mode 100644
index 000000000000..4a4ad751e421
--- /dev/null
+++ b/core/res/res/layout/platlogo_layout.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipChildren="false"
+ android:background="@android:color/transparent">
+ <ImageView
+ android:id="@+id/text"
+ android:layout_width="400dp"
+ android:layout_height="wrap_content"
+ android:translationY="-100dp"
+ android:adjustViewBounds="true"
+ android:layout_marginBottom="-80dp"
+ android:layout_centerInParent="true"
+ android:src="@drawable/android_logotype"
+ android:tint="?android:attr/textColorPrimary"
+ />
+ <ImageView
+ android:id="@+id/one"
+ android:layout_width="200dp"
+ android:layout_height="200dp"
+ android:layout_marginLeft="24dp"
+ android:layout_below="@id/text"
+ android:layout_alignLeft="@id/text"
+ android:tint="?android:attr/textColorPrimary"
+ />
+ <ImageView
+ android:id="@+id/zero"
+ android:layout_width="200dp"
+ android:layout_height="200dp"
+ android:layout_marginRight="34dp"
+ android:layout_below="@id/text"
+ android:layout_alignRight="@id/text"
+ android:tint="?android:attr/textColorPrimary"
+ />
+</RelativeLayout>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f515b2dd45f0..bc7e3b7e9058 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4210,6 +4210,14 @@
one bar higher than they actually are -->
<bool name="config_inflateSignalStrength">false</bool>
+ <!-- Trigger a warning for notifications with RemoteView objects that are larger in bytes than
+ this value (default 1MB)-->
+ <integer name="config_notificationWarnRemoteViewSizeBytes">1000000</integer>
+
+ <!-- Strip notification RemoteView objects that are larger in bytes than this value (also log)
+ (default 2MB) -->
+ <integer name="config_notificationStripRemoteViewSizeBytes">2000000</integer>
+
<!-- Sharesheet: define a max number of targets per application for new shortcuts-based direct share introduced in Q -->
<integer name="config_maxShortcutTargetsPerApp">3</integer>
@@ -4217,4 +4225,8 @@
the default implementation of ACTION_FACTORY_RESET does not work, so it is needed to re-route
this intent to this package. This is being used in MasterClearReceiver.java. -->
<string name="config_factoryResetPackage" translatable="false"></string>
+
+ <!-- The list of packages to automatically opt out of refresh rates higher than 60hz because
+ of known compatibility issues. -->
+ <string-array name="config_highRefreshRateBlacklist"></string-array>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6c908aac1ee8..498e60e0405b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3823,5 +3823,14 @@
<java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" />
<java-symbol type="bool" name="config_inflateSignalStrength" />
+
+ <java-symbol type="drawable" name="android_logotype" />
+ <java-symbol type="layout" name="platlogo_layout" />
+
+ <java-symbol type="integer" name="config_notificationWarnRemoteViewSizeBytes" />
+ <java-symbol type="integer" name="config_notificationStripRemoteViewSizeBytes" />
+
<java-symbol type="string" name="config_factoryResetPackage" />
+ <java-symbol type="array" name="config_highRefreshRateBlacklist" />
+
</resources>
diff --git a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
index 1ca879cde6c8..49849ee72a18 100644
--- a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
+++ b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
@@ -36,12 +36,12 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.frameworks.coretests.R;
-import libcore.testing.io.TestIoUtils;
-
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import java.io.File;
@@ -60,21 +60,14 @@ public class DexMetadataHelperTest {
private static final String APK_FILE_EXTENSION = ".apk";
private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
+ @Rule
+ public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
private File mTmpDir = null;
@Before
- public void setUp() {
- mTmpDir = TestIoUtils.createTemporaryDirectory("DexMetadataHelperTest");
- }
-
- @After
- public void tearDown() {
- if (mTmpDir != null) {
- File[] files = mTmpDir.listFiles();
- for (File f : files) {
- f.delete();
- }
- }
+ public void setUp() throws IOException {
+ mTmpDir = mTemporaryFolder.newFolder("DexMetadataHelperTest");
}
private File createDexMetadataFile(String apkFileName) throws IOException {
diff --git a/core/tests/coretests/src/android/view/textclassifier/logging/SmartSelectionEventTrackerTest.java b/core/tests/coretests/src/android/view/textclassifier/logging/SmartSelectionEventTrackerTest.java
new file mode 100644
index 000000000000..321a7f21c307
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/logging/SmartSelectionEventTrackerTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.view.textclassifier.logging;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.google.common.truth.Truth;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SmartSelectionEventTrackerTest {
+
+ @Test
+ public void getVersionInfo_valid() {
+ String signature = "a|702|b";
+ String versionInfo = SmartSelectionEventTracker.SelectionEvent.getVersionInfo(signature);
+ Truth.assertThat(versionInfo).isEqualTo("702");
+ }
+
+ @Test
+ public void getVersionInfo_invalid() {
+ String signature = "|702";
+ String versionInfo = SmartSelectionEventTracker.SelectionEvent.getVersionInfo(signature);
+ Truth.assertThat(versionInfo).isEmpty();
+ }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 54c548a7b174..89e26daed82a 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -269,6 +269,8 @@ applications that come with the platform
<permission name="android.permission.INSTALL_PACKAGES"/>
<!-- Needed for test only -->
<permission name="android.permission.INTERACT_ACROSS_PROFILES"/>
+ <!-- Permission required to test onPermissionsChangedListener -->
+ <permission name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"/>
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.LOCAL_MAC_ADDRESS"/>
<permission name="android.permission.MANAGE_ACCESSIBILITY"/>
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index bf948b135728..0d837f2c7fed 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -195,6 +195,7 @@ cc_defaults {
"RecordingCanvas.cpp",
"RenderNode.cpp",
"RenderProperties.cpp",
+ "RootRenderNode.cpp",
"SkiaCanvas.cpp",
"VectorDrawable.cpp",
],
@@ -250,7 +251,6 @@ cc_defaults {
"ProfileData.cpp",
"ProfileDataContainer.cpp",
"Readback.cpp",
- "RootRenderNode.cpp",
"TreeInfo.cpp",
"WebViewFunctorManager.cpp",
"protos/graphicsstats.proto",
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 93b9decd9cbc..74cf1fda1b75 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -155,11 +155,9 @@ void BaseRenderNodeAnimator::pushStaging(AnimationContext& context) {
RenderNode* oldTarget = mTarget;
mTarget = mStagingTarget;
mStagingTarget = nullptr;
-#ifdef __ANDROID__ // Layoutlib does not support RenderNode
if (oldTarget && oldTarget != mTarget) {
oldTarget->onAnimatorTargetChanged(this);
}
-#endif
}
if (!mHasStartValue) {
diff --git a/libs/hwui/RootRenderNode.cpp b/libs/hwui/RootRenderNode.cpp
index 24801928121b..ddbbf58b3071 100644
--- a/libs/hwui/RootRenderNode.cpp
+++ b/libs/hwui/RootRenderNode.cpp
@@ -16,10 +16,13 @@
#include "RootRenderNode.h"
+#ifdef __ANDROID__ // Layoutlib does not support Looper (windows)
#include <utils/Looper.h>
+#endif
namespace android::uirenderer {
+#ifdef __ANDROID__ // Layoutlib does not support Looper
class FinishAndInvokeListener : public MessageHandler {
public:
explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim) : mAnimator(anim) {
@@ -282,5 +285,22 @@ private:
AnimationContext* ContextFactoryImpl::createAnimationContext(renderthread::TimeLord& clock) {
return new AnimationContextBridge(clock, mRootNode);
}
+#else
+
+void RootRenderNode::prepareTree(TreeInfo& info) {
+ info.errorHandler = mErrorHandler.get();
+ info.updateWindowPositions = true;
+ RenderNode::prepareTree(info);
+ info.updateWindowPositions = false;
+ info.errorHandler = nullptr;
+}
+
+void RootRenderNode::attachAnimatingNode(RenderNode* animatingNode) { }
+
+void RootRenderNode::destroy() { }
+
+void RootRenderNode::addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { }
+
+#endif
} // namespace android::uirenderer
diff --git a/libs/hwui/RootRenderNode.h b/libs/hwui/RootRenderNode.h
index 5c830e08ef68..12de4ecac94b 100644
--- a/libs/hwui/RootRenderNode.h
+++ b/libs/hwui/RootRenderNode.h
@@ -74,6 +74,7 @@ private:
void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim);
};
+#ifdef __ANDROID__ // Layoutlib does not support Animations
class ANDROID_API ContextFactoryImpl : public IContextFactory {
public:
ANDROID_API explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
@@ -84,5 +85,6 @@ public:
private:
RootRenderNode* mRootNode;
};
+#endif
} // namespace android::uirenderer
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 813e4744fc77..0346010f4587 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -800,7 +800,7 @@ public class MediaMetadataRetriever implements AutoCloseable {
*/
public static final int METADATA_KEY_YEAR = 8;
/**
- * The metadata key to retrieve the playback duration of the data source.
+ * The metadata key to retrieve the playback duration (in ms) of the data source.
*/
public static final int METADATA_KEY_DURATION = 9;
/**
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 534d63b4cca0..fb581b532dd2 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -356,19 +356,21 @@ public class ThumbnailUtils {
return ImageDecoder.decodeBitmap(ImageDecoder.createSource(raw), resizer);
}
- // Fall back to middle of video
final int width = Integer.parseInt(mmr.extractMetadata(METADATA_KEY_VIDEO_WIDTH));
final int height = Integer.parseInt(mmr.extractMetadata(METADATA_KEY_VIDEO_HEIGHT));
- final long duration = Long.parseLong(mmr.extractMetadata(METADATA_KEY_DURATION));
+ // Fall back to middle of video
+ // Note: METADATA_KEY_DURATION unit is in ms, not us.
+ final long thumbnailTimeUs =
+ Long.parseLong(mmr.extractMetadata(METADATA_KEY_DURATION)) * 1000 / 2;
// If we're okay with something larger than native format, just
// return a frame without up-scaling it
if (size.getWidth() > width && size.getHeight() > height) {
return Objects.requireNonNull(
- mmr.getFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC));
+ mmr.getFrameAtTime(thumbnailTimeUs, OPTION_CLOSEST_SYNC));
} else {
return Objects.requireNonNull(
- mmr.getScaledFrameAtTime(duration / 2, OPTION_CLOSEST_SYNC,
+ mmr.getScaledFrameAtTime(thumbnailTimeUs, OPTION_CLOSEST_SYNC,
size.getWidth(), size.getHeight()));
}
} catch (RuntimeException e) {
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp
index 589623b0d6cd..61cab73c226a 100644
--- a/packages/CarSystemUI/Android.bp
+++ b/packages/CarSystemUI/Android.bp
@@ -26,8 +26,8 @@ android_app {
],
static_libs: [
- "CarNotificationLib",
"SystemUI-core",
+ "CarNotificationLib",
"SystemUIPluginLib",
"SystemUISharedLib",
"SettingsLib",
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 358e2cd4ee33..812adf94b8bc 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -61,9 +61,9 @@ import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.classifier.FalsingLog;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.car.CarQSFragment;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -877,7 +877,7 @@ public class CarStatusBar extends StatusBar implements
KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
}
- FalsingManagerFactory.getInstance(mContext).dump(pw);
+ Dependency.get(FalsingManager.class).dump(pw);
FalsingLog.dump(pw);
pw.println("SharedPreferences:");
diff --git a/packages/EasterEgg/AndroidManifest.xml b/packages/EasterEgg/AndroidManifest.xml
index c7dd40d7afdb..7f76a4529963 100644
--- a/packages/EasterEgg/AndroidManifest.xml
+++ b/packages/EasterEgg/AndroidManifest.xml
@@ -1,40 +1,38 @@
<?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.egg"
android:versionCode="1"
android:versionName="1.0">
- <uses-sdk android:minSdkVersion="28" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
- android:icon="@drawable/icon"
+ android:icon="@drawable/q_icon"
android:label="@string/app_name">
+ <activity android:name=".quares.QuaresActivity"
+ android:icon="@drawable/q_icon"
+ android:label="@string/q_egg_name"
+ android:theme="@style/QuaresTheme">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <!-- <category android:name="android.intent.category.LAUNCHER" /> -->
+ <category android:name="com.android.internal.category.PLATLOGO" />
+ </intent-filter>
+ </activity>
<activity
android:name=".paint.PaintActivity"
android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
- android:label="@string/app_name"
+ android:icon="@drawable/p_icon"
+ android:label="@string/p_egg_name"
android:theme="@style/AppTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <!--<category android:name="android.intent.category.LAUNCHER" />-->
- <category android:name="com.android.internal.category.PLATLOGO" />
+
+ <!-- <category android:name="android.intent.category.DEFAULT" /> -->
+ <!-- <category android:name="android.intent.category.LAUNCHER" /> -->
+ <!-- <category android:name="com.android.internal.category.PLATLOGO" /> -->
</intent-filter>
</activity>
</application>
diff --git a/packages/EasterEgg/res/drawable/icon_bg.xml b/packages/EasterEgg/res/drawable/icon_bg.xml
index c1553ce50946..659f98be4f43 100644
--- a/packages/EasterEgg/res/drawable/icon_bg.xml
+++ b/packages/EasterEgg/res/drawable/icon_bg.xml
@@ -15,4 +15,4 @@
limitations under the License.
-->
<color xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="#C5E1A5" /> \ No newline at end of file
+ android:color="@color/q_clue_text" />
diff --git a/packages/EasterEgg/res/drawable/icon.xml b/packages/EasterEgg/res/drawable/p_icon.xml
index 2306b7b554c5..2306b7b554c5 100644
--- a/packages/EasterEgg/res/drawable/icon.xml
+++ b/packages/EasterEgg/res/drawable/p_icon.xml
diff --git a/packages/EasterEgg/res/drawable/pixel_bg.xml b/packages/EasterEgg/res/drawable/pixel_bg.xml
new file mode 100644
index 000000000000..4d4a113cce53
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/pixel_bg.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:exitFadeDuration="100">
+ <item android:state_pressed="true">
+ <shape><solid android:color="@color/red"/></shape>
+ </item>
+ <item android:state_checked="true">
+ <shape><solid android:color="@color/pixel_on"/></shape>
+ </item>
+ <item>
+ <shape><solid android:color="@color/pixel_off"/></shape>
+ </item>
+</selector> \ No newline at end of file
diff --git a/packages/EasterEgg/res/drawable/q.xml b/packages/EasterEgg/res/drawable/q.xml
new file mode 100644
index 000000000000..75baa47e3aa6
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/q.xml
@@ -0,0 +1,27 @@
+<!--
+Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/q_icon_fg"
+ android:pathData="M19.45,22.89l-10.250001,-10.249999l-2.6599998,2.6599998l-1.77,-1.7600002l4.43,-4.4300003l12.0199995,12.0199995l-1.7699986,1.7600002z"/>
+ <path
+ android:fillColor="@color/q_icon_fg"
+ android:pathData="M12,6a6,6 0,1 1,-6 6,6 6,0 0,1 6,-6m0,-2.5A8.5,8.5 0,1 0,20.5 12,8.51 8.51,0 0,0 12,3.5Z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/q_icon.xml b/packages/EasterEgg/res/drawable/q_icon.xml
new file mode 100644
index 000000000000..ef4b0a362043
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/q_icon.xml
@@ -0,0 +1,19 @@
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/icon_bg"/>
+ <foreground android:drawable="@drawable/q_smaller"/>
+</adaptive-icon>
diff --git a/packages/EasterEgg/res/drawable/q_smaller.xml b/packages/EasterEgg/res/drawable/q_smaller.xml
new file mode 100644
index 000000000000..c71dff094235
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/q_smaller.xml
@@ -0,0 +1,23 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:insetBottom="5dp"
+ android:insetLeft="5dp"
+ android:insetRight="5dp"
+ android:insetTop="5dp"
+ android:drawable="@drawable/q" />
diff --git a/packages/EasterEgg/res/layout/activity_quares.xml b/packages/EasterEgg/res/layout/activity_quares.xml
new file mode 100644
index 000000000000..dcc90f6f77ae
--- /dev/null
+++ b/packages/EasterEgg/res/layout/activity_quares.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:animateLayoutChanges="true"
+ tools:context="com.android.egg.quares.QuaresActivity">
+
+ <GridLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:alignmentMode="alignBounds"
+ android:id="@+id/grid"
+ />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/label"
+ android:layout_gravity="center_horizontal|bottom"
+ android:gravity="center"
+ android:textSize="18dp"
+ android:visibility="gone"
+ android:drawablePadding="8dp"
+ android:padding="12dp"
+ android:backgroundTint="@color/q_clue_bg_correct"
+ android:textColor="@color/q_clue_text"
+ android:layout_marginBottom="48dp"
+ android:elevation="30dp"
+ />
+</FrameLayout>
diff --git a/packages/EasterEgg/res/values-night/q_colors.xml b/packages/EasterEgg/res/values-night/q_colors.xml
new file mode 100644
index 000000000000..191bd944b7dc
--- /dev/null
+++ b/packages/EasterEgg/res/values-night/q_colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <color name="pixel_off">#000000</color>
+ <color name="pixel_on">#FFFFFF</color>
+
+ <color name="q_clue_bg">@color/navy</color>
+ <color name="q_clue_text">@color/tan</color>
+</resources> \ No newline at end of file
diff --git a/packages/EasterEgg/res/values/q_colors.xml b/packages/EasterEgg/res/values/q_colors.xml
new file mode 100644
index 000000000000..5e92c84fd97d
--- /dev/null
+++ b/packages/EasterEgg/res/values/q_colors.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <color name="emerald">#3ddc84</color>
+ <color name="red">#f8c734</color>
+ <color name="navy">#073042</color>
+ <color name="vapor">#d7effe</color>
+ <color name="tan">#eff7cf</color>
+
+ <color name="pixel_off">#FFFFFF</color>
+ <color name="pixel_on">#000000</color>
+
+ <color name="q_clue_bg">@color/tan</color>
+ <color name="q_clue_text">@color/navy</color>
+ <color name="q_clue_bg_correct">@color/emerald</color>
+
+ <color name="q_icon_fg">@color/emerald</color>
+</resources>
diff --git a/packages/EasterEgg/res/values/q_puzzles.xml b/packages/EasterEgg/res/values/q_puzzles.xml
new file mode 100644
index 000000000000..7c2eff152ffe
--- /dev/null
+++ b/packages/EasterEgg/res/values/q_puzzles.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string-array name="puzzles">
+
+ <item>q</item>
+ <item>q</item>
+ <item>q</item>
+ <item>q</item>
+ <item>q</item>
+
+ <item>android:drawable/ic_info</item>
+
+ <item>android:drawable/stat_sys_adb</item>
+ <item>android:drawable/stat_sys_battery</item>
+ <item>android:drawable/stat_sys_phone_call</item>
+ <item>android:drawable/stat_sys_certificate_info</item>
+ <item>android:drawable/stat_sys_data_bluetooth</item>
+ <item>android:drawable/stat_sys_data_usb</item>
+ <item>android:drawable/stat_sys_download</item>
+ <item>android:drawable/stat_sys_gps_on</item>
+ <item>android:drawable/stat_sys_phone_call</item>
+ <item>android:drawable/stat_sys_tether_wifi</item>
+ <item>android:drawable/stat_sys_throttled</item>
+ <item>android:drawable/stat_sys_upload</item>
+
+ <item>android:drawable/stat_notify_car_mode</item>
+ <item>android:drawable/stat_notify_chat</item>
+ <item>android:drawable/stat_notify_disk_full</item>
+ <item>android:drawable/stat_notify_email_generic</item>
+ <item>android:drawable/stat_notify_error</item>
+ <item>android:drawable/stat_notify_gmail</item>
+ <item>android:drawable/stat_notify_missed_call</item>
+ <item>android:drawable/stat_notify_mmcc_indication_icn</item>
+ <item>android:drawable/stat_notify_more</item>
+ <item>android:drawable/stat_notify_rssi_in_range</item>
+ <item>android:drawable/stat_notify_sdcard</item>
+ <item>android:drawable/stat_notify_sdcard_prepare</item>
+ <item>android:drawable/stat_notify_sdcard_usb</item>
+ <item>android:drawable/stat_notify_sim_toolkit</item>
+ <item>android:drawable/stat_notify_sync</item>
+ <item>android:drawable/stat_notify_sync_anim0</item>
+ <item>android:drawable/stat_notify_sync_error</item>
+ <item>android:drawable/stat_notify_voicemail</item>
+
+ <item>android:drawable/ic_audio_alarm</item>
+ <item>android:drawable/ic_audio_alarm_mute</item>
+ <item>android:drawable/ic_bluetooth_share_icon</item>
+ <item>android:drawable/ic_bt_headphones_a2dp</item>
+ <item>android:drawable/ic_bt_headset_hfp</item>
+ <item>android:drawable/ic_bt_hearing_aid</item>
+ <item>android:drawable/ic_bt_laptop</item>
+ <item>android:drawable/ic_bt_misc_hid</item>
+ <item>android:drawable/ic_bt_network_pan</item>
+ <item>android:drawable/ic_bt_pointing_hid</item>
+ <item>android:drawable/ic_corp_badge</item>
+ <item>android:drawable/ic_expand_more</item>
+ <item>android:drawable/ic_faster_emergency</item>
+ <item>android:drawable/ic_file_copy</item>
+ <item>android:drawable/ic_info_outline_24</item>
+ <item>android:drawable/ic_lock</item>
+ <item>android:drawable/ic_lock_bugreport</item>
+ <item>android:drawable/ic_lock_open</item>
+ <item>android:drawable/ic_lock_power_off</item>
+ <item>android:drawable/ic_lockscreen_ime</item>
+ <item>android:drawable/ic_mode_edit</item>
+ <item>android:drawable/ic_phone</item>
+ <item>android:drawable/ic_qs_airplane</item>
+ <item>android:drawable/ic_qs_auto_rotate</item>
+ <item>android:drawable/ic_qs_battery_saver</item>
+ <item>android:drawable/ic_qs_bluetooth</item>
+ <item>android:drawable/ic_qs_dnd</item>
+ <item>android:drawable/ic_qs_flashlight</item>
+ <item>android:drawable/ic_qs_night_display_on</item>
+ <item>android:drawable/ic_restart</item>
+ <item>android:drawable/ic_screenshot</item>
+ <item>android:drawable/ic_settings_bluetooth</item>
+ <item>android:drawable/ic_signal_cellular_0_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_0_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_1_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_1_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_2_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_2_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_3_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_3_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_4_4_bar</item>
+ <item>android:drawable/ic_signal_cellular_4_5_bar</item>
+ <item>android:drawable/ic_signal_cellular_5_5_bar</item>
+ <item>android:drawable/ic_signal_location</item>
+ <item>android:drawable/ic_wifi_signal_0</item>
+ <item>android:drawable/ic_wifi_signal_1</item>
+ <item>android:drawable/ic_wifi_signal_2</item>
+ <item>android:drawable/ic_wifi_signal_3</item>
+ <item>android:drawable/ic_wifi_signal_4</item>
+ <item>android:drawable/perm_group_activity_recognition</item>
+ <item>android:drawable/perm_group_calendar</item>
+ <item>android:drawable/perm_group_call_log</item>
+ <item>android:drawable/perm_group_camera</item>
+ <item>android:drawable/perm_group_contacts</item>
+ <item>android:drawable/perm_group_location</item>
+ <item>android:drawable/perm_group_microphone</item>
+ <item>android:drawable/perm_group_phone_calls</item>
+ <item>android:drawable/perm_group_sensors</item>
+ <item>android:drawable/perm_group_sms</item>
+ <item>android:drawable/perm_group_storage</item>
+ <item>android:drawable/perm_group_visual</item>
+
+ <item>com.android.settings:drawable/ic_add_24dp</item>
+ <item>com.android.settings:drawable/ic_airplanemode_active</item>
+ <item>com.android.settings:drawable/ic_android</item>
+ <item>com.android.settings:drawable/ic_apps</item>
+ <item>com.android.settings:drawable/ic_arrow_back</item>
+ <item>com.android.settings:drawable/ic_arrow_down_24dp</item>
+ <item>com.android.settings:drawable/ic_battery_charging_full</item>
+ <item>com.android.settings:drawable/ic_battery_status_bad_24dp</item>
+ <item>com.android.settings:drawable/ic_battery_status_good_24dp</item>
+ <item>com.android.settings:drawable/ic_battery_status_maybe_24dp</item>
+ <item>com.android.settings:drawable/ic_call_24dp</item>
+ <item>com.android.settings:drawable/ic_cancel</item>
+ <item>com.android.settings:drawable/ic_cast_24dp</item>
+ <item>com.android.settings:drawable/ic_chevron_right_24dp</item>
+ <item>com.android.settings:drawable/ic_data_saver</item>
+ <item>com.android.settings:drawable/ic_delete</item>
+ <item>com.android.settings:drawable/ic_devices_other</item>
+ <item>com.android.settings:drawable/ic_devices_other_opaque_black</item>
+ <item>com.android.settings:drawable/ic_do_not_disturb_on_24dp</item>
+ <item>com.android.settings:drawable/ic_eject_24dp</item>
+ <item>com.android.settings:drawable/ic_expand_less</item>
+ <item>com.android.settings:drawable/ic_expand_more_inverse</item>
+ <item>com.android.settings:drawable/ic_folder_vd_theme_24</item>
+ <item>com.android.settings:drawable/ic_friction_lock_closed</item>
+ <item>com.android.settings:drawable/ic_gray_scale_24dp</item>
+ <item>com.android.settings:drawable/ic_headset_24dp</item>
+ <item>com.android.settings:drawable/ic_help</item>
+ <item>com.android.settings:drawable/ic_local_movies</item>
+ <item>com.android.settings:drawable/ic_lock</item>
+ <item>com.android.settings:drawable/ic_media_stream</item>
+ <item>com.android.settings:drawable/ic_network_cell</item>
+ <item>com.android.settings:drawable/ic_notifications</item>
+ <item>com.android.settings:drawable/ic_notifications_off_24dp</item>
+ <item>com.android.settings:drawable/ic_phone_info</item>
+ <item>com.android.settings:drawable/ic_photo_library</item>
+ <item>com.android.settings:drawable/ic_settings_accessibility</item>
+ <item>com.android.settings:drawable/ic_settings_accounts</item>
+ <item>com.android.settings:drawable/ic_settings_backup</item>
+ <item>com.android.settings:drawable/ic_settings_battery_white</item>
+ <item>com.android.settings:drawable/ic_settings_data_usage</item>
+ <item>com.android.settings:drawable/ic_settings_date_time</item>
+ <item>com.android.settings:drawable/ic_settings_delete</item>
+ <item>com.android.settings:drawable/ic_settings_display_white</item>
+ <item>com.android.settings:drawable/ic_settings_home</item>
+ <item>com.android.settings:drawable/ic_settings_location</item>
+ <item>com.android.settings:drawable/ic_settings_night_display</item>
+ <item>com.android.settings:drawable/ic_settings_open</item>
+ <item>com.android.settings:drawable/ic_settings_print</item>
+ <item>com.android.settings:drawable/ic_settings_privacy</item>
+ <item>com.android.settings:drawable/ic_settings_security_white</item>
+ <item>com.android.settings:drawable/ic_settings_sim</item>
+ <item>com.android.settings:drawable/ic_settings_wireless</item>
+ <item>com.android.settings:drawable/ic_storage</item>
+ <item>com.android.settings:drawable/ic_storage_white</item>
+ <item>com.android.settings:drawable/ic_suggestion_night_display</item>
+ <item>com.android.settings:drawable/ic_sync</item>
+ <item>com.android.settings:drawable/ic_system_update</item>
+ <item>com.android.settings:drawable/ic_videogame_vd_theme_24</item>
+ <item>com.android.settings:drawable/ic_volume_ringer_vibrate</item>
+ <item>com.android.settings:drawable/ic_volume_up_24dp</item>
+ <item>com.android.settings:drawable/ic_vpn_key</item>
+ <item>com.android.settings:drawable/ic_wifi_tethering</item>
+
+ <item>com.android.systemui:drawable/ic_alarm</item>
+ <item>com.android.systemui:drawable/ic_alarm_dim</item>
+ <item>com.android.systemui:drawable/ic_arrow_back</item>
+ <item>com.android.systemui:drawable/ic_bluetooth_connected</item>
+ <item>com.android.systemui:drawable/ic_brightness_thumb</item>
+ <item>com.android.systemui:drawable/ic_camera</item>
+ <item>com.android.systemui:drawable/ic_cast</item>
+ <item>com.android.systemui:drawable/ic_cast_connected</item>
+ <item>com.android.systemui:drawable/ic_cast_connected_fill</item>
+ <item>com.android.systemui:drawable/ic_close_white</item>
+ <item>com.android.systemui:drawable/ic_data_saver</item>
+ <item>com.android.systemui:drawable/ic_data_saver_off</item>
+ <item>com.android.systemui:drawable/ic_drag_handle</item>
+ <item>com.android.systemui:drawable/ic_headset</item>
+ <item>com.android.systemui:drawable/ic_headset_mic</item>
+ <item>com.android.systemui:drawable/ic_hotspot</item>
+ <item>com.android.systemui:drawable/ic_invert_colors</item>
+ <item>com.android.systemui:drawable/ic_location</item>
+ <item>com.android.systemui:drawable/ic_lockscreen_ime</item>
+ <item>com.android.systemui:drawable/ic_notifications_alert</item>
+ <item>com.android.systemui:drawable/ic_notifications_silence</item>
+ <item>com.android.systemui:drawable/ic_power_low</item>
+ <item>com.android.systemui:drawable/ic_power_saver</item>
+ <item>com.android.systemui:drawable/ic_qs_bluetooth_connecting</item>
+ <item>com.android.systemui:drawable/ic_qs_bluetooth_on</item>
+ <item>com.android.systemui:drawable/ic_qs_cancel</item>
+ <item>com.android.systemui:drawable/ic_qs_no_sim</item>
+ <item>com.android.systemui:drawable/ic_screenshot_delete</item>
+ <item>com.android.systemui:drawable/ic_settings</item>
+ <item>com.android.systemui:drawable/ic_swap_vert</item>
+ <item>com.android.systemui:drawable/ic_volume_alarm</item>
+ <item>com.android.systemui:drawable/ic_volume_alarm_mute</item>
+ <item>com.android.systemui:drawable/ic_volume_media</item>
+ <item>com.android.systemui:drawable/ic_volume_media_mute</item>
+ <item>com.android.systemui:drawable/ic_volume_ringer</item>
+ <item>com.android.systemui:drawable/ic_volume_ringer_mute</item>
+ <item>com.android.systemui:drawable/ic_volume_ringer_vibrate</item>
+ <item>com.android.systemui:drawable/ic_volume_voice</item>
+ <item>com.android.systemui:drawable/stat_sys_camera</item>
+ <item>com.android.systemui:drawable/stat_sys_managed_profile_status</item>
+ <item>com.android.systemui:drawable/stat_sys_mic_none</item>
+ <item>com.android.systemui:drawable/stat_sys_vpn_ic</item>
+
+ </string-array>
+</resources>
diff --git a/packages/EasterEgg/res/values/strings.xml b/packages/EasterEgg/res/values/strings.xml
index 32dbc97a00fb..b95ec6be4c84 100644
--- a/packages/EasterEgg/res/values/strings.xml
+++ b/packages/EasterEgg/res/values/strings.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?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");
@@ -15,5 +14,11 @@ Copyright (C) 2018 The Android Open Source Project
limitations under the License.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <string name="app_name" translatable="false">PAINT.APK</string>
+ <string name="app_name" translatable="false">Android Q Easter Egg</string>
+
+ <!-- name of the Q easter egg, a nonogram-style icon puzzle -->
+ <string name="q_egg_name" translatable="false">Icon Quiz</string>
+
+ <!-- name of the P easter egg, a humble paint program -->
+ <string name="p_egg_name" translatable="false">PAINT.APK</string>
</resources>
diff --git a/packages/EasterEgg/res/values/styles.xml b/packages/EasterEgg/res/values/styles.xml
index 44e2ce52aab8..e576526f49b7 100644
--- a/packages/EasterEgg/res/values/styles.xml
+++ b/packages/EasterEgg/res/values/styles.xml
@@ -20,4 +20,16 @@
<item name="android:windowLightNavigationBar">true</item>
</style>
+ <style name="QuaresTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:colorBackgroundCacheHint">@null</item>
+ <item name="android:windowShowWallpaper">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowFullscreen">true</item>
+ <item name="android:statusBarColor">@android:color/transparent</item>
+ <item name="android:navigationBarColor">@android:color/transparent</item>
+ </style>
+
</resources>
diff --git a/packages/EasterEgg/src/com/android/egg/quares/Quare.kt b/packages/EasterEgg/src/com/android/egg/quares/Quare.kt
new file mode 100644
index 000000000000..eb77362a0be2
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/quares/Quare.kt
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.egg.quares
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.Icon
+import android.os.Parcel
+import android.os.Parcelable
+import java.util.ArrayList
+import kotlin.math.abs
+import kotlin.math.round
+
+class Quare(val width: Int, val height: Int, val depth: Int) : Parcelable {
+ private val data: IntArray = IntArray(width * height)
+ private val user: IntArray = data.copyOf()
+
+ private fun loadAndQuantize(bitmap8bpp: Bitmap) {
+ bitmap8bpp.getPixels(data, 0, width, 0, 0, width, height)
+ if (depth == 8) return
+ val s = (255f / depth)
+ for (i in 0 until data.size) {
+ var f = (data[i] ushr 24).toFloat() / s
+ // f = f.pow(0.75f) // gamma adjust for bolder lines
+ f *= 1.25f // brightness adjust for bolder lines
+ f.coerceAtMost(1f)
+ data[i] = (round(f) * s).toInt() shl 24
+ }
+ }
+
+ fun isBlank(): Boolean {
+ return data.sum() == 0
+ }
+
+ fun load(drawable: Drawable) {
+ val resized = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8)
+ val canvas = Canvas(resized)
+ drawable.setBounds(0, 0, width, height)
+ drawable.setTint(0xFF000000.toInt())
+ drawable.draw(canvas)
+ loadAndQuantize(resized)
+ resized.recycle()
+ }
+
+ fun load(context: Context, icon: Icon) {
+ icon.loadDrawable(context)?.let {
+ load(it)
+ }
+ }
+
+ fun bitmap(): Bitmap {
+ return Bitmap.createBitmap(data, width, height, Bitmap.Config.ALPHA_8)
+ }
+
+ fun getUserMark(x: Int, y: Int): Int {
+ return user[y * width + x] ushr 24
+ }
+
+ fun setUserMark(x: Int, y: Int, v: Int) {
+ user[y * width + x] = v shl 24
+ }
+
+ fun getDataAt(x: Int, y: Int): Int {
+ return data[y * width + x] ushr 24
+ }
+
+ fun check(): Boolean {
+ return data.contentEquals(user)
+ }
+
+ fun check(xSel: Int, ySel: Int): Boolean {
+ val xStart = if (xSel < 0) 0 else xSel
+ val xEnd = if (xSel < 0) width - 1 else xSel
+ val yStart = if (ySel < 0) 0 else ySel
+ val yEnd = if (ySel < 0) height - 1 else ySel
+ for (y in yStart..yEnd)
+ for (x in xStart..xEnd)
+ if (getDataAt(x, y) != getUserMark(x, y)) return false
+ return true
+ }
+
+ fun errors(): IntArray {
+ return IntArray(width * height) {
+ abs(data[it] - user[it])
+ }
+ }
+
+ fun getRowClue(y: Int): IntArray {
+ return getClue(-1, y)
+ }
+ fun getColumnClue(x: Int): IntArray {
+ return getClue(x, -1)
+ }
+ fun getClue(xSel: Int, ySel: Int): IntArray {
+ val arr = ArrayList<Int>()
+ var len = 0
+ val xStart = if (xSel < 0) 0 else xSel
+ val xEnd = if (xSel < 0) width - 1 else xSel
+ val yStart = if (ySel < 0) 0 else ySel
+ val yEnd = if (ySel < 0) height - 1 else ySel
+ for (y in yStart..yEnd)
+ for (x in xStart..xEnd)
+ if (getDataAt(x, y) != 0) {
+ len++
+ } else if (len > 0) {
+ arr.add(len)
+ len = 0
+ }
+ if (len > 0) arr.add(len)
+ else if (arr.size == 0) arr.add(0)
+ return arr.toIntArray()
+ }
+
+ fun resetUserMarks() {
+ user.forEachIndexed { index, _ -> user[index] = 0 }
+ }
+
+ // Parcelable interface
+
+ override fun describeContents(): Int {
+ return 0
+ }
+
+ override fun writeToParcel(p: Parcel?, flags: Int) {
+ p?.let {
+ p.writeInt(width)
+ p.writeInt(height)
+ p.writeInt(depth)
+ p.writeIntArray(data)
+ p.writeIntArray(user)
+ }
+ }
+
+ companion object CREATOR : Parcelable.Creator<Quare> {
+ override fun createFromParcel(p: Parcel?): Quare {
+ return p!!.let {
+ Quare(
+ p.readInt(), // width
+ p.readInt(), // height
+ p.readInt() // depth
+ ).also {
+ p.readIntArray(it.data)
+ p.readIntArray(it.user)
+ }
+ }
+ }
+
+ override fun newArray(size: Int): Array<Quare?> {
+ return arrayOfNulls(size)
+ }
+ }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt b/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt
new file mode 100644
index 000000000000..ce439a9a663c
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.egg.quares
+
+import android.app.Activity
+import android.content.Context
+import android.content.res.Configuration
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.Typeface
+import android.graphics.drawable.Icon
+import android.os.Bundle
+import android.text.StaticLayout
+import android.text.TextPaint
+import android.util.Log
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.widget.Button
+import android.widget.CompoundButton
+import android.widget.GridLayout
+
+import java.util.Random
+
+import com.android.egg.R
+
+const val TAG = "Quares"
+
+class QuaresActivity : Activity() {
+ private var q: Quare = Quare(16, 16, 1)
+ private var resId = 0
+ private var resName = ""
+ private var icon: Icon? = null
+
+ private lateinit var label: Button
+ private lateinit var grid: GridLayout
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ window.decorView.systemUiVisibility =
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+
+ actionBar?.hide()
+
+ setContentView(R.layout.activity_quares)
+
+ grid = findViewById(R.id.grid)
+ label = findViewById(R.id.label)
+
+ if (savedInstanceState != null) {
+ Log.v(TAG, "restoring puzzle from state")
+ q = savedInstanceState.getParcelable("q") ?: q
+ resId = savedInstanceState.getInt("resId")
+ resName = savedInstanceState.getString("resName", "")
+ loadPuzzle()
+ }
+
+ label.setOnClickListener { newPuzzle() }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ if (resId == 0) {
+ // lazy init from onCreate
+ newPuzzle()
+ }
+ checkVictory()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+
+ outState.putParcelable("q", q)
+ outState.putInt("resId", resId)
+ outState.putString("resName", resName)
+ }
+
+ fun newPuzzle() {
+ Log.v(TAG, "new puzzle...")
+
+ q.resetUserMarks()
+ val oldResId = resId
+ resId = android.R.drawable.stat_sys_warning
+ try {
+ for (tries in 0..3) {
+ val ar = resources.obtainTypedArray(R.array.puzzles)
+ val newName = ar.getString(Random().nextInt(ar.length()))
+ if (newName == null) continue
+
+ Log.v(TAG, "Looking for icon " + newName)
+
+ val pkg = getPackageNameForResourceName(newName)
+ val newId = packageManager.getResourcesForApplication(pkg)
+ .getIdentifier(newName, "drawable", pkg)
+ if (newId == 0) {
+ Log.v(TAG, "oops, " + newName + " doesn't resolve from pkg " + pkg)
+ } else if (newId != oldResId) {
+ // got a good one
+ resId = newId
+ resName = newName
+ break
+ }
+ }
+ } catch (e: RuntimeException) {
+ Log.v(TAG, "problem loading puzzle, using fallback", e)
+ }
+ loadPuzzle()
+ }
+
+ fun getPackageNameForResourceName(name: String): String {
+ return if (name.contains(":") && !name.startsWith("android:")) {
+ name.substring(0, name.indexOf(":"))
+ } else {
+ packageName
+ }
+ }
+
+ fun checkVictory() {
+ if (q.check()) {
+ val dp = resources.displayMetrics.density
+
+ val label: Button = findViewById(R.id.label)
+ label.text = resName.replace(Regex("^.*/"), "")
+ val drawable = icon?.loadDrawable(this)?.also {
+ it.setBounds(0, 0, (32 * dp).toInt(), (32 * dp).toInt())
+ it.setTint(label.currentTextColor)
+ }
+ label.setCompoundDrawables(drawable, null, null, null)
+
+ label.visibility = VISIBLE
+ } else {
+ label.visibility = GONE
+ }
+ }
+
+ fun loadPuzzle() {
+ Log.v(TAG, "loading " + resName + " at " + q.width + "x" + q.height)
+
+ val dp = resources.displayMetrics.density
+
+ icon = Icon.createWithResource(getPackageNameForResourceName(resName), resId)
+ q.load(this, icon!!)
+
+ if (q.isBlank()) {
+ // this is a really boring puzzle, let's try again
+ resId = 0
+ resName = ""
+ recreate()
+ return
+ }
+
+ grid.removeAllViews()
+ grid.columnCount = q.width + 1
+ grid.rowCount = q.height + 1
+
+ label.visibility = GONE
+
+ val orientation = resources.configuration.orientation
+
+ // clean this up a bit
+ val minSide = resources.configuration.smallestScreenWidthDp - 25 // ish
+ val size = (minSide / (q.height + 0.5) * dp).toInt()
+
+ val sb = StringBuffer()
+
+ for (j in 0 until grid.rowCount) {
+ for (i in 0 until grid.columnCount) {
+ val tv: View
+ val params = GridLayout.LayoutParams().also {
+ it.width = size
+ it.height = size
+ it.setMargins(1, 1, 1, 1)
+ it.rowSpec = GridLayout.spec(GridLayout.UNDEFINED, GridLayout.TOP) // UGH
+ }
+ val x = i - 1
+ val y = j - 1
+ if (i > 0 && j > 0) {
+ if (i == 1 && j > 1) sb.append("\n")
+ sb.append(if (q.getDataAt(x, y) == 0) " " else "X")
+ tv = PixelButton(this)
+ tv.isChecked = q.getUserMark(x, y) != 0
+ tv.setOnClickListener {
+ q.setUserMark(x, y, if (tv.isChecked) 0xFF else 0)
+ val columnCorrect = (grid.getChildAt(i) as? ClueView)?.check(q) ?: false
+ val rowCorrect = (grid.getChildAt(j*(grid.columnCount)) as? ClueView)
+ ?.check(q) ?: false
+ if (columnCorrect && rowCorrect) {
+ checkVictory()
+ } else {
+ label.visibility = GONE
+ }
+ }
+ } else if (i == j) { // 0,0
+ tv = View(this)
+ tv.visibility = GONE
+ } else {
+ tv = ClueView(this)
+ if (j == 0) {
+ tv.textRotation = 90f
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ params.height /= 2
+ tv.showText = false
+ } else {
+ params.height = (96 * dp).toInt()
+ }
+ if (x >= 0) {
+ tv.setColumn(q, x)
+ }
+ }
+ if (i == 0) {
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ params.width /= 2
+ tv.showText = false
+ } else {
+ params.width = (96 * dp).toInt()
+ }
+ if (y >= 0) {
+ tv.setRow(q, y)
+ }
+ }
+ }
+ grid.addView(tv, params)
+ }
+ }
+
+ Log.v(TAG, "icon: \n" + sb)
+ }
+}
+
+class PixelButton(context: Context) : CompoundButton(context) {
+ init {
+ setBackgroundResource(R.drawable.pixel_bg)
+ isClickable = true
+ isEnabled = true
+ }
+}
+
+class ClueView(context: Context) : View(context) {
+ var row: Int = -1
+ var column: Int = -1
+ var textRotation: Float = 0f
+ var text: CharSequence = ""
+ var showText = true
+ val paint: TextPaint
+ val incorrectColor: Int
+ val correctColor: Int
+
+ init {
+ setBackgroundColor(0)
+ paint = TextPaint().also {
+ it.textSize = 14f * context.resources.displayMetrics.density
+ it.color = context.getColor(R.color.q_clue_text)
+ it.typeface = Typeface.DEFAULT_BOLD
+ it.textAlign = Paint.Align.CENTER
+ }
+ incorrectColor = context.getColor(R.color.q_clue_bg)
+ correctColor = context.getColor(R.color.q_clue_bg_correct)
+ }
+
+ fun setRow(q: Quare, row: Int): Boolean {
+ this.row = row
+ this.column = -1
+ this.textRotation = 0f
+ text = q.getRowClue(row).joinToString("-")
+ return check(q)
+ }
+ fun setColumn(q: Quare, column: Int): Boolean {
+ this.column = column
+ this.row = -1
+ this.textRotation = 90f
+ text = q.getColumnClue(column).joinToString("-")
+ return check(q)
+ }
+ fun check(q: Quare): Boolean {
+ val correct = q.check(column, row)
+ setBackgroundColor(if (correct) correctColor else incorrectColor)
+ return correct
+ }
+
+ override fun onDraw(canvas: Canvas?) {
+ super.onDraw(canvas)
+ if (!showText) return
+ canvas?.let {
+ val x = canvas.width / 2f
+ val y = canvas.height / 2f
+ var textWidth = canvas.width
+ if (textRotation != 0f) {
+ canvas.rotate(textRotation, x, y)
+ textWidth = canvas.height
+ }
+ val textLayout = StaticLayout.Builder.obtain(
+ text, 0, text.length, paint, textWidth).build()
+ canvas.translate(x, y - textLayout.height / 2)
+ textLayout.draw(canvas)
+ }
+ }
+}
diff --git a/packages/SettingsLib/AppPreference/res/layout/preference_app.xml b/packages/SettingsLib/AppPreference/res/layout/preference_app.xml
index dbc51958ae0b..8c208e35a371 100644
--- a/packages/SettingsLib/AppPreference/res/layout/preference_app.xml
+++ b/packages/SettingsLib/AppPreference/res/layout/preference_app.xml
@@ -61,6 +61,7 @@
android:id="@android:id/summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:textDirection="locale"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary"/>
diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS
index d87908738b56..a28ba8584054 100644
--- a/packages/SettingsLib/OWNERS
+++ b/packages/SettingsLib/OWNERS
@@ -1,21 +1,13 @@
# People who can approve changes for submission
-asapperstein@google.com
-asargent@google.com
-dehboxturtle@google.com
-dhnishi@google.com
-dling@google.com
dsandler@android.com
+edgarwang@google.com
+emilychuang@google.com
evanlaird@google.com
-jackqdyulei@google.com
-jmonk@google.com
leifhendrik@google.com
-mfritze@google.com
-rogerxue@google.com
+rafftsai@google.com
+tmfang@google.com
virgild@google.com
zhfan@google.com
-# Emergency approvers in case the above are not available
-miket@google.com
-
# Exempt resource files (because they are in a flat directory and too hard to manage via OWNERS)
per-file *.xml=*
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index 7f906f6c5b06..6d874ab2be9b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -117,7 +117,7 @@ public class HidProfile implements LocalBluetoothProfile {
public boolean isPreferred(BluetoothDevice device) {
if (mService == null) return false;
- return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ return mService.getPriority(device) != BluetoothProfile.PRIORITY_OFF;
}
public int getPreferred(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
index 0b6996365372..ac7a12187fd6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
+++ b/packages/SettingsLib/src/com/android/settingslib/license/LicenseHtmlLoaderCompat.java
@@ -38,7 +38,7 @@ public class LicenseHtmlLoaderCompat extends AsyncLoaderCompat<File> {
"/odm/etc/NOTICE.xml.gz",
"/oem/etc/NOTICE.xml.gz",
"/product/etc/NOTICE.xml.gz",
- "/product_services/etc/NOTICE.xml.gz"};
+ "/system_ext/etc/NOTICE.xml.gz"};
static final String NOTICE_HTML_FILE_NAME = "NOTICE.html";
private final Context mContext;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index de38e8a366b4..b15ea980ae15 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -18,15 +18,11 @@ package com.android.settingslib.net;
import android.content.Context;
import android.net.NetworkTemplate;
-import android.os.ParcelUuid;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Utils class for data usage
*/
@@ -38,7 +34,7 @@ public class DataUsageUtils {
*/
public static NetworkTemplate getMobileTemplate(Context context, int subId) {
final TelephonyManager telephonyManager = context.getSystemService(
- TelephonyManager.class);
+ TelephonyManager.class).createForSubscriptionId(subId);
final SubscriptionManager subscriptionManager = context.getSystemService(
SubscriptionManager.class);
final SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(subId);
@@ -49,23 +45,8 @@ public class DataUsageUtils {
Log.i(TAG, "Subscription is not active: " + subId);
return mobileAll;
}
- final ParcelUuid groupUuid = info.getGroupUuid();
- if (groupUuid == null) {
- Log.i(TAG, "Subscription doesn't have valid group uuid: " + subId);
- return mobileAll;
- }
- // Otherwise merge other subscriberId to create new NetworkTemplate
- final List<SubscriptionInfo> groupInfos = subscriptionManager.getSubscriptionsInGroup(
- groupUuid);
- final List<String> mergedSubscriberIds = new ArrayList<>();
- for (SubscriptionInfo subInfo : groupInfos) {
- final String subscriberId = telephonyManager.getSubscriberId(
- subInfo.getSubscriptionId());
- if (subscriberId != null) {
- mergedSubscriberIds.add(subscriberId);
- }
- }
- return NetworkTemplate.normalize(mobileAll, mergedSubscriberIds.toArray(new String[0]));
+ // Use old API to build networkTemplate
+ return NetworkTemplate.normalize(mobileAll, telephonyManager.getMergedSubscriberIds());
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
index dc33cfe4b2f8..821c0b3a23f7 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
@@ -44,7 +44,6 @@ import java.util.List;
public class DataUsageUtilsTest {
private static final int SUB_ID = 1;
- private static final int SUB_ID_2 = 2;
private static final String SUBSCRIBER_ID = "Test Subscriber";
private static final String SUBSCRIBER_ID_2 = "Test Subscriber 2";
@@ -67,11 +66,11 @@ public class DataUsageUtilsTest {
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+ when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
when(mTelephonyManager.getSubscriberId(SUB_ID)).thenReturn(SUBSCRIBER_ID);
- when(mTelephonyManager.getSubscriberId(SUB_ID_2)).thenReturn(SUBSCRIBER_ID_2);
- when(mInfo1.getSubscriptionId()).thenReturn(SUB_ID);
- when(mInfo2.getSubscriptionId()).thenReturn(SUB_ID_2);
+ when(mTelephonyManager.getMergedSubscriberIds()).thenReturn(
+ new String[]{SUBSCRIBER_ID, SUBSCRIBER_ID_2});
mInfos = new ArrayList<>();
mInfos.add(mInfo1);
@@ -89,17 +88,7 @@ public class DataUsageUtilsTest {
}
@Test
- public void getMobileTemplate_groupUuidNull_returnMobileAll() {
- when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
- when(mInfo1.getGroupUuid()).thenReturn(null);
-
- final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
- assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
- assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse();
- }
-
- @Test
- public void getMobileTemplate_groupUuidExist_returnMobileMerged() {
+ public void getMobileTemplate_infoExisted_returnMobileMerged() {
when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
when(mInfo1.getGroupUuid()).thenReturn(mParcelUuid);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 98c6702f899d..8689eef79583 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -101,6 +101,8 @@
<uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.WHITELIST_RESTRICTED_PERMISSIONS" />
+ <!-- Permission required to test onPermissionsChangedListener -->
+ <uses-permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS" />
<uses-permission android:name="android.permission.SET_KEYBOARD_LAYOUT" />
<uses-permission android:name="android.permission.GET_DETAILED_TASKS" />
<uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 17274f418a1e..4f74605b4003 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -20,6 +20,7 @@
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
package="com.android.systemui"
android:sharedUserId="android.uid.systemui"
+ xmlns:tools="http://schemas.android.com/tools"
coreApp="true">
<!-- Using OpenGL ES 2.0 -->
@@ -259,7 +260,8 @@
android:theme="@style/Theme.SystemUI"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
- android:appComponentFactory="androidx.core.app.CoreComponentFactory">
+ tools:replace="android:appComponentFactory"
+ android:appComponentFactory=".SystemUIAppComponentFactory">
<!-- Keep theme in sync with SystemUIApplication.onCreate().
Setting the theme on the application does not affect views inflated by services.
The application theme is set again from onCreate to take effect for those views. -->
diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md
index c2159df1cee1..c440fba10135 100644
--- a/packages/SystemUI/docs/dagger.md
+++ b/packages/SystemUI/docs/dagger.md
@@ -53,7 +53,7 @@ variants (like other form factors e.g. Car).
### Adding injection to a new SystemUI object
Anything that depends on any `@Singleton` provider from SystemUIRootComponent
-should be declared as an `@Subcomponent` of the root component, this requires
+should be declared as a `@Subcomponent` of the root component. This requires
declaring your own interface for generating your own modules or just the
object you need injected. The subcomponent also needs to be added to
SystemUIRootComponent in SystemUIFactory so it can be acquired.
@@ -204,6 +204,13 @@ public CustomView(@Named(VIEW_CONTEXT) Context themedViewContext, AttributeSet a
}
```
+## Updating Dagger2
+
+Binaries can be downloaded from https://repo1.maven.org/maven2/com/google/dagger/ and then loaded
+into
+[/prebuilts/tools/common/m2/repository/com/google/dagger/](http://cs/android/prebuilts/tools/common/m2/repository/com/google/dagger/)
+
+
## TODO List
- Eliminate usages of Dependency#get
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java
index 14fd149d22f4..b89218c81a91 100644
--- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java
@@ -41,8 +41,10 @@ import android.widget.ScrollView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.recents.LegacyRecentsImpl;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
@@ -86,15 +88,15 @@ import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.utilities.AnimationProps;
import com.android.systemui.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.grid.GridTaskView;
import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
import com.android.systemui.recents.views.grid.TaskViewFocusFrame;
-
+import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -256,7 +258,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, this);
mStableLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, null);
mStackScroller = new TaskStackViewScroller(context, this, mLayoutAlgorithm);
- mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
+ mTouchHandler = new TaskStackViewTouchHandler(
+ context, this, mStackScroller, Dependency.get(FalsingManager.class));
mAnimationHelper = new TaskStackAnimationHelper(context, this);
mTaskCornerRadiusPx = LegacyRecentsImpl.getConfiguration().isGridEnabled ?
res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index dd6926c848b4..a7fb4fae09ec 100644
--- a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -37,6 +37,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.LegacyRecentsImpl;
import com.android.systemui.recents.events.EventBus;
@@ -107,7 +108,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
boolean mInterceptedBySwipeHelper;
public TaskStackViewTouchHandler(Context context, TaskStackView sv,
- TaskStackViewScroller scroller) {
+ TaskStackViewScroller scroller, FalsingManager falsingManager) {
Resources res = context.getResources();
ViewConfiguration configuration = ViewConfiguration.get(context);
mContext = context;
@@ -119,7 +120,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
mWindowTouchSlop = configuration.getScaledWindowTouchSlop();
mFlingAnimUtils = new FlingAnimationUtils(context, 0.2f);
mOverscrollSize = res.getDimensionPixelSize(R.dimen.recents_fling_overscroll_distance);
- mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, context) {
+ mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, context, falsingManager) {
@Override
protected float getSize(View v) {
return getScaledDismissSize();
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index a549870ec780..7c2413039ae4 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -480,4 +480,10 @@
<!-- ThemePicker package name for overlaying icons. -->
<string name="themepicker_overlayable_package" translatable="false">com.android.wallpaper</string>
+ <!-- Default rounded corner curve (a Bezier). Must match (the curved path in) rounded.xml.
+ Note that while rounded.xml includes the entire path (including the horizontal and vertical
+ corner edges), this pulls out just the curve.
+ -->
+ <string name="config_rounded_mask" translatable="false">"M8,0C3.6,0,0,3.6,0,8"</string>
+
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index a2abb4b1695c..506813beadf6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -307,28 +307,22 @@ public class ActivityManagerWrapper {
}
final ActivityOptions finalOptions = options;
- // Execute this from another thread such that we can do other things (like caching the
- // bitmap for the thumbnail) while AM is busy starting our activity.
- mBackgroundExecutor.submit(new Runnable() {
- @Override
- public void run() {
- boolean result = false;
- try {
- result = startActivityFromRecents(taskKey.id, finalOptions);
- } catch (Exception e) {
- // Fall through
- }
- final boolean finalResult = result;
- if (resultCallback != null) {
- resultCallbackHandler.post(new Runnable() {
- @Override
- public void run() {
- resultCallback.accept(finalResult);
- }
- });
+
+ boolean result = false;
+ try {
+ result = startActivityFromRecents(taskKey.id, finalOptions);
+ } catch (Exception e) {
+ // Fall through
+ }
+ final boolean finalResult = result;
+ if (resultCallback != null) {
+ resultCallbackHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ resultCallback.accept(finalResult);
}
- }
- });
+ });
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java
new file mode 100644
index 000000000000..8fabe7aa9eb6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+/**
+ * Interface necessary to make Dagger happy. See {@link ContextComponentResolver}.
+ */
+public interface ContextComponentHelper {
+ /** Turns a classname into an instance of the class or returns null. */
+ <T> T resolve(String className);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java
new file mode 100644
index 000000000000..09bccd993f39
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+/**
+ * Used during Service and Activity instantiation to make them injectable.
+ */
+public class ContextComponentResolver implements ContextComponentHelper {
+ private final Map<Class<?>, Provider<Object>> mCreators;
+
+ @Inject
+ ContextComponentResolver(Map<Class<?>, Provider<Object>> creators) {
+ mCreators = creators;
+ }
+
+ /**
+ * Looks up the class name to see if Dagger has an instance of it.
+ */
+ @Override
+ public <T> T resolve(String className) {
+ for (Map.Entry<Class<?>, Provider<Object>> p : mCreators.entrySet()) {
+ if (p.getKey().getName().equals(className)) {
+ return (T) p.getValue().get();
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 9a0e9fc92af6..c9d4957494e4 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -46,6 +46,8 @@ public class ImageWallpaper extends WallpaperService {
// We delayed destroy render context that subsequent render requests have chance to cancel it.
// This is to avoid destroying then recreating render context in a very short time.
private static final int DELAY_FINISH_RENDERING = 1000;
+ private static final int INTERVAL_WAIT_FOR_RENDERING = 100;
+ private static final int PATIENCE_WAIT_FOR_RENDERING = 5;
private HandlerThread mWorker;
@Override
@@ -80,7 +82,10 @@ public class ImageWallpaper extends WallpaperService {
private StatusBarStateController mController;
private final Runnable mFinishRenderingTask = this::finishRendering;
private final boolean mNeedTransition;
+ private final Object mMonitor = new Object();
private boolean mNeedRedraw;
+ // This variable can only be accessed in synchronized block.
+ private boolean mWaitingForRendering;
GLEngine(Context context) {
mNeedTransition = ActivityManager.isHighEndGfx()
@@ -122,6 +127,27 @@ public class ImageWallpaper extends WallpaperService {
long duration = mNeedTransition || animationDuration != 0 ? animationDuration : 0;
mWorker.getThreadHandler().post(
() -> mRenderer.updateAmbientMode(inAmbientMode, duration));
+ if (inAmbientMode && duration == 0) {
+ // This means that we are transiting from home to aod, to avoid
+ // race condition between window visibility and transition,
+ // we don't return until the transition is finished. See b/136643341.
+ waitForBackgroundRendering();
+ }
+ }
+
+ private void waitForBackgroundRendering() {
+ synchronized (mMonitor) {
+ try {
+ mWaitingForRendering = true;
+ for (int patience = 1; mWaitingForRendering; patience++) {
+ mMonitor.wait(INTERVAL_WAIT_FOR_RENDERING);
+ mWaitingForRendering &= patience < PATIENCE_WAIT_FOR_RENDERING;
+ }
+ } catch (InterruptedException ex) {
+ } finally {
+ mWaitingForRendering = false;
+ }
+ }
}
@Override
@@ -178,7 +204,8 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void preRender() {
- mWorker.getThreadHandler().post(this::preRenderInternal);
+ // This method should only be invoked from worker thread.
+ preRenderInternal();
}
private void preRenderInternal() {
@@ -212,7 +239,8 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void requestRender() {
- mWorker.getThreadHandler().post(this::requestRenderInternal);
+ // This method should only be invoked from worker thread.
+ requestRenderInternal();
}
private void requestRenderInternal() {
@@ -234,7 +262,21 @@ public class ImageWallpaper extends WallpaperService {
@Override
public void postRender() {
- mWorker.getThreadHandler().post(this::scheduleFinishRendering);
+ // This method should only be invoked from worker thread.
+ notifyWaitingThread();
+ scheduleFinishRendering();
+ }
+
+ private void notifyWaitingThread() {
+ synchronized (mMonitor) {
+ if (mWaitingForRendering) {
+ try {
+ mWaitingForRendering = false;
+ mMonitor.notify();
+ } catch (IllegalMonitorStateException ex) {
+ }
+ }
+ }
}
private void cancelFinishRenderingTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
new file mode 100644
index 000000000000..6282c6e5282f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import com.android.systemui.doze.DozeService;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+
+/**
+ * Services and Activities that are injectable should go here.
+ */
+@Module
+public abstract class ServiceBinder {
+
+ @Binds
+ public abstract ContextComponentHelper bindComponentHelper(
+ ContextComponentResolver componentHelper);
+
+ @Binds
+ @IntoMap
+ @ClassKey(DozeService.class)
+ public abstract Object bindDozeService(DozeService service);
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 84e0238fdd3a..58c52a1fc50e 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -34,7 +34,6 @@ import android.view.View;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -98,7 +97,8 @@ public class SwipeHelper implements Gefingerpoken {
private final ArrayMap<View, Animator> mDismissPendingMap = new ArrayMap<>();
- public SwipeHelper(int swipeDirection, Callback callback, Context context) {
+ public SwipeHelper(
+ int swipeDirection, Callback callback, Context context, FalsingManager falsingManager) {
mContext = context;
mCallback = callback;
mHandler = new Handler();
@@ -113,7 +113,7 @@ public class SwipeHelper implements Gefingerpoken {
mDensityScale = res.getDisplayMetrics().density;
mFalsingThreshold = res.getDimensionPixelSize(R.dimen.swipe_helper_falsing_threshold);
mFadeDependingOnAmountSwiped = res.getBoolean(R.bool.config_fadeDependingOnAmountSwiped);
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = falsingManager;
mFlingAnimationUtils = new FlingAnimationUtils(context, getMaxEscapeAnimDuration() / 1000f);
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
new file mode 100644
index 000000000000..00ae99295768
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.app.Application;
+import android.app.Service;
+import android.content.Intent;
+
+import androidx.core.app.CoreComponentFactory;
+
+import javax.inject.Inject;
+
+/**
+ * Implementation of AppComponentFactory that injects into constructors.
+ */
+public class SystemUIAppComponentFactory extends CoreComponentFactory {
+
+ @Inject
+ public ContextComponentHelper mComponentHelper;
+
+ public SystemUIAppComponentFactory() {
+ super();
+ }
+
+ @Override
+ public Application instantiateApplication(ClassLoader cl, String className)
+ throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ Application app = super.instantiateApplication(cl, className);
+ if (app instanceof SystemUIApplication) {
+ ((SystemUIApplication) app).setContextAvailableCallback(
+ context -> {
+ SystemUIFactory.createFromConfig(context);
+ SystemUIFactory.getInstance().getRootComponent().inject(
+ SystemUIAppComponentFactory.this);
+ }
+ );
+ }
+
+ return app;
+ }
+
+ @Override
+ public Service instantiateService(ClassLoader cl, String className, Intent intent)
+ throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ Service service = mComponentHelper.resolve(className);
+ if (service != null) {
+ return checkCompatWrapper(service);
+ }
+ return super.instantiateService(cl, className, intent);
+ }
+
+ static <T> T checkCompatWrapper(T obj) {
+ if (obj instanceof CompatWrapped) {
+ T wrapper = (T) ((CompatWrapped) obj).getWrapper();
+ if (wrapper != null) {
+ return wrapper;
+ }
+ }
+
+ return obj;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index e89e6cb269f8..f8449add6dce 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -60,16 +60,20 @@ public class SystemUIApplication extends Application implements SysUiServiceProv
private boolean mServicesStarted;
private boolean mBootCompleted;
private final Map<Class<?>, Object> mComponents = new HashMap<>();
+ private ContextAvailableCallback mContextAvailableCallback;
@Override
public void onCreate() {
super.onCreate();
+ // This line is used to setup Dagger's dependency injection and should be kept at the
+ // top of this method.
+ mContextAvailableCallback.onContextAvailable(this);
+
// Set the application theme that is inherited by all services. Note that setting the
// application theme in the manifest does only work for activities. Keep this in sync with
// the theme set there.
setTheme(R.style.Theme_SystemUI);
- SystemUIFactory.createFromConfig(this);
if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
@@ -286,4 +290,12 @@ public class SystemUIApplication extends Application implements SysUiServiceProv
public SystemUI[] getServices() {
return mServices;
}
+
+ void setContextAvailableCallback(ContextAvailableCallback callback) {
+ mContextAvailableCallback = callback;
+ }
+
+ interface ContextAvailableCallback {
+ void onContextAvailable(Context context);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 4d42e0c66817..311ed8a913f1 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -19,8 +19,8 @@ package com.android.systemui;
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
-import android.annotation.Nullable;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AlarmManager;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -29,17 +29,15 @@ import android.os.Looper;
import android.util.Log;
import android.view.ViewGroup;
-
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.internal.util.function.TriConsumer;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.assist.AssistManager;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.dock.DockManager;
-import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
@@ -69,8 +67,6 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.util.AsyncSensorManager;
-import com.android.systemui.util.InjectionInflationController;
-import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeDialogComponent;
import java.util.function.Consumer;
@@ -78,7 +74,6 @@ import java.util.function.Consumer;
import javax.inject.Named;
import javax.inject.Singleton;
-import dagger.Component;
import dagger.Module;
import dagger.Provides;
@@ -116,7 +111,7 @@ public class SystemUIFactory {
public SystemUIFactory() {}
protected void init(Context context) {
- initWithRootComponent(DaggerSystemUIFactory_SystemUIRootComponent.builder()
+ initWithRootComponent(DaggerSystemUIRootComponent.builder()
.systemUIFactory(this)
.dependencyProvider(new com.android.systemui.DependencyProvider())
.contextHolder(new ContextHolder(context))
@@ -143,9 +138,10 @@ public class SystemUIFactory {
public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
LockPatternUtils lockPatternUtils, ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry,
- KeyguardBouncer.BouncerExpansionCallback expansionCallback) {
+ KeyguardBouncer.BouncerExpansionCallback expansionCallback,
+ FalsingManager falsingManager) {
return new KeyguardBouncer(context, callback, lockPatternUtils, container,
- dismissCallbackRegistry, FalsingManagerFactory.getInstance(context),
+ dismissCallbackRegistry, falsingManager,
expansionCallback, UnlockMethodCache.getInstance(context),
KeyguardUpdateMonitor.getInstance(context), new Handler(Looper.getMainLooper()));
}
@@ -276,29 +272,4 @@ public class SystemUIFactory {
return mContext;
}
}
-
- @Singleton
- @Component(modules = {SystemUIFactory.class, DependencyProvider.class, DependencyBinder.class,
- ContextHolder.class})
- public interface SystemUIRootComponent {
- @Singleton
- Dependency.DependencyInjector createDependency();
-
- @Singleton
- StatusBar.StatusBarInjector getStatusBarInjector();
-
- /**
- * FragmentCreator generates all Fragments that need injection.
- */
- @Singleton
- FragmentService.FragmentCreator createFragmentCreator();
-
- /**
- * ViewCreator generates all Views that need injection.
- */
- InjectionInflationController.ViewCreator createViewCreator();
-
- @Singleton
- GarbageMonitor createGarbageMonitor();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
new file mode 100644
index 000000000000..c732df3fdb9f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.util.InjectionInflationController;
+import com.android.systemui.util.leak.GarbageMonitor;
+
+import javax.inject.Singleton;
+
+import dagger.Component;
+
+/**
+ * Root component for Dagger injection.
+ */
+@Singleton
+@Component(modules = {SystemUIFactory.class, DependencyProvider.class, DependencyBinder.class,
+ ServiceBinder.class, SystemUIFactory.ContextHolder.class})
+public interface SystemUIRootComponent {
+ /**
+ * Main dependency providing module.
+ */
+ @Singleton
+ Dependency.DependencyInjector createDependency();
+
+ /**
+ * Injects the StatusBar.
+ */
+ @Singleton
+ StatusBar.StatusBarInjector getStatusBarInjector();
+
+ /**
+ * FragmentCreator generates all Fragments that need injection.
+ */
+ @Singleton
+ FragmentService.FragmentCreator createFragmentCreator();
+
+ /**
+ * ViewCreator generates all Views that need injection.
+ */
+ InjectionInflationController.ViewCreator createViewCreator();
+
+ /**
+ * Creatse a GarbageMonitor.
+ */
+ @Singleton
+ GarbageMonitor createGarbageMonitor();
+
+ /**
+ * Injects into the supplied argument.
+ */
+ void inject(SystemUIAppComponentFactory factory);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/CircularCornerPathRenderer.java b/packages/SystemUI/src/com/android/systemui/assist/ui/CircularCornerPathRenderer.java
index 00346a36d3f1..e61e47a2201f 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/CircularCornerPathRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/CircularCornerPathRenderer.java
@@ -16,6 +16,7 @@
package com.android.systemui.assist.ui;
+import android.content.Context;
import android.graphics.Path;
/**
@@ -29,12 +30,11 @@ public final class CircularCornerPathRenderer extends CornerPathRenderer {
private final int mWidth;
private final Path mPath = new Path();
- public CircularCornerPathRenderer(int cornerRadiusBottom, int cornerRadiusTop,
- int width, int height) {
- mCornerRadiusBottom = cornerRadiusBottom;
- mCornerRadiusTop = cornerRadiusTop;
- mHeight = height;
- mWidth = width;
+ public CircularCornerPathRenderer(Context context) {
+ mCornerRadiusBottom = DisplayUtils.getCornerRadiusBottom(context);
+ mCornerRadiusTop = DisplayUtils.getCornerRadiusTop(context);
+ mHeight = DisplayUtils.getHeight(context);
+ mWidth = DisplayUtils.getWidth(context);
}
@Override // CornerPathRenderer
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
index 43e7045511c5..bc782a7d62eb 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -247,13 +247,9 @@ public class InvocationLightsView extends View
* To render corners that aren't circular, override this method in a subclass.
*/
protected CornerPathRenderer createCornerPathRenderer(Context context) {
- int displayWidth = DisplayUtils.getWidth(context);
- int displayHeight = DisplayUtils.getHeight(context);
- int cornerRadiusBottom = DisplayUtils.getCornerRadiusBottom(context);
- int cornerRadiusTop = DisplayUtils.getCornerRadiusTop(context);
- return new CircularCornerPathRenderer(
- cornerRadiusBottom, cornerRadiusTop, displayWidth, displayHeight);
+ return new CircularCornerPathRenderer(context);
}
+
/**
* Receives an intensity from 0 (lightest) to 1 (darkest) and sets the handle color
* appropriately. Intention is to match the home handle color.
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/PathSpecCornerPathRenderer.java b/packages/SystemUI/src/com/android/systemui/assist/ui/PathSpecCornerPathRenderer.java
new file mode 100644
index 000000000000..2bad7fc9583a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/PathSpecCornerPathRenderer.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.assist.ui;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Path;
+import android.graphics.RectF;
+import android.util.Log;
+import android.util.PathParser;
+
+import com.android.systemui.R;
+
+/**
+ * Parses a path describing rounded corners from a string.
+ */
+public final class PathSpecCornerPathRenderer extends CornerPathRenderer {
+ private static final String TAG = "PathSpecCornerPathRenderer";
+
+ private final int mHeight;
+ private final int mWidth;
+ private final float mPathScale;
+ private final int mBottomCornerRadius;
+ private final int mTopCornerRadius;
+
+ private final Path mPath = new Path();
+ private final Path mRoundedPath;
+ private final Matrix mMatrix = new Matrix();
+
+ public PathSpecCornerPathRenderer(Context context) {
+ mWidth = DisplayUtils.getWidth(context);
+ mHeight = DisplayUtils.getHeight(context);
+
+ mBottomCornerRadius = DisplayUtils.getCornerRadiusBottom(context);
+ mTopCornerRadius = DisplayUtils.getCornerRadiusTop(context);
+
+ String pathData = context.getResources().getString(R.string.config_rounded_mask);
+ Path path = PathParser.createPathFromPathData(pathData);
+ if (path == null) {
+ Log.e(TAG, "No rounded corner path found!");
+ mRoundedPath = new Path();
+ } else {
+ mRoundedPath = path;
+
+ }
+
+ RectF bounds = new RectF();
+ mRoundedPath.computeBounds(bounds, true);
+
+ // we use this to scale the path such that the larger of its [width, height] is scaled to
+ // the corner radius (to account for asymmetric paths)
+ mPathScale = Math.min(
+ Math.abs(bounds.right - bounds.left),
+ Math.abs(bounds.top - bounds.bottom));
+ }
+
+ /**
+ * Scales and rotates each corner from the path specification to its correct position.
+ *
+ * Note: the rounded corners are passed in as the full shape (a curved triangle), but we only
+ * want the actual corner curve. Therefore we call getSegment to jump past the horizontal and
+ * vertical lines.
+ */
+ @Override
+ public Path getCornerPath(Corner corner) {
+ if (mRoundedPath.isEmpty()) {
+ return mRoundedPath;
+ }
+ int cornerRadius;
+ int rotateDegrees;
+ int translateX;
+ int translateY;
+ switch (corner) {
+ case TOP_LEFT:
+ cornerRadius = mTopCornerRadius;
+ rotateDegrees = 0;
+ translateX = 0;
+ translateY = 0;
+ break;
+ case TOP_RIGHT:
+ cornerRadius = mTopCornerRadius;
+ rotateDegrees = 90;
+ translateX = mWidth;
+ translateY = 0;
+ break;
+ case BOTTOM_RIGHT:
+ cornerRadius = mBottomCornerRadius;
+ rotateDegrees = 180;
+ translateX = mWidth;
+ translateY = mHeight;
+ break;
+ case BOTTOM_LEFT:
+ default:
+ cornerRadius = mBottomCornerRadius;
+ rotateDegrees = 270;
+ translateX = 0;
+ translateY = mHeight;
+ break;
+ }
+ mPath.reset();
+ mMatrix.reset();
+ mPath.addPath(mRoundedPath);
+
+ mMatrix.preScale(cornerRadius / mPathScale, cornerRadius / mPathScale);
+ mMatrix.postRotate(rotateDegrees);
+ mMatrix.postTranslate(translateX, translateY);
+ mPath.transform(mMatrix);
+ return mPath;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/PerimeterPathGuide.java b/packages/SystemUI/src/com/android/systemui/assist/ui/PerimeterPathGuide.java
index 65a9fcc3a955..fb41b1c4715f 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/PerimeterPathGuide.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/PerimeterPathGuide.java
@@ -102,7 +102,7 @@ public class PerimeterPathGuide {
* Sets the rotation.
*
* @param rotation one of Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_180,
- * Surface.ROTATION_270
+ * Surface.ROTATION_270
*/
public void setRotation(int rotation) {
if (rotation != mRotation) {
@@ -229,14 +229,14 @@ public class PerimeterPathGuide {
- mDeviceWidthPx) / 2, (mDeviceWidthPx - mDeviceHeightPx) / 2);
}
- CircularCornerPathRenderer.Corner screenBottomLeft = getRotatedCorner(
- CircularCornerPathRenderer.Corner.BOTTOM_LEFT);
- CircularCornerPathRenderer.Corner screenBottomRight = getRotatedCorner(
- CircularCornerPathRenderer.Corner.BOTTOM_RIGHT);
- CircularCornerPathRenderer.Corner screenTopLeft = getRotatedCorner(
- CircularCornerPathRenderer.Corner.TOP_LEFT);
- CircularCornerPathRenderer.Corner screenTopRight = getRotatedCorner(
- CircularCornerPathRenderer.Corner.TOP_RIGHT);
+ CornerPathRenderer.Corner screenBottomLeft = getRotatedCorner(
+ CornerPathRenderer.Corner.BOTTOM_LEFT);
+ CornerPathRenderer.Corner screenBottomRight = getRotatedCorner(
+ CornerPathRenderer.Corner.BOTTOM_RIGHT);
+ CornerPathRenderer.Corner screenTopLeft = getRotatedCorner(
+ CornerPathRenderer.Corner.TOP_LEFT);
+ CornerPathRenderer.Corner screenTopRight = getRotatedCorner(
+ CornerPathRenderer.Corner.TOP_RIGHT);
mRegions[Region.BOTTOM_LEFT.ordinal()].path =
mCornerPathRenderer.getInsetPath(screenBottomLeft, mEdgeInset);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java
deleted file mode 100644
index 01921f0d9a60..000000000000
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFactory.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2015 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.classifier;
-
-import android.content.Context;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.plugins.FalsingManager;
-
-/**
- * When the phone is locked, listens to touch, sensor and phone events and sends them to
- * DataCollector and HumanInteractionClassifier.
- *
- * It does not collect touch events when the bouncer shows up.
- *
- * TODO: FalsingManager supports dependency injection. Use it.
- */
-public class FalsingManagerFactory {
- private static FalsingManager sInstance = null;
-
- private FalsingManagerFactory() {}
-
- public static FalsingManager getInstance(Context context) {
- if (sInstance == null) {
- sInstance = Dependency.get(FalsingManager.class);
- }
- return sInstance;
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
new file mode 100644
index 000000000000..0041b0c9a469
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.classifier;
+
+import android.net.Uri;
+import android.view.MotionEvent;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.plugins.FalsingManager;
+
+import java.io.PrintWriter;
+
+/**
+ * Simple Fake for testing where {@link FalsingManager} is required.
+ */
+public class FalsingManagerFake implements FalsingManager {
+ private boolean mIsFalseTouch;
+ private boolean mIsUnlockingDisabled;
+ private boolean mIsClassiferEnabled;
+ private boolean mShouldEnforceBouncer;
+ private boolean mIsReportingEnabled;
+
+ @Override
+ public void onSucccessfulUnlock() {
+
+ }
+
+ @Override
+ public void onNotificationActive() {
+
+ }
+
+ @Override
+ public void setShowingAod(boolean showingAod) {
+
+ }
+
+ @Override
+ public void onNotificatonStartDraggingDown() {
+
+ }
+
+ @VisibleForTesting
+ public void setIsUnlockingDisabled(boolean isUnlockingDisabled) {
+ mIsUnlockingDisabled = isUnlockingDisabled;
+ }
+
+ @Override
+ public boolean isUnlockingDisabled() {
+ return mIsUnlockingDisabled;
+ }
+
+ @VisibleForTesting
+ public void setIsFalseTouch(boolean isFalseTouch) {
+ mIsFalseTouch = isFalseTouch;
+ }
+
+ @Override
+ public boolean isFalseTouch() {
+ return mIsFalseTouch;
+ }
+
+ @Override
+ public void onNotificatonStopDraggingDown() {
+
+ }
+
+ @Override
+ public void setNotificationExpanded() {
+
+ }
+
+ @VisibleForTesting
+ public void setIsClassiferEnabled(boolean isClassiferEnabled) {
+ mIsClassiferEnabled = isClassiferEnabled;
+ }
+
+ @Override
+ public boolean isClassiferEnabled() {
+ return mIsClassiferEnabled;
+ }
+
+ @Override
+ public void onQsDown() {
+
+ }
+
+ @Override
+ public void setQsExpanded(boolean expanded) {
+
+ }
+
+ @VisibleForTesting
+ public void setShouldEnforceBouncer(boolean shouldEnforceBouncer) {
+ mShouldEnforceBouncer = shouldEnforceBouncer;
+ }
+
+ @Override
+ public boolean shouldEnforceBouncer() {
+ return mShouldEnforceBouncer;
+ }
+
+ @Override
+ public void onTrackingStarted(boolean secure) {
+
+ }
+
+ @Override
+ public void onTrackingStopped() {
+
+ }
+
+ @Override
+ public void onLeftAffordanceOn() {
+
+ }
+
+ @Override
+ public void onCameraOn() {
+
+ }
+
+ @Override
+ public void onAffordanceSwipingStarted(boolean rightCorner) {
+
+ }
+
+ @Override
+ public void onAffordanceSwipingAborted() {
+
+ }
+
+ @Override
+ public void onStartExpandingFromPulse() {
+
+ }
+
+ @Override
+ public void onExpansionFromPulseStopped() {
+
+ }
+
+ @Override
+ public Uri reportRejectedTouch() {
+ return null;
+ }
+
+ @Override
+ public void onScreenOnFromTouch() {
+
+ }
+
+
+ @VisibleForTesting
+ public void setIsReportingEnabled(boolean isReportingEnabled) {
+ mIsReportingEnabled = isReportingEnabled;
+ }
+
+ @Override
+ public boolean isReportingEnabled() {
+ return mIsReportingEnabled;
+ }
+
+ @Override
+ public void onUnlockHintStarted() {
+
+ }
+
+ @Override
+ public void onCameraHintStarted() {
+
+ }
+
+ @Override
+ public void onLeftAffordanceHintStarted() {
+
+ }
+
+ @Override
+ public void onScreenTurningOn() {
+
+ }
+
+ @Override
+ public void onScreenOff() {
+
+ }
+
+ @Override
+ public void onNotificatonStopDismissing() {
+
+ }
+
+ @Override
+ public void onNotificationDismissed() {
+
+ }
+
+ @Override
+ public void onNotificatonStartDismissing() {
+
+ }
+
+ @Override
+ public void onNotificationDoubleTap(boolean accepted, float dx, float dy) {
+
+ }
+
+ @Override
+ public void onBouncerShown() {
+
+ }
+
+ @Override
+ public void onBouncerHidden() {
+
+ }
+
+ @Override
+ public void onTouchEvent(MotionEvent ev, int width, int height) {
+
+ }
+
+ @Override
+ public void dump(PrintWriter pw) {
+
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index fc3d1a52342f..537c09ed3199 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -28,8 +28,8 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.AsyncSensorManager;
import com.android.systemui.util.wakelock.DelayedWakeLock;
@@ -41,7 +41,7 @@ public class DozeFactory {
}
/** Creates a DozeMachine with its parts for {@code dozeService}. */
- public DozeMachine assembleMachine(DozeService dozeService) {
+ public DozeMachine assembleMachine(DozeService dozeService, FalsingManager falsingManager) {
Context context = dozeService;
SensorManager sensorManager = Dependency.get(AsyncSensorManager.class);
AlarmManager alarmManager = context.getSystemService(AlarmManager.class);
@@ -63,7 +63,7 @@ public class DozeFactory {
DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
machine.setParts(new DozeMachine.Part[]{
new DozePauser(handler, machine, alarmManager, params.getPolicy()),
- new DozeFalsingManagerAdapter(FalsingManagerFactory.getInstance(context)),
+ new DozeFalsingManagerAdapter(falsingManager),
createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
handler, wakeLock, machine, dockManager),
createDozeUi(context, host, wakeLock, machine, handler, alarmManager, params),
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 2db73065fe19..e92acfc7f219 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -25,23 +25,29 @@ import android.util.Log;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.DozeServicePlugin;
import com.android.systemui.plugins.DozeServicePlugin.RequestDoze;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.plugins.PluginManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+
public class DozeService extends DreamService
implements DozeMachine.Service, RequestDoze, PluginListener<DozeServicePlugin> {
private static final String TAG = "DozeService";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private final FalsingManager mFalsingManager;
private DozeMachine mDozeMachine;
private DozeServicePlugin mDozePlugin;
private PluginManager mPluginManager;
- public DozeService() {
+ @Inject
+ public DozeService(FalsingManager falsingManager) {
setDebug(DEBUG);
+ mFalsingManager = falsingManager;
}
@Override
@@ -56,7 +62,7 @@ public class DozeService extends DreamService
}
mPluginManager = Dependency.get(PluginManager.class);
mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */);
- mDozeMachine = new DozeFactory().assembleMachine(this);
+ mDozeMachine = new DozeFactory().assembleMachine(this, mFalsingManager);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index 8dbaf0f681cf..b4cc571be061 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -22,7 +22,7 @@ import android.view.View;
import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.Dumpable;
-import com.android.systemui.SystemUIFactory;
+import com.android.systemui.SystemUIRootComponent;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
@@ -51,7 +51,7 @@ public class FragmentService implements ConfigurationChangedReceiver, Dumpable {
private final FragmentCreator mFragmentCreator;
@Inject
- public FragmentService(SystemUIFactory.SystemUIRootComponent rootComponent) {
+ public FragmentService(SystemUIRootComponent rootComponent) {
mFragmentCreator = rootComponent.createFragmentCreator();
initInjectionMap();
}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
index 6a1f24afe620..45e97b38d87e 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
@@ -84,7 +84,17 @@ class ImageRevealHelper {
void updateAwake(boolean awake, long duration) {
mAwake = awake;
mAnimator.setDuration(duration);
- animate();
+ if (!mAwake && duration == 0) {
+ // We are transiting from home to aod,
+ // since main thread is waiting for rendering finished, we only need draw
+ // the last state directly, which is a black screen.
+ mReveal = MIN_REVEAL;
+ mRevealListener.onRevealStart();
+ mRevealListener.onRevealStateChanged();
+ mRevealListener.onRevealEnd();
+ } else {
+ animate();
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4dcb9f94088c..819ce5f317e8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -84,7 +84,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
-import com.android.systemui.classifier.FalsingManagerFactory;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -1596,7 +1596,7 @@ public class KeyguardViewMediator extends SystemUI {
Trace.beginSection("KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM");
StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj;
handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration);
- FalsingManagerFactory.getInstance(mContext).onSucccessfulUnlock();
+ Dependency.get(FalsingManager.class).onSucccessfulUnlock();
Trace.endSection();
break;
case KEYGUARD_DONE_PENDING_TIMEOUT:
@@ -2063,10 +2063,11 @@ public class KeyguardViewMediator extends SystemUI {
public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
ViewGroup container, NotificationPanelView panelView,
BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer,
- View notificationContainer, KeyguardBypassController bypassController) {
+ View notificationContainer, KeyguardBypassController bypassController,
+ FalsingManager falsingManager) {
mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container, panelView,
biometricUnlockController, mDismissCallbackRegistry, lockIconContainer,
- notificationContainer, bypassController);
+ notificationContainer, bypassController, falsingManager);
return mStatusBarKeyguardViewManager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 514a2ae7a74e..d93982889655 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -29,7 +29,6 @@ import com.android.systemui.ExpandHelper;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -59,14 +58,15 @@ public class DragDownHelper implements Gefingerpoken {
private FalsingManager mFalsingManager;
public DragDownHelper(Context context, View host, ExpandHelper.Callback callback,
- DragDownCallback dragDownCallback) {
+ DragDownCallback dragDownCallback,
+ FalsingManager falsingManager) {
mMinDragDistance = context.getResources().getDimensionPixelSize(
R.dimen.keyguard_drag_down_min_distance);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mCallback = callback;
mDragDownCallback = dragDownCallback;
mHost = host;
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = falsingManager;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index 986486ac14d4..48d6de964b08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -27,11 +27,11 @@ import android.os.SystemClock
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.ViewConfiguration
+import com.android.systemui.Dependency
import com.android.systemui.Gefingerpoken
import com.android.systemui.Interpolators
import com.android.systemui.R
-import com.android.systemui.classifier.FalsingManagerFactory
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
@@ -115,7 +115,7 @@ constructor(context: Context,
mMinDragDistance = context.resources.getDimensionPixelSize(
R.dimen.keyguard_drag_down_min_distance)
mTouchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat()
- mFalsingManager = FalsingManagerFactory.getInstance(context)
+ mFalsingManager = Dependency.get(FalsingManager::class.java)
mPowerManager = context.getSystemService(PowerManager::class.java)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index dca152fbe37a..8d7325118139 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -33,9 +33,9 @@ import android.view.accessibility.AccessibilityManager;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FakeShadowView;
@@ -130,7 +130,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private boolean mLastInSection;
private boolean mFirstInSection;
private boolean mIsBelowSpeedBump;
- private FalsingManager mFalsingManager;
+ private final FalsingManager mFalsingManager;
private float mNormalBackgroundVisibilityAmount;
private float mDimmedBackgroundFadeInAmount = -1;
@@ -164,10 +164,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
super(context, attrs);
mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
+ mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
setClipChildren(false);
setClipToPadding(false);
updateColors();
- mFalsingManager = FalsingManagerFactory.getInstance(context);
mAccessibilityManager = AccessibilityManager.getInstance(mContext);
mDoubleTapHelper = new DoubleTapHelper(this, (active) -> {
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 a8327f63dcf7..6e84089e8ff5 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
@@ -74,7 +74,6 @@ import com.android.internal.widget.CachingIconView;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
@@ -1635,7 +1634,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public ExpandableNotificationRow(Context context, AttributeSet attrs) {
super(context, attrs);
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
mNotificationInflater = new NotificationContentInflater(this);
mMenuRow = new NotificationMenuRow(mContext);
mImageResolver = new NotificationInlineImageResolver(context,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index b654cd6569fe..bec95201e4b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -86,7 +86,6 @@ import com.android.systemui.ExpandHelper;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
@@ -512,7 +511,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
ActivityStarter activityStarter,
StatusBarStateController statusBarStateController,
HeadsUpManagerPhone headsUpManager,
- KeyguardBypassController keyguardBypassController) {
+ KeyguardBypassController keyguardBypassController,
+ FalsingManager falsingManager) {
super(context, attrs, 0, 0);
Resources res = getResources();
@@ -527,6 +527,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mHeadsUpManager.addListener(mRoundnessManager);
mHeadsUpManager.setAnimationStateHandler(this::setHeadsUpGoingAwayAnimationsAllowed);
mKeyguardBypassController = keyguardBypassController;
+ mFalsingManager = falsingManager;
mSectionsManager =
new NotificationSectionsManager(
@@ -551,10 +552,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
mExpandHelper.setEventSource(this);
mExpandHelper.setScrollAdapter(this);
mSwipeHelper = new NotificationSwipeHelper(SwipeHelper.X, mNotificationCallback,
- getContext(), mMenuEventListener);
+ getContext(), mMenuEventListener, mFalsingManager);
mStackScrollAlgorithm = createStackScrollAlgorithm(context);
initView(context);
- mFalsingManager = FalsingManagerFactory.getInstance(context);
mShouldDrawNotificationBackground =
res.getBoolean(R.bool.config_drawNotificationBackground);
mFadeNotificationsOnDismiss =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 4dfc343df283..0968674d31cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -28,6 +28,7 @@ import android.view.View;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.SwipeHelper;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -50,9 +51,11 @@ class NotificationSwipeHelper extends SwipeHelper
private boolean mIsExpanded;
private boolean mPulsing;
- public NotificationSwipeHelper(int swipeDirection, NotificationCallback callback,
- Context context, NotificationMenuRowPlugin.OnMenuEventListener menuListener) {
- super(swipeDirection, callback, context);
+ NotificationSwipeHelper(
+ int swipeDirection, NotificationCallback callback, Context context,
+ NotificationMenuRowPlugin.OnMenuEventListener menuListener,
+ FalsingManager falsingManager) {
+ super(swipeDirection, callback, context, falsingManager);
mMenuListener = menuListener;
mCallback = callback;
mFalsingCheck = new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 4691a31fad21..66b1dd8db123 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -27,7 +27,6 @@ import android.view.ViewConfiguration;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.KeyguardAffordanceView;
@@ -59,7 +58,7 @@ public class KeyguardAffordanceHelper {
private KeyguardAffordanceView mLeftIcon;
private KeyguardAffordanceView mRightIcon;
private Animator mSwipeAnimator;
- private FalsingManager mFalsingManager;
+ private final FalsingManager mFalsingManager;
private int mMinBackgroundRadius;
private boolean mMotionCancelled;
private int mTouchTargetSize;
@@ -80,12 +79,13 @@ public class KeyguardAffordanceHelper {
}
};
- KeyguardAffordanceHelper(Callback callback, Context context) {
+ KeyguardAffordanceHelper(Callback callback, Context context, FalsingManager falsingManager) {
mContext = context;
mCallback = callback;
initIcons();
updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false);
updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false);
+ mFalsingManager = falsingManager;
initDimens();
}
@@ -102,7 +102,6 @@ public class KeyguardAffordanceHelper {
mHintGrowAmount =
mContext.getResources().getDimensionPixelSize(R.dimen.hint_grow_amount_sideways);
mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.4f);
- mFalsingManager = FalsingManagerFactory.getInstance(mContext);
}
private void initIcons() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 7430f7cc2cd1..f64fc81f37ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -61,7 +61,6 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.FalsingManager;
@@ -381,11 +380,12 @@ public class NotificationPanelView extends PanelView implements
NotificationWakeUpCoordinator coordinator,
PulseExpansionHandler pulseExpansionHandler,
DynamicPrivacyController dynamicPrivacyController,
- KeyguardBypassController bypassController) {
+ KeyguardBypassController bypassController,
+ FalsingManager falsingManager) {
super(context, attrs);
setWillNotDraw(!DEBUG);
mInjectionInflationController = injectionInflationController;
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = falsingManager;
mPowerManager = context.getSystemService(PowerManager.class);
mWakeUpCoordinator = coordinator;
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -610,7 +610,7 @@ public class NotificationPanelView extends PanelView implements
}
private void initBottomArea() {
- mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext());
+ mAffordanceHelper = new KeyguardAffordanceHelper(this, getContext(), mFalsingManager);
mKeyguardBottomArea.setAffordanceHelper(mAffordanceHelper);
mKeyguardBottomArea.setStatusBar(mStatusBar);
mKeyguardBottomArea.setUserSetupComplete(mUserSetupComplete);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index a5b221bbad8c..853faabbbc81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -42,7 +42,6 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -110,7 +109,7 @@ public abstract class PanelView extends FrameLayout {
private FlingAnimationUtils mFlingAnimationUtils;
private FlingAnimationUtils mFlingAnimationUtilsClosing;
private FlingAnimationUtils mFlingAnimationUtilsDismissing;
- private FalsingManager mFalsingManager;
+ private final FalsingManager mFalsingManager;
private final VibratorHelper mVibratorHelper;
/**
@@ -213,7 +212,7 @@ public abstract class PanelView extends FrameLayout {
0.5f /* maxLengthSeconds */, 0.2f /* speedUpFactor */, 0.6f /* x2 */,
0.84f /* y2 */);
mBounceInterpolator = new BounceInterpolator();
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
mNotificationsDragEnabled =
getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
mVibratorHelper = Dependency.get(VibratorHelper.class);
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 4392c35ee233..0970f2a7ae67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -147,7 +147,6 @@ import com.android.systemui.assist.AssistManager;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
@@ -695,6 +694,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mRecents = getComponent(Recents.class);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+ mFalsingManager = Dependency.get(FalsingManager.class);
// Connect in to the status bar manager service
mCommandQueue = getComponent(CommandQueue.class);
@@ -770,7 +770,6 @@ public class StatusBar extends SystemUI implements DemoMode,
putComponent(DozeHost.class, mDozeServiceHost);
mScreenPinningRequest = new ScreenPinningRequest(mContext);
- mFalsingManager = FalsingManagerFactory.getInstance(mContext);
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
@@ -1233,7 +1232,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller,
- mKeyguardBypassController);
+ mKeyguardBypassController, mFalsingManager);
mKeyguardIndicationController
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
@@ -2390,7 +2389,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mKeyguardUpdateMonitor.dump(fd, pw, args);
}
- FalsingManagerFactory.getInstance(mContext).dump(pw);
+ Dependency.get(FalsingManager.class).dump(pw);
FalsingLog.dump(pw);
pw.println("SharedPreferences:");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index f810293a34ac..d67818273ef2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -44,6 +44,7 @@ import com.android.systemui.Dependency;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
@@ -211,7 +212,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
BiometricUnlockController biometricUnlockController,
DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController) {
+ KeyguardBypassController bypassController, FalsingManager falsingManager) {
mStatusBar = statusBar;
mContainer = container;
mLockIconContainer = lockIconContainer;
@@ -221,7 +222,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mBiometricUnlockController = biometricUnlockController;
mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
- mExpansionCallback);
+ mExpansionCallback, falsingManager);
mNotificationPanelView = notificationPanelView;
notificationPanelView.setExpansionListener(this);
mBypassController = bypassController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 94054188d769..f1049f005dea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -62,7 +62,6 @@ import com.android.internal.widget.FloatingToolbar;
import com.android.systemui.Dependency;
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
-import com.android.systemui.classifier.FalsingManagerFactory;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.DragDownHelper;
@@ -156,7 +155,7 @@ public class StatusBarWindowView extends FrameLayout {
setMotionEventSplittingEnabled(false);
mTransparentSrcPaint.setColor(0);
mTransparentSrcPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
- mFalsingManager = FalsingManagerFactory.getInstance(context);
+ mFalsingManager = Dependency.get(FalsingManager.class); // TODO: inject into a controller.
mGestureDetector = new GestureDetector(context, mGestureListener);
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
Dependency.get(TunerService.class).addTunable(mTunable,
@@ -290,7 +289,7 @@ public class StatusBarWindowView extends FrameLayout {
ExpandHelper.Callback expandHelperCallback = stackScrollLayout.getExpandHelperCallback();
DragDownHelper.DragDownCallback dragDownCallback = stackScrollLayout.getDragDownCallback();
setDragDownHelper(new DragDownHelper(getContext(), this, expandHelperCallback,
- dragDownCallback));
+ dragDownCallback, mFalsingManager));
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index ede30046d6c3..9b264c4a326e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -26,7 +26,7 @@ import android.view.View;
import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardMessageArea;
import com.android.keyguard.KeyguardSliceView;
-import com.android.systemui.SystemUIFactory;
+import com.android.systemui.SystemUIRootComponent;
import com.android.systemui.qs.QSCarrierGroup;
import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QSPanel;
@@ -62,7 +62,7 @@ public class InjectionInflationController {
private final LayoutInflater.Factory2 mFactory = new InjectionFactory();
@Inject
- public InjectionInflationController(SystemUIFactory.SystemUIRootComponent rootComponent) {
+ public InjectionInflationController(SystemUIRootComponent rootComponent) {
mViewCreator = rootComponent.createViewCreator();
initInjectionMap();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 92173ccbad2e..c1911eef6671 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -53,6 +53,7 @@ import com.android.systemui.ExpandHelper;
import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.EmptyShadeView;
@@ -79,7 +80,6 @@ import com.android.systemui.statusbar.phone.StatusBarTest.TestableNotificationEn
import com.android.systemui.statusbar.policy.ConfigurationController;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -164,7 +164,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mock(ActivityStarterDelegate.class),
mock(StatusBarStateController.class),
mHeadsUpManager,
- mKeyguardBypassController);
+ mKeyguardBypassController,
+ new FalsingManagerFake());
mStackScroller = spy(mStackScrollerInternal);
mStackScroller.setShelf(notificationShelf);
mStackScroller.setStatusBar(mBar);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index b24c3ddc1199..06a2eecd208c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -40,6 +40,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SwipeHelper;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -76,7 +77,8 @@ public class NotificationSwipeHelperTest extends SysuiTestCase {
public void setUp() throws Exception {
mCallback = mock(NotificationSwipeHelper.NotificationCallback.class);
mListener = mock(NotificationMenuRowPlugin.OnMenuEventListener.class);
- mSwipeHelper = spy(new NotificationSwipeHelper(SwipeHelper.X, mCallback, mContext, mListener));
+ mSwipeHelper = spy(new NotificationSwipeHelper(
+ SwipeHelper.X, mCallback, mContext, mListener, new FalsingManagerFake()));
mView = mock(View.class);
mEvent = mock(MotionEvent.class);
mMenuRow = mock(NotificationMenuRowPlugin.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index d14b460d8c63..a96efd7d2fc2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -36,6 +36,7 @@ import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -98,6 +99,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private PanelBar mPanelBar;
@Mock
private KeyguardAffordanceHelper mAffordanceHelper;
+ @Mock
+ private FalsingManager mFalsingManager;
private NotificationPanelView mNotificationPanelView;
@Before
@@ -191,7 +194,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
new InjectionInflationController(
SystemUIFactory.getInstance().getRootComponent()),
coordinator, expansionHandler, mock(DynamicPrivacyController.class),
- bypassController);
+ bypassController,
+ mFalsingManager);
mNotificationStackScroller = mNotificationStackScrollLayout;
mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index da2e8dc90854..63f653b0b303 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -39,8 +39,10 @@ import androidx.test.filters.SmallTest;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -93,7 +95,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
mViewMediatorCallback, mLockPatternUtils);
mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
mNotificationPanelView, mBiometrucUnlockController, mDismissCallbackRegistry,
- mLockIconContainer, mNotificationContainer, mBypassController);
+ mLockIconContainer, mNotificationContainer, mBypassController,
+ new FalsingManagerFake());
mStatusBarKeyguardViewManager.show(null);
}
@@ -232,11 +235,11 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
BiometricUnlockController fingerprintUnlockController,
DismissCallbackRegistry dismissCallbackRegistry,
ViewGroup lockIconContainer, View notificationContainer,
- KeyguardBypassController bypassController) {
+ KeyguardBypassController bypassController, FalsingManager falsingManager) {
super.registerStatusBar(statusBar, container, notificationPanelView,
fingerprintUnlockController, dismissCallbackRegistry, lockIconContainer,
- notificationContainer, bypassController);
+ notificationContainer, bypassController, falsingManager);
mBouncer = StatusBarKeyguardViewManagerTest.this.mBouncer;
}
}
-} \ No newline at end of file
+}
diff --git a/packages/overlays/AccentColorBlackOverlay/Android.mk b/packages/overlays/AccentColorBlackOverlay/Android.mk
index a689defe5b6b..86d873dcab66 100644
--- a/packages/overlays/AccentColorBlackOverlay/Android.mk
+++ b/packages/overlays/AccentColorBlackOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := AccentColorBlack
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := AccentColorBlackOverlay
diff --git a/packages/overlays/AccentColorCinnamonOverlay/Android.mk b/packages/overlays/AccentColorCinnamonOverlay/Android.mk
index 3a6cbe3a182a..a8d3f10cfb9e 100644
--- a/packages/overlays/AccentColorCinnamonOverlay/Android.mk
+++ b/packages/overlays/AccentColorCinnamonOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := AccentColorCinnamon
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := AccentColorCinnamonOverlay
diff --git a/packages/overlays/AccentColorGreenOverlay/Android.mk b/packages/overlays/AccentColorGreenOverlay/Android.mk
index d96dbe17b103..c3aa6a87a2f1 100644
--- a/packages/overlays/AccentColorGreenOverlay/Android.mk
+++ b/packages/overlays/AccentColorGreenOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := AccentColorGreen
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := AccentColorGreenOverlay
diff --git a/packages/overlays/AccentColorOceanOverlay/Android.mk b/packages/overlays/AccentColorOceanOverlay/Android.mk
index cf0c6b310f02..96fbee4bbe74 100644
--- a/packages/overlays/AccentColorOceanOverlay/Android.mk
+++ b/packages/overlays/AccentColorOceanOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := AccentColorOcean
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := AccentColorOceanOverlay
diff --git a/packages/overlays/AccentColorOrchidOverlay/Android.mk b/packages/overlays/AccentColorOrchidOverlay/Android.mk
index fc55befef71e..352e36be8c82 100644
--- a/packages/overlays/AccentColorOrchidOverlay/Android.mk
+++ b/packages/overlays/AccentColorOrchidOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := AccentColorOrchid
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := AccentColorOrchidOverlay
diff --git a/packages/overlays/AccentColorPurpleOverlay/Android.mk b/packages/overlays/AccentColorPurpleOverlay/Android.mk
index 3a28efa2f820..29d5fc9c39b0 100644
--- a/packages/overlays/AccentColorPurpleOverlay/Android.mk
+++ b/packages/overlays/AccentColorPurpleOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := AccentColorPurple
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := AccentColorPurpleOverlay
diff --git a/packages/overlays/AccentColorSpaceOverlay/Android.mk b/packages/overlays/AccentColorSpaceOverlay/Android.mk
index 78cbf7325dee..cbddf6352aaa 100644
--- a/packages/overlays/AccentColorSpaceOverlay/Android.mk
+++ b/packages/overlays/AccentColorSpaceOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := AccentColorSpace
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := AccentColorSpaceOverlay
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.mk
index b73aea320d60..c3e8642084a0 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.mk
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/Android.mk
@@ -6,8 +6,6 @@ LOCAL_RRO_THEME := DisplayCutoutEmulationCorner
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := DisplayCutoutEmulationCornerOverlay
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk
index 8ca2dad25f3f..09d158d3e1f3 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk
@@ -6,8 +6,6 @@ LOCAL_RRO_THEME := DisplayCutoutEmulationDouble
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := DisplayCutoutEmulationDoubleOverlay
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.mk
index 7458cb5db9fb..6a1c09c87e33 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.mk
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/Android.mk
@@ -6,8 +6,6 @@ LOCAL_RRO_THEME := DisplayCutoutEmulationNarrow
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := DisplayCutoutEmulationNarrowOverlay
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.mk
index 1a405e2275c6..cbceff08ae5e 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.mk
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/Android.mk
@@ -6,8 +6,6 @@ LOCAL_RRO_THEME := DisplayCutoutEmulationTall
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := DisplayCutoutEmulationTallOverlay
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.mk
index 3ebc540852c8..82a076a88d9b 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.mk
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/Android.mk
@@ -6,8 +6,6 @@ LOCAL_RRO_THEME := DisplayCutoutEmulationWide
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := DisplayCutoutEmulationWideOverlay
diff --git a/packages/overlays/FontNotoSerifSourceOverlay/Android.mk b/packages/overlays/FontNotoSerifSourceOverlay/Android.mk
index f4eedaf377f9..16a0173a4635 100644
--- a/packages/overlays/FontNotoSerifSourceOverlay/Android.mk
+++ b/packages/overlays/FontNotoSerifSourceOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := FontNotoSerifSource
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := FontNotoSerifSourceOverlay
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/Android.mk b/packages/overlays/IconPackCircularAndroidOverlay/Android.mk
index 8f3baa5962dc..d96185fa34ea 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/Android.mk
+++ b/packages/overlays/IconPackCircularAndroidOverlay/Android.mk
@@ -20,8 +20,6 @@ LOCAL_RRO_THEME := IconPackCircularAndroid
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackCircularAndroidOverlay
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/Android.mk b/packages/overlays/IconPackCircularLauncherOverlay/Android.mk
index 310bdef44b48..d736d7d666a5 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/Android.mk
+++ b/packages/overlays/IconPackCircularLauncherOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackCircularLauncher
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackCircularLauncherOverlay
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/Android.mk b/packages/overlays/IconPackCircularSettingsOverlay/Android.mk
index d06732228b82..ea2da30fba24 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/Android.mk
+++ b/packages/overlays/IconPackCircularSettingsOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackCircularSettings
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackCircularSettingsOverlay
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/Android.mk b/packages/overlays/IconPackCircularSystemUIOverlay/Android.mk
index 5e0dcbee8118..9045e8e58e6a 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/Android.mk
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackCircularSystemUI
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackCircularSystemUIOverlay
diff --git a/packages/overlays/IconPackCircularThemePickerOverlay/Android.mk b/packages/overlays/IconPackCircularThemePickerOverlay/Android.mk
index 412c26fc3da4..c2d472d541b8 100644
--- a/packages/overlays/IconPackCircularThemePickerOverlay/Android.mk
+++ b/packages/overlays/IconPackCircularThemePickerOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackCircularThemePicker
LOCAL_CERTIFICATE := platform
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackCircularThemePickerOverlay
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/Android.mk b/packages/overlays/IconPackFilledAndroidOverlay/Android.mk
index 3036f7df9f1e..78db7658aee1 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/Android.mk
+++ b/packages/overlays/IconPackFilledAndroidOverlay/Android.mk
@@ -20,8 +20,6 @@ LOCAL_RRO_THEME := IconPackFilledAndroid
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackFilledAndroidOverlay
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/Android.mk b/packages/overlays/IconPackFilledLauncherOverlay/Android.mk
index 2460fa4675ff..16b8f526d2a2 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/Android.mk
+++ b/packages/overlays/IconPackFilledLauncherOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackFilledLauncher
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackFilledLauncherOverlay
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/Android.mk b/packages/overlays/IconPackFilledSettingsOverlay/Android.mk
index 3cc071d732e1..d4e90007e956 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/Android.mk
+++ b/packages/overlays/IconPackFilledSettingsOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackFilledSettings
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackFilledSettingsOverlay
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/Android.mk b/packages/overlays/IconPackFilledSystemUIOverlay/Android.mk
index f0276927b8e2..35e157a268d5 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/Android.mk
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackFilledSystemUI
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackFilledSystemUIOverlay
diff --git a/packages/overlays/IconPackFilledThemePickerOverlay/Android.mk b/packages/overlays/IconPackFilledThemePickerOverlay/Android.mk
index 6d15603663b5..835d35e63efe 100644
--- a/packages/overlays/IconPackFilledThemePickerOverlay/Android.mk
+++ b/packages/overlays/IconPackFilledThemePickerOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackFilledThemePicker
LOCAL_CERTIFICATE := platform
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackFilledThemePickerOverlay
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/Android.mk b/packages/overlays/IconPackRoundedAndroidOverlay/Android.mk
index c6ad4ac04092..70d6fc44444c 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/Android.mk
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/Android.mk
@@ -20,8 +20,6 @@ LOCAL_RRO_THEME := IconPackRoundedAndroid
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackRoundedAndroidOverlay
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/Android.mk b/packages/overlays/IconPackRoundedLauncherOverlay/Android.mk
index 713e2819bb65..63de27fb18e0 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/Android.mk
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackRoundedLauncher
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackRoundedLauncherOverlay
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/Android.mk b/packages/overlays/IconPackRoundedSettingsOverlay/Android.mk
index 6c775190f548..c59bf7da10aa 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/Android.mk
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackRoundedSettings
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackRoundedSettingsOverlay
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/Android.mk b/packages/overlays/IconPackRoundedSystemUIOverlay/Android.mk
index 4e21b41828c8..3b68c9209634 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/Android.mk
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackRoundedSystemUI
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackRoundedSystemUIOverlay
diff --git a/packages/overlays/IconPackRoundedThemePickerOverlay/Android.mk b/packages/overlays/IconPackRoundedThemePickerOverlay/Android.mk
index ae48186e05ee..e31aa4a40baf 100644
--- a/packages/overlays/IconPackRoundedThemePickerOverlay/Android.mk
+++ b/packages/overlays/IconPackRoundedThemePickerOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconPackRoundedThemePicker
LOCAL_CERTIFICATE := platform
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconPackRoundedThemePickerOverlay
diff --git a/packages/overlays/IconShapeRoundedRectOverlay/Android.mk b/packages/overlays/IconShapeRoundedRectOverlay/Android.mk
index 21cd011ef83c..c6f00d1b5584 100644
--- a/packages/overlays/IconShapeRoundedRectOverlay/Android.mk
+++ b/packages/overlays/IconShapeRoundedRectOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconShapeRoundedRect
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconShapeRoundedRectOverlay
diff --git a/packages/overlays/IconShapeSquareOverlay/Android.mk b/packages/overlays/IconShapeSquareOverlay/Android.mk
index c8728838303c..602072126468 100644
--- a/packages/overlays/IconShapeSquareOverlay/Android.mk
+++ b/packages/overlays/IconShapeSquareOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconShapeSquare
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconShapeSquareOverlay
diff --git a/packages/overlays/IconShapeSquircleOverlay/Android.mk b/packages/overlays/IconShapeSquircleOverlay/Android.mk
index fa5fe6906dce..04409a544edf 100644
--- a/packages/overlays/IconShapeSquircleOverlay/Android.mk
+++ b/packages/overlays/IconShapeSquircleOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconShapeSquircle
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconShapeSquircleOverlay
diff --git a/packages/overlays/IconShapeTeardropOverlay/Android.mk b/packages/overlays/IconShapeTeardropOverlay/Android.mk
index d5f01f39965b..b127deabda4c 100644
--- a/packages/overlays/IconShapeTeardropOverlay/Android.mk
+++ b/packages/overlays/IconShapeTeardropOverlay/Android.mk
@@ -21,8 +21,6 @@ LOCAL_RRO_THEME := IconShapeTeardrop
LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := IconShapeTeardropOverlay
diff --git a/packages/overlays/NavigationBarMode2ButtonOverlay/Android.mk b/packages/overlays/NavigationBarMode2ButtonOverlay/Android.mk
index be86ef2d3ff4..30477cceebcb 100644
--- a/packages/overlays/NavigationBarMode2ButtonOverlay/Android.mk
+++ b/packages/overlays/NavigationBarMode2ButtonOverlay/Android.mk
@@ -20,8 +20,6 @@ include $(CLEAR_VARS)
LOCAL_RRO_THEME := NavigationBarMode2Button
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := NavigationBarMode2ButtonOverlay
diff --git a/packages/overlays/NavigationBarMode3ButtonOverlay/Android.mk b/packages/overlays/NavigationBarMode3ButtonOverlay/Android.mk
index f44a362b266d..3d5a5a578c70 100644
--- a/packages/overlays/NavigationBarMode3ButtonOverlay/Android.mk
+++ b/packages/overlays/NavigationBarMode3ButtonOverlay/Android.mk
@@ -20,8 +20,6 @@ include $(CLEAR_VARS)
LOCAL_RRO_THEME := NavigationBarMode3Button
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := NavigationBarMode3ButtonOverlay
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/Android.mk b/packages/overlays/NavigationBarModeGesturalOverlay/Android.mk
index 02e2074accb7..3b7605a95a24 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/Android.mk
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/Android.mk
@@ -20,8 +20,6 @@ include $(CLEAR_VARS)
LOCAL_RRO_THEME := NavigationBarModeGestural
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := NavigationBarModeGesturalOverlay
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.mk b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.mk
index 9a38efa2f95d..1a1388eebd31 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.mk
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.mk
@@ -20,8 +20,6 @@ include $(CLEAR_VARS)
LOCAL_RRO_THEME := NavigationBarModeGesturalExtraWideBack
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := NavigationBarModeGesturalOverlayExtraWideBack
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.mk b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.mk
index 1d004c83faef..868998662aaa 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.mk
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.mk
@@ -20,8 +20,6 @@ include $(CLEAR_VARS)
LOCAL_RRO_THEME := NavigationBarModeGesturalNarrowBack
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := NavigationBarModeGesturalOverlayNarrowBack
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.mk b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.mk
index 0ab463f8e49f..2723add528be 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.mk
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.mk
@@ -20,8 +20,6 @@ include $(CLEAR_VARS)
LOCAL_RRO_THEME := NavigationBarModeGesturalWideBack
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_PACKAGE_NAME := NavigationBarModeGesturalOverlayWideBack
diff --git a/services/autofill/java/com/android/server/autofill/RemoteFillService.java b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
index 44f19ffe1904..5a9320f61b38 100644
--- a/services/autofill/java/com/android/server/autofill/RemoteFillService.java
+++ b/services/autofill/java/com/android/server/autofill/RemoteFillService.java
@@ -187,10 +187,9 @@ final class RemoteFillService extends ServiceConnector.Impl<IAutoFillService> {
if (err instanceof TimeoutException) {
dispatchCancellationSignal(cancellationSink.get());
mCallbacks.onFillRequestTimeout(request.getId());
+ } else if (err instanceof CancellationException) {
+ dispatchCancellationSignal(cancellationSink.get());
} else {
- if (err instanceof CancellationException) {
- dispatchCancellationSignal(cancellationSink.get());
- }
mCallbacks.onFillRequestFailure(request.getId(), err.getMessage());
}
}
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index b6fa1570cdb0..c0f10a3c86e1 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -37,6 +37,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.service.carrier.CarrierMessagingService;
import android.telephony.SmsManager;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Slog;
@@ -331,7 +332,7 @@ public class MmsServiceBroker extends SystemService {
@Override
public void sendMessage(int subId, String callingPkg, Uri contentUri,
String locationUrl, Bundle configOverrides, PendingIntent sentIntent)
- throws RemoteException {
+ throws RemoteException {
Slog.d(TAG, "sendMessage() by " + callingPkg);
mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
@@ -341,7 +342,8 @@ public class MmsServiceBroker extends SystemService {
}
contentUri = adjustUriForUserAndGrantPermission(contentUri,
CarrierMessagingService.SERVICE_INTERFACE,
- Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ subId);
getServiceGuarded().sendMessage(subId, callingPkg, contentUri, locationUrl,
configOverrides, sentIntent);
}
@@ -360,7 +362,8 @@ public class MmsServiceBroker extends SystemService {
}
contentUri = adjustUriForUserAndGrantPermission(contentUri,
CarrierMessagingService.SERVICE_INTERFACE,
- Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+ subId);
getServiceGuarded().downloadMessage(subId, callingPkg, locationUrl, contentUri,
configOverrides, downloadedIntent);
@@ -388,7 +391,7 @@ public class MmsServiceBroker extends SystemService {
@Override
public Uri importMultimediaMessage(String callingPkg, Uri contentUri,
String messageId, long timestampSecs, boolean seen, boolean read)
- throws RemoteException {
+ throws RemoteException {
if (getAppOpsManager().noteOp(AppOpsManager.OP_WRITE_SMS, Binder.getCallingUid(),
callingPkg) != AppOpsManager.MODE_ALLOWED) {
// Silently fail AppOps failure due to not being the default SMS app
@@ -496,12 +499,12 @@ public class MmsServiceBroker extends SystemService {
* even if the caller is not in the primary user.
*
* @param contentUri The Uri to adjust
- * @param action The intent action used to find the associated carrier app
+ * @param action The intent action used to find the associated carrier app
* @param permission The permission to add
* @return The adjusted Uri containing the calling userId.
*/
private Uri adjustUriForUserAndGrantPermission(Uri contentUri, String action,
- int permission) {
+ int permission, int subId) {
final Intent grantIntent = new Intent();
grantIntent.setData(contentUri);
grantIntent.setFlags(permission);
@@ -521,9 +524,10 @@ public class MmsServiceBroker extends SystemService {
// Grant permission for the carrier app.
Intent intent = new Intent(action);
TelephonyManager telephonyManager =
- (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- List<String> carrierPackages = telephonyManager.getCarrierPackageNamesForIntent(
- intent);
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ List<String> carrierPackages =
+ telephonyManager.getCarrierPackageNamesForIntentAndPhone(
+ intent, SubscriptionManager.getPhoneId(subId));
if (carrierPackages != null && carrierPackages.size() == 1) {
LocalServices.getService(UriGrantsManagerInternal.class)
.grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index e66e596d5038..f7e825eecc12 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1027,7 +1027,12 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log(str);
}
mLocalLog.log(str);
- if (validatePhoneId(phoneId)) {
+ // for service state updates, don't notify clients when subId is invalid. This prevents
+ // us from sending incorrect notifications like b/133140128
+ // In the future, we can remove this logic for every notification here and add a
+ // callback so listeners know when their PhoneStateListener's subId becomes invalid, but
+ // for now we use the simplest fix.
+ if (validatePhoneId(phoneId) && SubscriptionManager.isValidSubscriptionId(subId)) {
mServiceState[phoneId] = state;
for (Record r : mRecords) {
@@ -1059,7 +1064,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
} else {
- log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId);
+ log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId
+ + " or subId=" + subId);
}
handleRemoveListLocked();
}
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 19ad32e202fe..a502ff24e5b8 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -103,6 +103,7 @@ public class Watchdog extends Thread {
public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList(
"android.hardware.audio@2.0::IDevicesFactory",
"android.hardware.audio@4.0::IDevicesFactory",
+ "android.hardware.audio@5.0::IDevicesFactory",
"android.hardware.biometrics.face@1.0::IBiometricsFace",
"android.hardware.bluetooth@1.0::IBluetoothHci",
"android.hardware.camera.provider@2.4::ICameraProvider",
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 8ef5b07531ce..a53786572f6c 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2543,15 +2543,11 @@ public class AudioService extends IAudioService.Stub
mVolumeController.postVolumeChanged(streamType, flags);
}
- // If Hdmi-CEC system audio mode is on, we show volume bar only when TV
- // receives volume notification from Audio Receiver.
+ // If Hdmi-CEC system audio mode is on and we are a TV panel, never show volume bar.
private int updateFlagsForTvPlatform(int flags) {
synchronized (mHdmiClientLock) {
- if (mHdmiTvClient != null) {
- if (mHdmiSystemAudioSupported &&
- ((flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) == 0)) {
- flags &= ~AudioManager.FLAG_SHOW_UI;
- }
+ if (mHdmiTvClient != null && mHdmiSystemAudioSupported) {
+ flags &= ~AudioManager.FLAG_SHOW_UI;
}
}
return flags;
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 72bac7494804..a38abdc1bed0 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -63,6 +63,7 @@ import com.android.server.SystemServerInitThreadPool;
import com.android.server.biometrics.AuthenticationClient;
import com.android.server.biometrics.BiometricServiceBase;
import com.android.server.biometrics.BiometricUtils;
+import com.android.server.biometrics.ClientMonitor;
import com.android.server.biometrics.Constants;
import com.android.server.biometrics.EnumerateClient;
import com.android.server.biometrics.RemovalClient;
@@ -342,7 +343,16 @@ public class FaceService extends BiometricServiceBase {
@Override // Binder call
public int revokeChallenge(IBinder token) {
checkPermission(MANAGE_BIOMETRIC);
- return startRevokeChallenge(token);
+ // TODO(b/137106905): Schedule binder calls in FaceService to avoid deadlocks.
+ if (getCurrentClient() == null) {
+ // if we aren't handling any other HIDL calls (mCurrentClient == null), revoke the
+ // challenge right away.
+ return startRevokeChallenge(token);
+ } else {
+ // postpone revoking the challenge until we finish processing the current HIDL call.
+ mRevokeChallengePending = true;
+ return Status.OK;
+ }
}
@Override // Binder call
@@ -812,6 +822,7 @@ public class FaceService extends BiometricServiceBase {
@GuardedBy("this")
private IBiometricsFace mDaemon;
private UsageStats mUsageStats;
+ private boolean mRevokeChallengePending = false;
// One of the AuthenticationClient constants
private int mCurrentUserLockoutMode;
@@ -1041,6 +1052,15 @@ public class FaceService extends BiometricServiceBase {
}
@Override
+ protected void removeClient(ClientMonitor client) {
+ super.removeClient(client);
+ if (mRevokeChallengePending) {
+ startRevokeChallenge(null);
+ mRevokeChallengePending = false;
+ }
+ }
+
+ @Override
public void onStart() {
super.onStart();
publishBinderService(Context.FACE_SERVICE, new FaceServiceWrapper());
@@ -1251,7 +1271,11 @@ public class FaceService extends BiometricServiceBase {
return 0;
}
try {
- return daemon.revokeChallenge();
+ final int res = daemon.revokeChallenge();
+ if (res != Status.OK) {
+ Slog.e(TAG, "revokeChallenge returned " + res);
+ }
+ return res;
} catch (RemoteException e) {
Slog.e(TAG, "startRevokeChallenge failed", e);
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 49b42df34fa5..09e93759196f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -17,7 +17,6 @@ package com.android.server.inputmethod;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.inputmethod.InputMethodSystemProperty.PER_PROFILE_IME_ENABLED;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -1036,9 +1035,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// sender userId can be a real user ID or USER_ALL.
final int senderUserId = pendingResult.getSendingUserId();
if (senderUserId != UserHandle.USER_ALL) {
- final int resolvedUserId = PER_PROFILE_IME_ENABLED
- ? senderUserId : mUserManagerInternal.getProfileParentId(senderUserId);
- if (resolvedUserId != mSettings.getCurrentUserId()) {
+ if (senderUserId != mSettings.getCurrentUserId()) {
// A background user is trying to hide the dialog. Ignore.
return;
}
@@ -1662,9 +1659,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (userId == mSettings.getCurrentUserId()) {
return true;
}
- if (!PER_PROFILE_IME_ENABLED && mSettings.isCurrentProfile(userId)) {
- return true;
- }
// Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
// foreground user, not for the user of that process. Accordingly InputMethodManagerService
@@ -3005,7 +2999,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return InputBindResult.INVALID_USER;
}
- if (PER_PROFILE_IME_ENABLED && userId != mSettings.getCurrentUserId()) {
+ if (userId != mSettings.getCurrentUserId()) {
switchUserLocked(userId);
}
// Master feature flag that overrides other conditions and forces IME preRendering.
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index b5e19aeed0c5..77e2fbd25670 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -35,13 +35,11 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.IntArray;
import android.util.Pair;
import android.util.Printer;
import android.util.Slog;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
-import android.view.inputmethod.InputMethodSystemProperty;
import android.view.textservice.SpellCheckerInfo;
import com.android.internal.annotations.GuardedBy;
@@ -1303,9 +1301,6 @@ final class InputMethodUtils {
* Converts a user ID, which can be a pseudo user ID such as {@link UserHandle#USER_ALL} to a
* list of real user IDs.
*
- * <p>This method also converts profile user ID to profile parent user ID unless
- * {@link InputMethodSystemProperty#PER_PROFILE_IME_ENABLED} is {@code true}.</p>
- *
* @param userIdToBeResolved A user ID. Two pseudo user ID {@link UserHandle#USER_CURRENT} and
* {@link UserHandle#USER_ALL} are also supported
* @param currentUserId A real user ID, which will be used when {@link UserHandle#USER_CURRENT}
@@ -1320,17 +1315,7 @@ final class InputMethodUtils {
LocalServices.getService(UserManagerInternal.class);
if (userIdToBeResolved == UserHandle.USER_ALL) {
- if (InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
- return userManagerInternal.getUserIds();
- }
- final IntArray result = new IntArray();
- for (int userId : userManagerInternal.getUserIds()) {
- final int parentUserId = userManagerInternal.getProfileParentId(userId);
- if (result.indexOf(parentUserId) < 0) {
- result.add(parentUserId);
- }
- }
- return result.toArray();
+ return userManagerInternal.getUserIds();
}
final int sourceUserId;
@@ -1353,8 +1338,6 @@ final class InputMethodUtils {
}
return new int[]{};
}
- final int resolvedUserId = InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
- ? sourceUserId : userManagerInternal.getProfileParentId(sourceUserId);
- return new int[]{resolvedUserId};
+ return new int[]{sourceUserId};
}
}
diff --git a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
index 766d8ca8a47c..3b24f46d4714 100644
--- a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
+++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistShellCommand.java
@@ -17,8 +17,6 @@
package com.android.server.net.watchlist;
import android.content.Context;
-import android.content.Intent;
-import android.net.NetworkWatchlistManager;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -26,7 +24,6 @@ import android.os.ShellCommand;
import android.provider.Settings;
import java.io.FileInputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
@@ -74,10 +71,12 @@ class NetworkWatchlistShellCommand extends ShellCommand {
try {
final String configXmlPath = getNextArgRequired();
final ParcelFileDescriptor pfd = openFileForSystem(configXmlPath, "r");
- if (pfd != null) {
- final InputStream fileStream = new FileInputStream(pfd.getFileDescriptor());
- WatchlistConfig.getInstance().setTestMode(fileStream);
+ if (pfd == null) {
+ pw.println("Error: can't open input file " + configXmlPath);
+ return -1;
}
+ final InputStream fileStream = new FileInputStream(pfd.getFileDescriptor());
+ WatchlistConfig.getInstance().setTestMode(fileStream);
pw.println("Success!");
} catch (Exception ex) {
pw.println("Error: " + ex.toString());
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f032fa6959ef..976931c5e86b 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -207,6 +207,7 @@ import android.util.Xml;
import android.util.proto.ProtoOutputStream;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import android.widget.RemoteViews;
import android.widget.Toast;
import com.android.internal.R;
@@ -463,6 +464,9 @@ public class NotificationManagerService extends SystemService {
private boolean mIsAutomotive;
private boolean mNotificationEffectsEnabledForAutomotive;
+ private int mWarnRemoteViewsSizeBytes;
+ private int mStripRemoteViewsSizeBytes;
+
private MetricsLogger mMetricsLogger;
private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
@@ -1723,6 +1727,11 @@ public class NotificationManagerService extends SystemService {
mZenModeHelper.setPriorityOnlyDndExemptPackages(getContext().getResources().getStringArray(
com.android.internal.R.array.config_priorityOnlyDndExemptPackages));
+
+ mWarnRemoteViewsSizeBytes = getContext().getResources().getInteger(
+ com.android.internal.R.integer.config_notificationWarnRemoteViewSizeBytes);
+ mStripRemoteViewsSizeBytes = getContext().getResources().getInteger(
+ com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
}
@Override
@@ -4712,7 +4721,7 @@ public class NotificationManagerService extends SystemService {
// Fix the notification as best we can.
try {
- fixNotification(notification, pkg, userId);
+ fixNotification(notification, pkg, tag, id, userId);
} catch (NameNotFoundException e) {
Slog.e(TAG, "Cannot create a context for sending app", e);
@@ -4817,8 +4826,8 @@ public class NotificationManagerService extends SystemService {
}
@VisibleForTesting
- protected void fixNotification(Notification notification, String pkg, int userId)
- throws NameNotFoundException {
+ protected void fixNotification(Notification notification, String pkg, String tag, int id,
+ int userId) throws NameNotFoundException {
final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
(userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
@@ -4841,6 +4850,50 @@ public class NotificationManagerService extends SystemService {
": Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission");
}
}
+
+ // Remote views? Are they too big?
+ checkRemoteViews(pkg, tag, id, notification);
+ }
+
+ private void checkRemoteViews(String pkg, String tag, int id, Notification notification) {
+ if (removeRemoteView(pkg, tag, id, notification.contentView)) {
+ notification.contentView = null;
+ }
+ if (removeRemoteView(pkg, tag, id, notification.bigContentView)) {
+ notification.bigContentView = null;
+ }
+ if (removeRemoteView(pkg, tag, id, notification.headsUpContentView)) {
+ notification.headsUpContentView = null;
+ }
+ if (notification.publicVersion != null) {
+ if (removeRemoteView(pkg, tag, id, notification.publicVersion.contentView)) {
+ notification.publicVersion.contentView = null;
+ }
+ if (removeRemoteView(pkg, tag, id, notification.publicVersion.bigContentView)) {
+ notification.publicVersion.bigContentView = null;
+ }
+ if (removeRemoteView(pkg, tag, id, notification.publicVersion.headsUpContentView)) {
+ notification.publicVersion.headsUpContentView = null;
+ }
+ }
+ }
+
+ private boolean removeRemoteView(String pkg, String tag, int id, RemoteViews contentView) {
+ if (contentView == null) {
+ return false;
+ }
+ final int contentViewSize = contentView.estimateMemoryUsage();
+ if (contentViewSize > mWarnRemoteViewsSizeBytes
+ && contentViewSize < mStripRemoteViewsSizeBytes) {
+ Slog.w(TAG, "RemoteViews too large on tag: " + tag + " id: " + id
+ + " this might be stripped in a future release");
+ }
+ if (contentViewSize >= mStripRemoteViewsSizeBytes) {
+ mUsageStats.registerImageRemoved(pkg);
+ Slog.w(TAG, "Removed too large RemoteViews on tag: " + tag + " id: " + id);
+ return true;
+ }
+ return false;
}
/**
@@ -5069,23 +5122,25 @@ public class NotificationManagerService extends SystemService {
}
}
- // snoozed apps
- if (mSnoozeHelper.isSnoozed(userId, pkg, r.getKey())) {
- MetricsLogger.action(r.getLogMaker()
- .setType(MetricsProto.MetricsEvent.TYPE_UPDATE)
- .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED));
- if (DBG) {
- Slog.d(TAG, "Ignored enqueue for snoozed notification " + r.getKey());
+ synchronized (mNotificationLock) {
+ // snoozed apps
+ if (mSnoozeHelper.isSnoozed(userId, pkg, r.getKey())) {
+ MetricsLogger.action(r.getLogMaker()
+ .setType(MetricsProto.MetricsEvent.TYPE_UPDATE)
+ .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED));
+ if (DBG) {
+ Slog.d(TAG, "Ignored enqueue for snoozed notification " + r.getKey());
+ }
+ mSnoozeHelper.update(userId, r);
+ handleSavePolicyFile();
+ return false;
}
- mSnoozeHelper.update(userId, r);
- handleSavePolicyFile();
- return false;
- }
- // blocked apps
- if (isBlocked(r, mUsageStats)) {
- return false;
+ // blocked apps
+ if (isBlocked(r, mUsageStats)) {
+ return false;
+ }
}
return true;
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 6748f80b4f77..a12607351775 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -34,11 +34,8 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
-import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.media.AudioSystem;
import android.metrics.LogMaker;
@@ -453,16 +450,11 @@ public final class NotificationRecord {
void dump(PrintWriter pw, String prefix, Context baseContext, boolean redact) {
final Notification notification = sbn.getNotification();
- final Icon icon = notification.getSmallIcon();
- String iconStr = String.valueOf(icon);
- if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) {
- iconStr += " / " + idDebugString(baseContext, icon.getResPackage(), icon.getResId());
- }
pw.println(prefix + this);
prefix = prefix + " ";
pw.println(prefix + "uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
pw.println(prefix + "opPkg=" + sbn.getOpPkg());
- pw.println(prefix + "icon=" + iconStr);
+ pw.println(prefix + "icon=" + notification.getSmallIcon());
pw.println(prefix + "flags=0x" + Integer.toHexString(notification.flags));
pw.println(prefix + "pri=" + notification.priority);
pw.println(prefix + "key=" + sbn.getKey());
@@ -592,28 +584,6 @@ public final class NotificationRecord {
pw.println(prefix + "mAdjustments=" + mAdjustments);
}
-
- static String idDebugString(Context baseContext, String packageName, int id) {
- Context c;
-
- if (packageName != null) {
- try {
- c = baseContext.createPackageContext(packageName, 0);
- } catch (NameNotFoundException e) {
- c = baseContext;
- }
- } else {
- c = baseContext;
- }
-
- Resources r = c.getResources();
- try {
- return r.getResourceName(id);
- } catch (Resources.NotFoundException e) {
- return "<name unknown>";
- }
- }
-
@Override
public final String toString() {
return String.format(
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index dd393b8846f0..fe3d0eb3e469 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -41,7 +41,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import java.io.PrintWriter;
-import java.lang.Math;
import java.util.ArrayDeque;
import java.util.Calendar;
import java.util.GregorianCalendar;
@@ -263,6 +262,17 @@ public class NotificationUsageStats {
}
}
+ /**
+ * Call this when RemoteViews object has been removed from a notification because the images
+ * it contains are too big (even after rescaling).
+ */
+ public synchronized void registerImageRemoved(String packageName) {
+ AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(packageName);
+ for (AggregatedStats stats : aggregatedStatsArray) {
+ stats.numImagesRemoved++;
+ }
+ }
+
// Locked by this.
private AggregatedStats[] getAggregatedStatsLocked(NotificationRecord record) {
return getAggregatedStatsLocked(record.sbn.getPackageName());
@@ -405,6 +415,7 @@ public class NotificationUsageStats {
public int numAlertViolations;
public int numQuotaViolations;
public long mLastAccessTime;
+ public int numImagesRemoved;
public AggregatedStats(Context context, String key) {
this.key = key;
@@ -529,6 +540,7 @@ public class NotificationUsageStats {
maybeCount("note_over_rate", (numRateViolations - previous.numRateViolations));
maybeCount("note_over_alert_rate", (numAlertViolations - previous.numAlertViolations));
maybeCount("note_over_quota", (numQuotaViolations - previous.numQuotaViolations));
+ maybeCount("note_images_removed", (numImagesRemoved - previous.numImagesRemoved));
noisyImportance.maybeCount(previous.noisyImportance);
quietImportance.maybeCount(previous.quietImportance);
finalImportance.maybeCount(previous.finalImportance);
@@ -562,6 +574,7 @@ public class NotificationUsageStats {
previous.numRateViolations = numRateViolations;
previous.numAlertViolations = numAlertViolations;
previous.numQuotaViolations = numQuotaViolations;
+ previous.numImagesRemoved = numImagesRemoved;
noisyImportance.update(previous.noisyImportance);
quietImportance.update(previous.quietImportance);
finalImportance.update(previous.finalImportance);
@@ -667,6 +680,8 @@ public class NotificationUsageStats {
output.append("numAlertViolations=").append(numAlertViolations).append("\n");
output.append(indentPlusTwo);
output.append("numQuotaViolations=").append(numQuotaViolations).append("\n");
+ output.append(indentPlusTwo);
+ output.append("numImagesRemoved=").append(numImagesRemoved).append("\n");
output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n");
output.append(indentPlusTwo).append(quietImportance.toString()).append("\n");
output.append(indentPlusTwo).append(finalImportance.toString()).append("\n");
@@ -709,6 +724,7 @@ public class NotificationUsageStats {
maybePut(dump, "numQuotaLViolations", numQuotaViolations);
maybePut(dump, "notificationEnqueueRate", getEnqueueRate());
maybePut(dump, "numAlertViolations", numAlertViolations);
+ maybePut(dump, "numImagesRemoved", numImagesRemoved);
noisyImportance.maybePut(dump, previous.noisyImportance);
quietImportance.maybePut(dump, previous.quietImportance);
finalImportance.maybePut(dump, previous.finalImportance);
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 03224d1939b9..2301e3fb093d 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.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.s
+ * limitations under the License.
*/
package com.android.server.pm;
@@ -29,12 +29,11 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageParserException;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
import android.sysprop.ApexProperties;
import android.util.Slog;
@@ -55,103 +54,33 @@ import java.util.stream.Collectors;
* ApexManager class handles communications with the apex service to perform operation and queries,
* as well as providing caching to avoid unnecessary calls to the service.
*/
-class ApexManager {
- static final String TAG = "ApexManager";
- private final IApexService mApexService;
- private final Context mContext;
- private final Object mLock = new Object();
- /**
- * A map from {@code APEX packageName} to the {@Link PackageInfo} generated from the {@code
- * AndroidManifest.xml}
- *
- * <p>Note that key of this map is {@code packageName} field of the corresponding {@code
- * AndroidManifest.xml}.
- */
- @GuardedBy("mLock")
- private List<PackageInfo> mAllPackagesCache;
-
- ApexManager(Context context) {
- mContext = context;
- if (!isApexSupported()) {
- mApexService = null;
- return;
- }
- try {
- mApexService = IApexService.Stub.asInterface(
- ServiceManager.getServiceOrThrow("apexservice"));
- } catch (ServiceNotFoundException e) {
- throw new IllegalStateException("Required service apexservice not available");
- }
- }
+abstract class ApexManager {
+
+ private static final String TAG = "ApexManager";
static final int MATCH_ACTIVE_PACKAGE = 1 << 0;
static final int MATCH_FACTORY_PACKAGE = 1 << 1;
- @IntDef(
- flag = true,
- prefix = { "MATCH_"},
- value = {MATCH_ACTIVE_PACKAGE, MATCH_FACTORY_PACKAGE})
- @Retention(RetentionPolicy.SOURCE)
- @interface PackageInfoFlags{}
-
- void systemReady() {
- if (!isApexSupported()) return;
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- onBootCompleted();
- mContext.unregisterReceiver(this);
- }
- }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
- }
- private void populateAllPackagesCacheIfNeeded() {
- synchronized (mLock) {
- if (mAllPackagesCache != null) {
- return;
- }
+ /**
+ * Returns an instance of either {@link ApexManagerImpl} or {@link ApexManagerNoOp} depending
+ * on whenever this device supports APEX, i.e. {@link ApexProperties#updatable()} evaluates to
+ * {@code true}.
+ */
+ static ApexManager create(Context systemContext) {
+ if (ApexProperties.updatable().orElse(false)) {
try {
- mAllPackagesCache = new ArrayList<>();
- HashSet<String> activePackagesSet = new HashSet<>();
- HashSet<String> factoryPackagesSet = new HashSet<>();
- final ApexInfo[] allPkgs = mApexService.getAllPackages();
- for (ApexInfo ai : allPkgs) {
- // If the device is using flattened APEX, don't report any APEX
- // packages since they won't be managed or updated by PackageManager.
- if ((new File(ai.modulePath)).isDirectory()) {
- break;
- }
- try {
- final PackageInfo pkg = PackageParser.generatePackageInfoFromApex(
- ai, PackageManager.GET_META_DATA
- | PackageManager.GET_SIGNING_CERTIFICATES);
- mAllPackagesCache.add(pkg);
- if (ai.isActive) {
- if (activePackagesSet.contains(pkg.packageName)) {
- throw new IllegalStateException(
- "Two active packages have the same name: "
- + pkg.packageName);
- }
- activePackagesSet.add(pkg.packageName);
- }
- if (ai.isFactory) {
- if (factoryPackagesSet.contains(pkg.packageName)) {
- throw new IllegalStateException(
- "Two factory packages have the same name: "
- + pkg.packageName);
- }
- factoryPackagesSet.add(pkg.packageName);
- }
- } catch (PackageParserException pe) {
- throw new IllegalStateException("Unable to parse: " + ai, pe);
- }
- }
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
- throw new RuntimeException(re);
+ return new ApexManagerImpl(systemContext, IApexService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow("apexservice")));
+ } catch (ServiceManager.ServiceNotFoundException e) {
+ throw new IllegalStateException("Required service apexservice not available");
}
+ } else {
+ return new ApexManagerNoOp();
}
}
+ abstract void systemReady();
+
/**
* Retrieves information about an APEX package.
*
@@ -164,22 +93,8 @@ class ApexManager {
* @return a PackageInfo object with the information about the package, or null if the package
* is not found.
*/
- @Nullable PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) {
- if (!isApexSupported()) return null;
- populateAllPackagesCacheIfNeeded();
- boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0;
- boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0;
- for (PackageInfo packageInfo: mAllPackagesCache) {
- if (!packageInfo.packageName.equals(packageName)) {
- continue;
- }
- if ((!matchActive || isActive(packageInfo))
- && (!matchFactory || isFactory(packageInfo))) {
- return packageInfo;
- }
- }
- return null;
- }
+ @Nullable
+ abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags);
/**
* Retrieves information about all active APEX packages.
@@ -187,14 +102,7 @@ class ApexManager {
* @return a List of PackageInfo object, each one containing information about a different
* active package.
*/
- List<PackageInfo> getActivePackages() {
- if (!isApexSupported()) return Collections.emptyList();
- populateAllPackagesCacheIfNeeded();
- return mAllPackagesCache
- .stream()
- .filter(item -> isActive(item))
- .collect(Collectors.toList());
- }
+ abstract List<PackageInfo> getActivePackages();
/**
* Retrieves information about all active pre-installed APEX packages.
@@ -202,14 +110,7 @@ class ApexManager {
* @return a List of PackageInfo object, each one containing information about a different
* active pre-installed package.
*/
- List<PackageInfo> getFactoryPackages() {
- if (!isApexSupported()) return Collections.emptyList();
- populateAllPackagesCacheIfNeeded();
- return mAllPackagesCache
- .stream()
- .filter(item -> isFactory(item))
- .collect(Collectors.toList());
- }
+ abstract List<PackageInfo> getFactoryPackages();
/**
* Retrieves information about all inactive APEX packages.
@@ -217,14 +118,7 @@ class ApexManager {
* @return a List of PackageInfo object, each one containing information about a different
* inactive package.
*/
- List<PackageInfo> getInactivePackages() {
- if (!isApexSupported()) return Collections.emptyList();
- populateAllPackagesCacheIfNeeded();
- return mAllPackagesCache
- .stream()
- .filter(item -> !isActive(item))
- .collect(Collectors.toList());
- }
+ abstract List<PackageInfo> getInactivePackages();
/**
* Checks if {@code packageName} is an apex package.
@@ -232,16 +126,7 @@ class ApexManager {
* @param packageName package to check.
* @return {@code true} if {@code packageName} is an apex package.
*/
- boolean isApexPackage(String packageName) {
- if (!isApexSupported()) return false;
- populateAllPackagesCacheIfNeeded();
- for (PackageInfo packageInfo : mAllPackagesCache) {
- if (packageInfo.packageName.equals(packageName)) {
- return true;
- }
- }
- return false;
- }
+ abstract boolean isApexPackage(String packageName);
/**
* Retrieves information about an apexd staged session i.e. the internal state used by apexd to
@@ -250,19 +135,8 @@ class ApexManager {
* @param sessionId the identifier of the session.
* @return an ApexSessionInfo object, or null if the session is not known.
*/
- @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) {
- if (!isApexSupported()) return null;
- try {
- ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId);
- if (apexSessionInfo.isUnknown) {
- return null;
- }
- return apexSessionInfo;
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to contact apexservice", re);
- throw new RuntimeException(re);
- }
- }
+ @Nullable
+ abstract ApexSessionInfo getStagedSessionInfo(int sessionId);
/**
* Submit a staged session to apex service. This causes the apex service to perform some initial
@@ -274,22 +148,10 @@ class ApexManager {
* @param childSessionIds if {@code sessionId} is a multi-package session, this should contain
* an array of identifiers of all the child sessions. Otherwise it should
* be an empty array.
- * @param apexInfoList this is an output parameter, which needs to be initialized by tha caller
- * and will be filled with a list of {@link ApexInfo} objects, each of which
- * contains metadata about one of the packages being submitted as part of
- * the session.
- * @return whether the submission of the session was successful.
+ * @throws PackageManagerException if call to apexd fails
*/
- boolean submitStagedSession(
- int sessionId, @NonNull int[] childSessionIds, @NonNull ApexInfoList apexInfoList) {
- if (!isApexSupported()) return false;
- try {
- return mApexService.submitStagedSession(sessionId, childSessionIds, apexInfoList);
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to contact apexservice", re);
- throw new RuntimeException(re);
- }
- }
+ abstract ApexInfoList submitStagedSession(int sessionId, @NonNull int[] childSessionIds)
+ throws PackageManagerException;
/**
* Mark a staged session previously submitted using {@code submitStagedSession} as ready to be
@@ -298,15 +160,7 @@ class ApexManager {
* @param sessionId the identifier of the {@link PackageInstallerSession} being marked as ready.
* @return true upon success, false if the session is unknown.
*/
- boolean markStagedSessionReady(int sessionId) {
- if (!isApexSupported()) return false;
- try {
- return mApexService.markStagedSessionReady(sessionId);
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to contact apexservice", re);
- throw new RuntimeException(re);
- }
- }
+ abstract boolean markStagedSessionReady(int sessionId);
/**
* Marks a staged session as successful.
@@ -316,44 +170,21 @@ class ApexManager {
* @param sessionId the identifier of the {@link PackageInstallerSession} being marked as
* successful.
*/
- void markStagedSessionSuccessful(int sessionId) {
- if (!isApexSupported()) return;
- try {
- mApexService.markStagedSessionSuccessful(sessionId);
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to contact apexservice", re);
- throw new RuntimeException(re);
- } catch (Exception e) {
- // It is fine to just log an exception in this case. APEXd will be able to recover in
- // case markStagedSessionSuccessful fails.
- Slog.e(TAG, "Failed to mark session " + sessionId + " as successful", e);
- }
- }
+ abstract void markStagedSessionSuccessful(int sessionId);
/**
* Whether the current device supports the management of APEX packages.
*
* @return true if APEX packages can be managed on this device, false otherwise.
*/
- boolean isApexSupported() {
- return ApexProperties.updatable().orElse(false);
- }
+ abstract boolean isApexSupported();
/**
* Abandons the (only) active session previously submitted.
*
* @return {@code true} upon success, {@code false} if any remote exception occurs
*/
- boolean abortActiveSession() {
- if (!isApexSupported()) return false;
- try {
- mApexService.abortActiveSession();
- return true;
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to contact apexservice", re);
- return false;
- }
- }
+ abstract boolean abortActiveSession();
/**
* Uninstalls given {@code apexPackage}.
@@ -363,120 +194,415 @@ class ApexManager {
* @param apexPackagePath package to uninstall.
* @return {@code true} upon successful uninstall, {@code false} otherwise.
*/
- boolean uninstallApex(String apexPackagePath) {
- if (!isApexSupported()) return false;
- try {
- mApexService.unstagePackages(Collections.singletonList(apexPackagePath));
- return true;
- } catch (Exception e) {
- return false;
- }
- }
+ abstract boolean uninstallApex(String apexPackagePath);
/**
- * Whether an APEX package is active or not.
+ * Dumps various state information to the provided {@link PrintWriter} object.
*
- * @param packageInfo the package to check
- * @return {@code true} if this package is active, {@code false} otherwise.
+ * @param pw the {@link PrintWriter} object to send information to.
+ * @param packageName a {@link String} containing a package name, or {@code null}. If set, only
+ * information about that specific package will be dumped.
*/
- private static boolean isActive(PackageInfo packageInfo) {
- return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
- }
+ abstract void dump(PrintWriter pw, @Nullable String packageName);
- /**
- * Whether the APEX package is pre-installed or not.
- *
- * @param packageInfo the package to check
- * @return {@code true} if this package is pre-installed, {@code false} otherwise.
- */
- private static boolean isFactory(PackageInfo packageInfo) {
- return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- }
+ @IntDef(
+ flag = true,
+ prefix = { "MATCH_"},
+ value = {MATCH_ACTIVE_PACKAGE, MATCH_FACTORY_PACKAGE})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface PackageInfoFlags{}
/**
- * Dump information about the packages contained in a particular cache
- * @param packagesCache the cache to print information about.
- * @param packageName a {@link String} containing a package name, or {@code null}. If set, only
- * information about that specific package will be dumped.
- * @param ipw the {@link IndentingPrintWriter} object to send information to.
+ * An implementation of {@link ApexManager} that should be used in case device supports updating
+ * APEX packages.
*/
- void dumpFromPackagesCache(
- List<PackageInfo> packagesCache,
- @Nullable String packageName,
- IndentingPrintWriter ipw) {
- ipw.println();
- ipw.increaseIndent();
- for (PackageInfo pi : packagesCache) {
- if (packageName != null && !packageName.equals(pi.packageName)) {
- continue;
+ private static class ApexManagerImpl extends ApexManager {
+ private final IApexService mApexService;
+ private final Context mContext;
+ private final Object mLock = new Object();
+ /**
+ * A map from {@code APEX packageName} to the {@Link PackageInfo} generated from the {@code
+ * AndroidManifest.xml}
+ *
+ * <p>Note that key of this map is {@code packageName} field of the corresponding {@code
+ * AndroidManifest.xml}.
+ */
+ @GuardedBy("mLock")
+ private List<PackageInfo> mAllPackagesCache;
+
+ ApexManagerImpl(Context context, IApexService apexService) {
+ mContext = context;
+ mApexService = apexService;
+ }
+
+ /**
+ * Whether an APEX package is active or not.
+ *
+ * @param packageInfo the package to check
+ * @return {@code true} if this package is active, {@code false} otherwise.
+ */
+ private static boolean isActive(PackageInfo packageInfo) {
+ return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
+ }
+
+ /**
+ * Whether the APEX package is pre-installed or not.
+ *
+ * @param packageInfo the package to check
+ * @return {@code true} if this package is pre-installed, {@code false} otherwise.
+ */
+ private static boolean isFactory(PackageInfo packageInfo) {
+ return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ }
+
+ @Override
+ void systemReady() {
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ populateAllPackagesCacheIfNeeded();
+ mContext.unregisterReceiver(this);
+ }
+ }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ }
+
+ private void populateAllPackagesCacheIfNeeded() {
+ synchronized (mLock) {
+ if (mAllPackagesCache != null) {
+ return;
+ }
+ try {
+ mAllPackagesCache = new ArrayList<>();
+ HashSet<String> activePackagesSet = new HashSet<>();
+ HashSet<String> factoryPackagesSet = new HashSet<>();
+ final ApexInfo[] allPkgs = mApexService.getAllPackages();
+ for (ApexInfo ai : allPkgs) {
+ // If the device is using flattened APEX, don't report any APEX
+ // packages since they won't be managed or updated by PackageManager.
+ if ((new File(ai.modulePath)).isDirectory()) {
+ break;
+ }
+ try {
+ final PackageInfo pkg = PackageParser.generatePackageInfoFromApex(
+ ai, PackageManager.GET_META_DATA
+ | PackageManager.GET_SIGNING_CERTIFICATES);
+ mAllPackagesCache.add(pkg);
+ if (ai.isActive) {
+ if (activePackagesSet.contains(pkg.packageName)) {
+ throw new IllegalStateException(
+ "Two active packages have the same name: "
+ + pkg.packageName);
+ }
+ activePackagesSet.add(pkg.packageName);
+ }
+ if (ai.isFactory) {
+ if (factoryPackagesSet.contains(pkg.packageName)) {
+ throw new IllegalStateException(
+ "Two factory packages have the same name: "
+ + pkg.packageName);
+ }
+ factoryPackagesSet.add(pkg.packageName);
+ }
+ } catch (PackageParser.PackageParserException pe) {
+ throw new IllegalStateException("Unable to parse: " + ai, pe);
+ }
+ }
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
+ throw new RuntimeException(re);
+ }
}
- ipw.println(pi.packageName);
- ipw.increaseIndent();
- ipw.println("Version: " + pi.versionCode);
- ipw.println("Path: " + pi.applicationInfo.sourceDir);
- ipw.println("IsActive: " + isActive(pi));
- ipw.println("IsFactory: " + isFactory(pi));
- ipw.decreaseIndent();
}
- ipw.decreaseIndent();
- ipw.println();
- }
- /**
- * Dumps various state information to the provided {@link PrintWriter} object.
- *
- * @param pw the {@link PrintWriter} object to send information to.
- * @param packageName a {@link String} containing a package name, or {@code null}. If set, only
- * information about that specific package will be dumped.
- */
- void dump(PrintWriter pw, @Nullable String packageName) {
- if (!isApexSupported()) return;
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
- try {
+ @Override
+ @Nullable PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) {
+ populateAllPackagesCacheIfNeeded();
+ boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0;
+ boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0;
+ for (PackageInfo packageInfo: mAllPackagesCache) {
+ if (!packageInfo.packageName.equals(packageName)) {
+ continue;
+ }
+ if ((!matchActive || isActive(packageInfo))
+ && (!matchFactory || isFactory(packageInfo))) {
+ return packageInfo;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ List<PackageInfo> getActivePackages() {
+ populateAllPackagesCacheIfNeeded();
+ return mAllPackagesCache
+ .stream()
+ .filter(item -> isActive(item))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ List<PackageInfo> getFactoryPackages() {
+ populateAllPackagesCacheIfNeeded();
+ return mAllPackagesCache
+ .stream()
+ .filter(item -> isFactory(item))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ List<PackageInfo> getInactivePackages() {
+ populateAllPackagesCacheIfNeeded();
+ return mAllPackagesCache
+ .stream()
+ .filter(item -> !isActive(item))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ boolean isApexPackage(String packageName) {
+ if (!isApexSupported()) return false;
populateAllPackagesCacheIfNeeded();
+ for (PackageInfo packageInfo : mAllPackagesCache) {
+ if (packageInfo.packageName.equals(packageName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) {
+ try {
+ ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId);
+ if (apexSessionInfo.isUnknown) {
+ return null;
+ }
+ return apexSessionInfo;
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to contact apexservice", re);
+ throw new RuntimeException(re);
+ }
+ }
+
+ @Override
+ ApexInfoList submitStagedSession(int sessionId, @NonNull int[] childSessionIds)
+ throws PackageManagerException {
+ try {
+ final ApexInfoList apexInfoList = new ApexInfoList();
+ mApexService.submitStagedSession(sessionId, childSessionIds, apexInfoList);
+ return apexInfoList;
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to contact apexservice", re);
+ throw new RuntimeException(re);
+ } catch (Exception e) {
+ throw new PackageManagerException(
+ PackageInstaller.SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ "apexd verification failed : " + e.getMessage());
+ }
+ }
+
+ @Override
+ boolean markStagedSessionReady(int sessionId) {
+ try {
+ return mApexService.markStagedSessionReady(sessionId);
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to contact apexservice", re);
+ throw new RuntimeException(re);
+ }
+ }
+
+ @Override
+ void markStagedSessionSuccessful(int sessionId) {
+ try {
+ mApexService.markStagedSessionSuccessful(sessionId);
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to contact apexservice", re);
+ throw new RuntimeException(re);
+ } catch (Exception e) {
+ // It is fine to just log an exception in this case. APEXd will be able to recover
+ // in case markStagedSessionSuccessful fails.
+ Slog.e(TAG, "Failed to mark session " + sessionId + " as successful", e);
+ }
+ }
+
+ @Override
+ boolean isApexSupported() {
+ return true;
+ }
+
+ @Override
+ boolean abortActiveSession() {
+ try {
+ mApexService.abortActiveSession();
+ return true;
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to contact apexservice", re);
+ return false;
+ }
+ }
+
+ @Override
+ boolean uninstallApex(String apexPackagePath) {
+ try {
+ mApexService.unstagePackages(Collections.singletonList(apexPackagePath));
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Dump information about the packages contained in a particular cache
+ * @param packagesCache the cache to print information about.
+ * @param packageName a {@link String} containing a package name, or {@code null}. If set,
+ * only information about that specific package will be dumped.
+ * @param ipw the {@link IndentingPrintWriter} object to send information to.
+ */
+ void dumpFromPackagesCache(
+ List<PackageInfo> packagesCache,
+ @Nullable String packageName,
+ IndentingPrintWriter ipw) {
ipw.println();
- ipw.println("Active APEX packages:");
- dumpFromPackagesCache(getActivePackages(), packageName, ipw);
- ipw.println("Inactive APEX packages:");
- dumpFromPackagesCache(getInactivePackages(), packageName, ipw);
- ipw.println("Factory APEX packages:");
- dumpFromPackagesCache(getFactoryPackages(), packageName, ipw);
- ipw.increaseIndent();
- ipw.println("APEX session state:");
ipw.increaseIndent();
- final ApexSessionInfo[] sessions = mApexService.getSessions();
- for (ApexSessionInfo si : sessions) {
- ipw.println("Session ID: " + si.sessionId);
- ipw.increaseIndent();
- if (si.isUnknown) {
- ipw.println("State: UNKNOWN");
- } else if (si.isVerified) {
- ipw.println("State: VERIFIED");
- } else if (si.isStaged) {
- ipw.println("State: STAGED");
- } else if (si.isActivated) {
- ipw.println("State: ACTIVATED");
- } else if (si.isActivationFailed) {
- ipw.println("State: ACTIVATION FAILED");
- } else if (si.isSuccess) {
- ipw.println("State: SUCCESS");
- } else if (si.isRollbackInProgress) {
- ipw.println("State: ROLLBACK IN PROGRESS");
- } else if (si.isRolledBack) {
- ipw.println("State: ROLLED BACK");
- } else if (si.isRollbackFailed) {
- ipw.println("State: ROLLBACK FAILED");
+ for (PackageInfo pi : packagesCache) {
+ if (packageName != null && !packageName.equals(pi.packageName)) {
+ continue;
}
+ ipw.println(pi.packageName);
+ ipw.increaseIndent();
+ ipw.println("Version: " + pi.versionCode);
+ ipw.println("Path: " + pi.applicationInfo.sourceDir);
+ ipw.println("IsActive: " + isActive(pi));
+ ipw.println("IsFactory: " + isFactory(pi));
ipw.decreaseIndent();
}
ipw.decreaseIndent();
- } catch (RemoteException e) {
- ipw.println("Couldn't communicate with apexd.");
+ ipw.println();
+ }
+
+ @Override
+ void dump(PrintWriter pw, @Nullable String packageName) {
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ try {
+ populateAllPackagesCacheIfNeeded();
+ ipw.println();
+ ipw.println("Active APEX packages:");
+ dumpFromPackagesCache(getActivePackages(), packageName, ipw);
+ ipw.println("Inactive APEX packages:");
+ dumpFromPackagesCache(getInactivePackages(), packageName, ipw);
+ ipw.println("Factory APEX packages:");
+ dumpFromPackagesCache(getFactoryPackages(), packageName, ipw);
+ ipw.increaseIndent();
+ ipw.println("APEX session state:");
+ ipw.increaseIndent();
+ final ApexSessionInfo[] sessions = mApexService.getSessions();
+ for (ApexSessionInfo si : sessions) {
+ ipw.println("Session ID: " + si.sessionId);
+ ipw.increaseIndent();
+ if (si.isUnknown) {
+ ipw.println("State: UNKNOWN");
+ } else if (si.isVerified) {
+ ipw.println("State: VERIFIED");
+ } else if (si.isStaged) {
+ ipw.println("State: STAGED");
+ } else if (si.isActivated) {
+ ipw.println("State: ACTIVATED");
+ } else if (si.isActivationFailed) {
+ ipw.println("State: ACTIVATION FAILED");
+ } else if (si.isSuccess) {
+ ipw.println("State: SUCCESS");
+ } else if (si.isRollbackInProgress) {
+ ipw.println("State: ROLLBACK IN PROGRESS");
+ } else if (si.isRolledBack) {
+ ipw.println("State: ROLLED BACK");
+ } else if (si.isRollbackFailed) {
+ ipw.println("State: ROLLBACK FAILED");
+ }
+ ipw.decreaseIndent();
+ }
+ ipw.decreaseIndent();
+ } catch (RemoteException e) {
+ ipw.println("Couldn't communicate with apexd.");
+ }
}
}
- public void onBootCompleted() {
- if (!isApexSupported()) return;
- populateAllPackagesCacheIfNeeded();
+ /**
+ * An implementation of {@link ApexManager} that should be used in case device does not support
+ * updating APEX packages.
+ */
+ private static final class ApexManagerNoOp extends ApexManager {
+
+ @Override
+ void systemReady() {
+ // No-op
+ }
+
+ @Override
+ PackageInfo getPackageInfo(String packageName, int flags) {
+ return null;
+ }
+
+ @Override
+ List<PackageInfo> getActivePackages() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ List<PackageInfo> getFactoryPackages() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ List<PackageInfo> getInactivePackages() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ boolean isApexPackage(String packageName) {
+ return false;
+ }
+
+ @Override
+ ApexSessionInfo getStagedSessionInfo(int sessionId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ ApexInfoList submitStagedSession(int sessionId, int[] childSessionIds)
+ throws PackageManagerException {
+ throw new PackageManagerException(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
+ "Device doesn't support updating APEX");
+ }
+
+ @Override
+ boolean markStagedSessionReady(int sessionId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ void markStagedSessionSuccessful(int sessionId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ boolean isApexSupported() {
+ return false;
+ }
+
+ @Override
+ boolean abortActiveSession() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ boolean uninstallApex(String apexPackagePath) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ void dump(PrintWriter pw, String packageName) {
+ // No-op
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index ad9ac1232437..2b33aced7151 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -254,9 +254,16 @@ public class BackgroundDexOptService extends JobService {
@Override
public void run() {
int result = idleOptimization(pm, pkgs, BackgroundDexOptService.this);
- if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
+ if (result == OPTIMIZE_PROCESSED) {
+ Log.i(TAG, "Idle optimizations completed.");
+ } else if (result == OPTIMIZE_ABORT_NO_SPACE_LEFT) {
Log.w(TAG, "Idle optimizations aborted because of space constraints.");
- // If we didn't abort we ran to completion (or stopped because of space).
+ } else if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
+ Log.w(TAG, "Idle optimizations aborted by job scheduler.");
+ } else {
+ Log.w(TAG, "Idle optimizations ended with unexpected code: " + result);
+ }
+ if (result != OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
// Abandon our timeslice and do not reschedule.
jobFinished(jobParams, /* reschedule */ false);
}
@@ -339,6 +346,7 @@ public class BackgroundDexOptService extends JobService {
long lowStorageThreshold, boolean isForPrimaryDex) {
ArraySet<String> updatedPackages = new ArraySet<>();
Set<String> unusedPackages = pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
+ boolean hadSomeLowSpaceFailure = false;
Log.d(TAG, "Unsused Packages " + String.join(",", unusedPackages));
// Only downgrade apps when space is low on device.
// Threshold is selected above the lowStorageThreshold so that we can pro-actively clean
@@ -359,6 +367,7 @@ public class BackgroundDexOptService extends JobService {
} else {
if (abort_code == OPTIMIZE_ABORT_NO_SPACE_LEFT) {
// can't dexopt because of low space.
+ hadSomeLowSpaceFailure = true;
continue;
}
dex_opt_performed = optimizePackage(pm, pkg, isForPrimaryDex);
@@ -369,7 +378,7 @@ public class BackgroundDexOptService extends JobService {
}
notifyPinService(updatedPackages);
- return OPTIMIZE_PROCESSED;
+ return hadSomeLowSpaceFailure ? OPTIMIZE_ABORT_NO_SPACE_LEFT : OPTIMIZE_PROCESSED;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 232bca82aa9c..5ab8ec3b04ab 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1768,11 +1768,12 @@ public class PackageManagerService extends IPackageManager.Stub
private PermissionCallback mPermissionCallback = new PermissionCallback() {
@Override
- public void onGidsChanged(int appId, int userId) {
+ public void onGidsChanged(int appId, @UserIdInt int userId) {
mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED));
}
+
@Override
- public void onPermissionGranted(int uid, int userId) {
+ public void onPermissionGranted(int uid, @UserIdInt int userId) {
mOnPermissionChangeListeners.onPermissionsChanged(uid);
// Not critical; if this is lost, the application has to request again.
@@ -1780,14 +1781,16 @@ public class PackageManagerService extends IPackageManager.Stub
mSettings.writeRuntimePermissionsForUserLPr(userId, false);
}
}
+
@Override
public void onInstallPermissionGranted() {
synchronized (mPackages) {
scheduleWriteSettingsLocked();
}
}
+
@Override
- public void onPermissionRevoked(int uid, int userId) {
+ public void onPermissionRevoked(int uid, @UserIdInt int userId) {
mOnPermissionChangeListeners.onPermissionsChanged(uid);
synchronized (mPackages) {
@@ -1798,26 +1801,43 @@ public class PackageManagerService extends IPackageManager.Stub
final int appId = UserHandle.getAppId(uid);
killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
}
+
@Override
public void onInstallPermissionRevoked() {
synchronized (mPackages) {
scheduleWriteSettingsLocked();
}
}
+
@Override
- public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
+ public void onPermissionUpdated(@UserIdInt int[] updatedUserIds, boolean sync) {
synchronized (mPackages) {
for (int userId : updatedUserIds) {
mSettings.writeRuntimePermissionsForUserLPr(userId, sync);
}
}
}
+
+ @Override
+ public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
+ int uid) {
+ onPermissionUpdated(updatedUserIds, sync);
+ mOnPermissionChangeListeners.onPermissionsChanged(uid);
+ }
+
@Override
public void onInstallPermissionUpdated() {
synchronized (mPackages) {
scheduleWriteSettingsLocked();
}
}
+
+ @Override
+ public void onInstallPermissionUpdatedNotifyListener(int uid) {
+ onInstallPermissionUpdated();
+ mOnPermissionChangeListeners.onPermissionsChanged(uid);
+ }
+
@Override
public void onPermissionRemoved() {
synchronized (mPackages) {
@@ -2489,7 +2509,7 @@ public class PackageManagerService extends IPackageManager.Stub
mProtectedPackages = new ProtectedPackages(mContext);
- mApexManager = new ApexManager(context);
+ mApexManager = ApexManager.create(context);
// CHECKSTYLE:OFF IndentationCheck
synchronized (mInstallLock) {
// writer
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index f9a019703f4d..404b515e233e 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -155,13 +155,10 @@ public class StagingManager {
}
}
}
- final ApexInfoList apexInfoList = new ApexInfoList();
- boolean submittedToApexd = mApexManager.submitStagedSession(session.sessionId,
- childSessionsIds.toArray(), apexInfoList);
- if (!submittedToApexd) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "APEX staging failed, check logcat messages from apexd for more details.");
- }
+ // submitStagedSession will throw a PackageManagerException if apexd verification fails,
+ // which will be propagated to populate stagedSessionErrorMessage of this session.
+ final ApexInfoList apexInfoList = mApexManager.submitStagedSession(session.sessionId,
+ childSessionsIds.toArray());
final List<PackageInfo> result = new ArrayList<>();
for (ApexInfo newPackage : apexInfoList.apexInfos) {
final PackageInfo pkg;
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 8a3b3e3f627c..f4ba4492dcbb 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -90,7 +90,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.BackgroundThread;
-import com.android.internal.os.RoSystemProperties;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
@@ -2217,10 +2216,11 @@ public class UserManagerService extends IUserManager.Stub {
@GuardedBy({"mPackagesLock", "mRestrictionsLock"})
private void fallbackToSingleUserLP() {
- int flags = UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN;
- // In headless system user mode, the primary flag is assigned to the first human user.
- if (!RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER) {
- flags |= UserInfo.FLAG_PRIMARY;
+ int flags = UserInfo.FLAG_INITIALIZED;
+ // In split system user mode, the admin and primary flags are assigned to the first human
+ // user.
+ if (!UserManager.isSplitSystemUser()) {
+ flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
}
// Create the system user
UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
@@ -2734,9 +2734,9 @@ public class UserManagerService extends IUserManager.Stub {
return null;
}
}
- // In headless system user mode, we assign the first human user the primary flag.
+ // In split system user mode, we assign the first human user the primary flag.
// And if there is no device owner, we also assign the admin flag to primary user.
- if (RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER
+ if (UserManager.isSplitSystemUser()
&& !isGuest && !isManagedProfile && getPrimaryUser() == null) {
flags |= UserInfo.FLAG_PRIMARY;
synchronized (mUsersLock) {
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 43a8373b339f..9b00dcaee1d7 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -2334,6 +2334,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return;
}
+ // Permission is already revoked, no need to do anything.
+ if (!permissionsState.hasRuntimePermission(permName, userId)) {
+ return;
+ }
+
if (permissionsState.revokeRuntimePermission(bp, userId) ==
PERMISSION_OPERATION_FAILURE) {
return;
@@ -2952,10 +2957,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// Install and runtime permissions are stored in different places,
// so figure out what permission changed and persist the change.
if (permissionsState.getInstallPermissionState(permName) != null) {
- callback.onInstallPermissionUpdated();
+ callback.onInstallPermissionUpdatedNotifyListener(pkg.applicationInfo.uid);
} else if (permissionsState.getRuntimePermissionState(permName, userId) != null
|| hadState) {
- callback.onPermissionUpdated(new int[] { userId }, false);
+ callback.onPermissionUpdatedNotifyListener(new int[] { userId }, false,
+ pkg.applicationInfo.uid);
}
}
}
@@ -2989,6 +2995,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
PermissionsState permissionsState = ps.getPermissionsState();
changed |= permissionsState.updatePermissionFlagsForAllPermissions(
userId, flagMask, flagValues);
+ callback.onPermissionUpdatedNotifyListener(new int[] { userId }, false,
+ pkg.applicationInfo.uid);
}
return changed;
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 23d011439ccc..a78557523345 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -16,6 +16,7 @@
package com.android.server.pm.permission;
+import android.annotation.AppIdInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -42,24 +43,29 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
* callback methods.
*/
public static class PermissionCallback {
- public void onGidsChanged(int appId, int userId) {
+ public void onGidsChanged(@AppIdInt int appId, @UserIdInt int userId) {
}
public void onPermissionChanged() {
}
- public void onPermissionGranted(int uid, int userId) {
+ public void onPermissionGranted(int uid, @UserIdInt int userId) {
}
public void onInstallPermissionGranted() {
}
- public void onPermissionRevoked(int uid, int userId) {
+ public void onPermissionRevoked(int uid, @UserIdInt int userId) {
}
public void onInstallPermissionRevoked() {
}
- public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
+ public void onPermissionUpdated(@UserIdInt int[] updatedUserIds, boolean sync) {
+ }
+ public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
+ int uid) {
}
public void onPermissionRemoved() {
}
public void onInstallPermissionUpdated() {
}
+ public void onInstallPermissionUpdatedNotifyListener(int uid) {
+ }
}
public abstract void systemReady();
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 82eab63eb4d5..4404b7363981 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -86,9 +86,9 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
private static final String TAG = "RollbackManager";
- // Rollbacks expire after 48 hours.
+ // Rollbacks expire after 14 days.
private static final long DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS =
- TimeUnit.HOURS.toMillis(48);
+ TimeUnit.DAYS.toMillis(14);
// Lock used to synchronize accesses to in-memory rollback data
// structures. By convention, methods with the suffix "Locked" require
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index 5f00148335a7..ab3d7b7f763c 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -30,6 +30,7 @@ import android.os.UserHandle;
import android.service.textclassifier.ITextClassifierCallback;
import android.service.textclassifier.ITextClassifierService;
import android.service.textclassifier.TextClassifierService;
+import android.util.ArrayMap;
import android.util.Slog;
import android.util.SparseArray;
import android.view.textclassifier.ConversationActions;
@@ -54,6 +55,7 @@ import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayDeque;
+import java.util.Map;
import java.util.Queue;
/**
@@ -119,6 +121,8 @@ public final class TextClassificationManagerService extends ITextClassifierServi
private final Object mLock;
@GuardedBy("mLock")
final SparseArray<UserState> mUserStates = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final Map<TextClassificationSessionId, Integer> mSessionUserIds = new ArrayMap<>();
private TextClassificationManagerService(Context context) {
mContext = Preconditions.checkNotNull(context);
@@ -127,15 +131,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Override
public void onSuggestSelection(
- TextClassificationSessionId sessionId,
+ @Nullable TextClassificationSessionId sessionId,
TextSelection.Request request, ITextClassifierCallback callback)
throws RemoteException {
Preconditions.checkNotNull(request);
Preconditions.checkNotNull(callback);
- validateInput(mContext, request.getCallingPackageName());
+ final int userId = request.getUserId();
+ validateInput(mContext, request.getCallingPackageName(), userId);
synchronized (mLock) {
- UserState userState = getCallingUserStateLocked();
+ UserState userState = getUserStateLocked(userId);
if (!userState.bindLocked()) {
callback.onFailure();
} else if (userState.isBoundLocked()) {
@@ -150,15 +155,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Override
public void onClassifyText(
- TextClassificationSessionId sessionId,
+ @Nullable TextClassificationSessionId sessionId,
TextClassification.Request request, ITextClassifierCallback callback)
throws RemoteException {
Preconditions.checkNotNull(request);
Preconditions.checkNotNull(callback);
- validateInput(mContext, request.getCallingPackageName());
+ final int userId = request.getUserId();
+ validateInput(mContext, request.getCallingPackageName(), userId);
synchronized (mLock) {
- UserState userState = getCallingUserStateLocked();
+ UserState userState = getUserStateLocked(userId);
if (!userState.bindLocked()) {
callback.onFailure();
} else if (userState.isBoundLocked()) {
@@ -173,15 +179,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Override
public void onGenerateLinks(
- TextClassificationSessionId sessionId,
+ @Nullable TextClassificationSessionId sessionId,
TextLinks.Request request, ITextClassifierCallback callback)
throws RemoteException {
Preconditions.checkNotNull(request);
Preconditions.checkNotNull(callback);
- validateInput(mContext, request.getCallingPackageName());
+ final int userId = request.getUserId();
+ validateInput(mContext, request.getCallingPackageName(), userId);
synchronized (mLock) {
- UserState userState = getCallingUserStateLocked();
+ UserState userState = getUserStateLocked(userId);
if (!userState.bindLocked()) {
callback.onFailure();
} else if (userState.isBoundLocked()) {
@@ -196,12 +203,14 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Override
public void onSelectionEvent(
- TextClassificationSessionId sessionId, SelectionEvent event) throws RemoteException {
+ @Nullable TextClassificationSessionId sessionId, SelectionEvent event)
+ throws RemoteException {
Preconditions.checkNotNull(event);
- validateInput(mContext, event.getPackageName());
+ final int userId = event.getUserId();
+ validateInput(mContext, event.getPackageName(), userId);
synchronized (mLock) {
- UserState userState = getCallingUserStateLocked();
+ UserState userState = getUserStateLocked(userId);
if (userState.isBoundLocked()) {
userState.mService.onSelectionEvent(sessionId, event);
} else {
@@ -213,16 +222,19 @@ public final class TextClassificationManagerService extends ITextClassifierServi
}
@Override
public void onTextClassifierEvent(
- TextClassificationSessionId sessionId,
+ @Nullable TextClassificationSessionId sessionId,
TextClassifierEvent event) throws RemoteException {
Preconditions.checkNotNull(event);
final String packageName = event.getEventContext() == null
? null
: event.getEventContext().getPackageName();
- validateInput(mContext, packageName);
+ final int userId = event.getEventContext() == null
+ ? UserHandle.getCallingUserId()
+ : event.getEventContext().getUserId();
+ validateInput(mContext, packageName, userId);
synchronized (mLock) {
- UserState userState = getCallingUserStateLocked();
+ UserState userState = getUserStateLocked(userId);
if (userState.isBoundLocked()) {
userState.mService.onTextClassifierEvent(sessionId, event);
} else {
@@ -235,15 +247,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Override
public void onDetectLanguage(
- TextClassificationSessionId sessionId,
+ @Nullable TextClassificationSessionId sessionId,
TextLanguage.Request request,
ITextClassifierCallback callback) throws RemoteException {
Preconditions.checkNotNull(request);
Preconditions.checkNotNull(callback);
- validateInput(mContext, request.getCallingPackageName());
+ final int userId = request.getUserId();
+ validateInput(mContext, request.getCallingPackageName(), userId);
synchronized (mLock) {
- UserState userState = getCallingUserStateLocked();
+ UserState userState = getUserStateLocked(userId);
if (!userState.bindLocked()) {
callback.onFailure();
} else if (userState.isBoundLocked()) {
@@ -258,15 +271,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
@Override
public void onSuggestConversationActions(
- TextClassificationSessionId sessionId,
+ @Nullable TextClassificationSessionId sessionId,
ConversationActions.Request request,
ITextClassifierCallback callback) throws RemoteException {
Preconditions.checkNotNull(request);
Preconditions.checkNotNull(callback);
- validateInput(mContext, request.getCallingPackageName());
+ final int userId = request.getUserId();
+ validateInput(mContext, request.getCallingPackageName(), userId);
synchronized (mLock) {
- UserState userState = getCallingUserStateLocked();
+ UserState userState = getUserStateLocked(userId);
if (!userState.bindLocked()) {
callback.onFailure();
} else if (userState.isBoundLocked()) {
@@ -285,13 +299,15 @@ public final class TextClassificationManagerService extends ITextClassifierServi
throws RemoteException {
Preconditions.checkNotNull(sessionId);
Preconditions.checkNotNull(classificationContext);
- validateInput(mContext, classificationContext.getPackageName());
+ final int userId = classificationContext.getUserId();
+ validateInput(mContext, classificationContext.getPackageName(), userId);
synchronized (mLock) {
- UserState userState = getCallingUserStateLocked();
+ UserState userState = getUserStateLocked(userId);
if (userState.isBoundLocked()) {
userState.mService.onCreateTextClassificationSession(
classificationContext, sessionId);
+ mSessionUserIds.put(sessionId, userId);
} else {
userState.mPendingRequests.add(new PendingRequest(
() -> onCreateTextClassificationSession(classificationContext, sessionId),
@@ -306,9 +322,15 @@ public final class TextClassificationManagerService extends ITextClassifierServi
Preconditions.checkNotNull(sessionId);
synchronized (mLock) {
- UserState userState = getCallingUserStateLocked();
+ final int userId = mSessionUserIds.containsKey(sessionId)
+ ? mSessionUserIds.get(sessionId)
+ : UserHandle.getCallingUserId();
+ validateInput(mContext, null /* packageName */, userId);
+
+ UserState userState = getUserStateLocked(userId);
if (userState.isBoundLocked()) {
userState.mService.onDestroyTextClassificationSession(sessionId);
+ mSessionUserIds.remove(sessionId);
} else {
userState.mPendingRequests.add(new PendingRequest(
() -> onDestroyTextClassificationSession(sessionId),
@@ -318,11 +340,6 @@ public final class TextClassificationManagerService extends ITextClassifierServi
}
@GuardedBy("mLock")
- private UserState getCallingUserStateLocked() {
- return getUserStateLocked(UserHandle.getCallingUserId());
- }
-
- @GuardedBy("mLock")
private UserState getUserStateLocked(int userId) {
UserState result = mUserStates.get(userId);
if (result == null) {
@@ -356,6 +373,7 @@ public final class TextClassificationManagerService extends ITextClassifierServi
pw.decreaseIndent();
}
}
+ pw.println("Number of active sessions: " + mSessionUserIds.size());
}
}
@@ -420,20 +438,32 @@ public final class TextClassificationManagerService extends ITextClassifierServi
e -> Slog.d(LOG_TAG, "Error " + opDesc + ": " + e.getMessage()));
}
- private static void validateInput(Context context, @Nullable String packageName)
+ private static void validateInput(
+ Context context, @Nullable String packageName, @UserIdInt int userId)
throws RemoteException {
- if (packageName == null) return;
try {
- final int packageUid = context.getPackageManager()
- .getPackageUidAsUser(packageName, UserHandle.getCallingUserId());
- final int callingUid = Binder.getCallingUid();
- Preconditions.checkArgument(callingUid == packageUid
- // Trust the system process:
- || callingUid == android.os.Process.SYSTEM_UID);
+ if (packageName != null) {
+ final int packageUid = context.getPackageManager()
+ .getPackageUidAsUser(packageName, UserHandle.getCallingUserId());
+ final int callingUid = Binder.getCallingUid();
+ Preconditions.checkArgument(callingUid == packageUid
+ // Trust the system process:
+ || callingUid == android.os.Process.SYSTEM_UID,
+ "Invalid package name. Package=" + packageName
+ + ", CallingUid=" + callingUid);
+ }
+
+ Preconditions.checkArgument(userId != UserHandle.USER_NULL, "Null userId");
+ final int callingUserId = UserHandle.getCallingUserId();
+ if (callingUserId != userId) {
+ context.enforceCallingPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ "Invalid userId. UserId=" + userId + ", CallingUserId=" + callingUserId);
+ }
} catch (Exception e) {
- throw new RemoteException(
- String.format("Invalid package: name=%s, error=%s", packageName, e));
+ throw new RemoteException("Invalid request", e,
+ /* enableSuppression */ true, /* writableStackTrace */ true);
}
}
diff --git a/services/core/java/com/android/server/textservices/LazyIntToIntMap.java b/services/core/java/com/android/server/textservices/LazyIntToIntMap.java
deleted file mode 100644
index 2e7f2a92e1d9..000000000000
--- a/services/core/java/com/android/server/textservices/LazyIntToIntMap.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.textservices;
-
-import android.annotation.NonNull;
-import android.util.SparseIntArray;
-
-import java.util.function.IntUnaryOperator;
-
-/**
- * Simple int-to-int key-value-store that is to be lazily initialized with the given
- * {@link IntUnaryOperator}.
- */
-final class LazyIntToIntMap {
-
- private final SparseIntArray mMap = new SparseIntArray();
-
- @NonNull
- private final IntUnaryOperator mMappingFunction;
-
- /**
- * @param mappingFunction int to int mapping rules to be (lazily) evaluated
- */
- public LazyIntToIntMap(@NonNull IntUnaryOperator mappingFunction) {
- mMappingFunction = mappingFunction;
- }
-
- /**
- * Deletes {@code key} and associated value.
- * @param key key to be deleted
- */
- public void delete(int key) {
- mMap.delete(key);
- }
-
- /**
- * @param key key associated with the value
- * @return value associated with the {@code key}. If this is the first time to access
- * {@code key}, then {@code mappingFunction} passed to the constructor will be evaluated
- */
- public int get(int key) {
- final int index = mMap.indexOfKey(key);
- if (index >= 0) {
- return mMap.valueAt(index);
- }
- final int value = mMappingFunction.applyAsInt(key);
- mMap.append(key, value);
- return value;
- }
-}
diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
index d4aa59d3ce85..e0bac93cce16 100644
--- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
@@ -43,7 +43,6 @@ import android.service.textservice.SpellCheckerService;
import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.inputmethod.InputMethodSystemProperty;
import android.view.textservice.SpellCheckerInfo;
import android.view.textservice.SpellCheckerSubtype;
@@ -86,10 +85,6 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
private final UserManager mUserManager;
private final Object mLock = new Object();
- @NonNull
- @GuardedBy("mLock")
- private final LazyIntToIntMap mSpellCheckerOwnerUserIdMap;
-
private static class TextServicesData {
@UserIdInt
private final int mUserId;
@@ -312,9 +307,6 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
void onStopUser(@UserIdInt int userId) {
synchronized (mLock) {
- // Clear user ID mapping table.
- mSpellCheckerOwnerUserIdMap.delete(userId);
-
// Clean per-user data
TextServicesData tsd = mUserData.get(userId);
if (tsd == null) return;
@@ -334,33 +326,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
public TextServicesManagerService(Context context) {
mContext = context;
mUserManager = mContext.getSystemService(UserManager.class);
- mSpellCheckerOwnerUserIdMap = new LazyIntToIntMap(callingUserId -> {
- if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
- final long token = Binder.clearCallingIdentity();
- try {
- final UserInfo parent = mUserManager.getProfileParent(callingUserId);
- return (parent != null) ? parent.id : callingUserId;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- } else {
- return callingUserId;
- }
- });
-
mMonitor = new TextServicesMonitor();
mMonitor.register(context, null, UserHandle.ALL, true);
}
@GuardedBy("mLock")
private void initializeInternalStateLocked(@UserIdInt int userId) {
- // When DISABLE_PER_PROFILE_SPELL_CHECKER is true, we make sure here that work profile users
- // will never have non-null TextServicesData for their user ID.
- if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
- && userId != mSpellCheckerOwnerUserIdMap.get(userId)) {
- return;
- }
-
TextServicesData tsd = mUserData.get(userId);
if (tsd == null) {
tsd = new TextServicesData(userId, mContext);
@@ -506,8 +477,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
@Nullable
private SpellCheckerInfo getCurrentSpellCheckerForUser(@UserIdInt int userId) {
synchronized (mLock) {
- final int spellCheckerOwnerUserId = mSpellCheckerOwnerUserIdMap.get(userId);
- final TextServicesData data = mUserData.get(spellCheckerOwnerUserId);
+ final TextServicesData data = mUserData.get(userId);
return data != null ? data.getCurrentSpellChecker() : null;
}
}
@@ -790,27 +760,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
@GuardedBy("mLock")
@Nullable
private TextServicesData getDataFromCallingUserIdLocked(@UserIdInt int callingUserId) {
- final int spellCheckerOwnerUserId = mSpellCheckerOwnerUserIdMap.get(callingUserId);
- final TextServicesData data = mUserData.get(spellCheckerOwnerUserId);
- if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
- if (spellCheckerOwnerUserId != callingUserId) {
- // Calling process is running under child profile.
- if (data == null) {
- return null;
- }
- final SpellCheckerInfo info = data.getCurrentSpellChecker();
- if (info == null) {
- return null;
- }
- final ServiceInfo serviceInfo = info.getServiceInfo();
- if ((serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
- // To be conservative, non pre-installed spell checker services are not allowed
- // to be used for child profiles.
- return null;
- }
- }
- }
- return data;
+ return mUserData.get(callingUserId);
}
private static final class SessionRequest {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 9908b3657121..b0f1e5d69be4 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -1172,8 +1172,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
return false;
}
final int displayId = display.getDisplayId();
- return displayId == DEFAULT_DISPLAY
- || mWindowManagerInternal.shouldShowSystemDecorOnDisplay(displayId);
+ if (displayId == DEFAULT_DISPLAY) {
+ return true;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return mWindowManagerInternal.shouldShowSystemDecorOnDisplay(displayId);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
void forEachDisplayConnector(Consumer<DisplayConnector> action) {
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 637ad0384dac..fe4811dce274 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -29,6 +29,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.os.Build.VERSION_CODES.N;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
@@ -55,18 +56,24 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.os.IBinder;
+import android.os.Message;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.IntArray;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.am.EventLogTags;
import java.io.PrintWriter;
@@ -156,6 +163,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
// Used in updating the display size
private Point mTmpDisplaySize = new Point();
+ // Used in updating override configurations
+ private final Configuration mTempConfig = new Configuration();
+
private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
ActivityDisplay(RootActivityContainer root, Display display) {
@@ -999,6 +1009,89 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
return mStacks.indexOf(stack);
}
+ boolean updateDisplayOverrideConfigurationLocked() {
+ Configuration values = new Configuration();
+ mDisplayContent.computeScreenConfiguration(values);
+
+ if (mService.mWindowManager != null) {
+ final Message msg = PooledLambda.obtainMessage(
+ ActivityManagerInternal::updateOomLevelsForDisplay, mService.mAmInternal,
+ mDisplayId);
+ mService.mH.sendMessage(msg);
+ }
+
+ Settings.System.clearConfiguration(values);
+ updateDisplayOverrideConfigurationLocked(values, null /* starting */,
+ false /* deferResume */, mService.mTmpUpdateConfigurationResult);
+ return mService.mTmpUpdateConfigurationResult.changes != 0;
+ }
+
+ /**
+ * Updates override configuration specific for the selected display. If no config is provided,
+ * new one will be computed in WM based on current display info.
+ */
+ boolean updateDisplayOverrideConfigurationLocked(Configuration values,
+ ActivityRecord starting, boolean deferResume,
+ ActivityTaskManagerService.UpdateConfigurationResult result) {
+
+ int changes = 0;
+ boolean kept = true;
+
+ if (mService.mWindowManager != null) {
+ mService.mWindowManager.deferSurfaceLayout();
+ }
+ try {
+ if (values != null) {
+ if (mDisplayId == DEFAULT_DISPLAY) {
+ // Override configuration of the default display duplicates global config, so
+ // we're calling global config update instead for default display. It will also
+ // apply the correct override config.
+ changes = mService.updateGlobalConfigurationLocked(values,
+ false /* initLocale */, false /* persistent */,
+ UserHandle.USER_NULL /* userId */, deferResume);
+ } else {
+ changes = performDisplayOverrideConfigUpdate(values, deferResume);
+ }
+ }
+
+ kept = mService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
+ } finally {
+ if (mService.mWindowManager != null) {
+ mService.mWindowManager.continueSurfaceLayout();
+ }
+ }
+
+ if (result != null) {
+ result.changes = changes;
+ result.activityRelaunched = !kept;
+ }
+ return kept;
+ }
+
+ int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume) {
+ mTempConfig.setTo(getRequestedOverrideConfiguration());
+ final int changes = mTempConfig.updateFrom(values);
+ if (changes != 0) {
+ Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
+ + mTempConfig + " for displayId=" + mDisplayId);
+ onRequestedOverrideConfigurationChanged(mTempConfig);
+
+ final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
+ if (isDensityChange && mDisplayId == DEFAULT_DISPLAY) {
+ mService.mAppWarnings.onDensityChanged();
+
+ // Post message to start process to avoid possible deadlock of calling into AMS with
+ // the ATMS lock held.
+ final Message msg = PooledLambda.obtainMessage(
+ ActivityManagerInternal::killAllBackgroundProcessesExcept,
+ mService.mAmInternal, N,
+ ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+ mService.mH.sendMessage(msg);
+ }
+ }
+ return changes;
+ }
+
@Override
public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
final int currRotation =
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 20ccf073e5b9..971a24d13643 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -459,7 +459,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
boolean mSuppressResizeConfigChanges;
- private final UpdateConfigurationResult mTmpUpdateConfigurationResult =
+ final UpdateConfigurationResult mTmpUpdateConfigurationResult =
new UpdateConfigurationResult();
static final class UpdateConfigurationResult {
@@ -631,7 +631,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
/** If non-null, we are tracking the time the user spends in the currently focused app. */
AppTimeTracker mCurAppTimeTracker;
- private AppWarnings mAppWarnings;
+ AppWarnings mAppWarnings;
/**
* Packages that the user has asked to have run in screen size
@@ -4388,46 +4388,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
- public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId) {
- mAmInternal.enforceCallingPermission(CHANGE_CONFIGURATION, "updateDisplayOverrideConfiguration()");
-
- synchronized (mGlobalLock) {
- // Check if display is initialized in AM.
- if (!mRootActivityContainer.isDisplayAdded(displayId)) {
- // Call might come when display is not yet added or has already been removed.
- if (DEBUG_CONFIGURATION) {
- Slog.w(TAG, "Trying to update display configuration for non-existing displayId="
- + displayId);
- }
- return false;
- }
-
- if (values == null && mWindowManager != null) {
- // sentinel: fetch the current configuration from the window manager
- values = mWindowManager.computeNewConfiguration(displayId);
- }
-
- if (mWindowManager != null) {
- final Message msg = PooledLambda.obtainMessage(
- ActivityManagerInternal::updateOomLevelsForDisplay, mAmInternal, displayId);
- mH.sendMessage(msg);
- }
-
- final long origId = Binder.clearCallingIdentity();
- try {
- if (values != null) {
- Settings.System.clearConfiguration(values);
- }
- updateDisplayOverrideConfigurationLocked(values, null /* starting */,
- false /* deferResume */, displayId, mTmpUpdateConfigurationResult);
- return mTmpUpdateConfigurationResult.changes != 0;
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
-
- @Override
public boolean updateConfiguration(Configuration values) {
mAmInternal.enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()");
@@ -5165,8 +5125,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
/** Update default (global) configuration and notify listeners about changes. */
- private int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
+ int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
boolean persistent, int userId, boolean deferResume) {
+
+ final ActivityDisplay defaultDisplay =
+ mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
+
mTempConfig.setTo(getGlobalConfiguration());
final int changes = mTempConfig.updateFrom(values);
if (changes == 0) {
@@ -5174,7 +5138,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// setting WindowManagerService.mWaitingForConfig to true, it is important that we call
// performDisplayOverrideConfigUpdate in order to send the new display configuration
// (even if there are no actual changes) to unfreeze the window.
- performDisplayOverrideConfigUpdate(values, deferResume, DEFAULT_DISPLAY);
+ defaultDisplay.performDisplayOverrideConfigUpdate(values, deferResume);
return 0;
}
@@ -5272,79 +5236,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// Override configuration of the default display duplicates global config, so we need to
// update it also. This will also notify WindowManager about changes.
- performDisplayOverrideConfigUpdate(mRootActivityContainer.getConfiguration(), deferResume,
- DEFAULT_DISPLAY);
-
- return changes;
- }
-
- boolean updateDisplayOverrideConfigurationLocked(Configuration values, ActivityRecord starting,
- boolean deferResume, int displayId) {
- return updateDisplayOverrideConfigurationLocked(values, starting, deferResume /* deferResume */,
- displayId, null /* result */);
- }
+ defaultDisplay.performDisplayOverrideConfigUpdate(mRootActivityContainer.getConfiguration(),
+ deferResume);
- /**
- * Updates override configuration specific for the selected display. If no config is provided,
- * new one will be computed in WM based on current display info.
- */
- boolean updateDisplayOverrideConfigurationLocked(Configuration values,
- ActivityRecord starting, boolean deferResume, int displayId,
- ActivityTaskManagerService.UpdateConfigurationResult result) {
- int changes = 0;
- boolean kept = true;
-
- if (mWindowManager != null) {
- mWindowManager.deferSurfaceLayout();
- }
- try {
- if (values != null) {
- if (displayId == DEFAULT_DISPLAY) {
- // Override configuration of the default display duplicates global config, so
- // we're calling global config update instead for default display. It will also
- // apply the correct override config.
- changes = updateGlobalConfigurationLocked(values, false /* initLocale */,
- false /* persistent */, UserHandle.USER_NULL /* userId */, deferResume);
- } else {
- changes = performDisplayOverrideConfigUpdate(values, deferResume, displayId);
- }
- }
-
- kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
- } finally {
- if (mWindowManager != null) {
- mWindowManager.continueSurfaceLayout();
- }
- }
-
- if (result != null) {
- result.changes = changes;
- result.activityRelaunched = !kept;
- }
- return kept;
- }
-
- private int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume,
- int displayId) {
- mTempConfig.setTo(mRootActivityContainer.getDisplayOverrideConfiguration(displayId));
- final int changes = mTempConfig.updateFrom(values);
- if (changes != 0) {
- Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
- + mTempConfig + " for displayId=" + displayId);
- mRootActivityContainer.setDisplayOverrideConfiguration(mTempConfig, displayId);
-
- final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
- if (isDensityChange && displayId == DEFAULT_DISPLAY) {
- mAppWarnings.onDensityChanged();
-
- // Post message to start process to avoid possible deadlock of calling into AMS with
- // the ATMS lock held.
- final Message msg = PooledLambda.obtainMessage(
- ActivityManagerInternal::killAllBackgroundProcessesExcept, mAmInternal,
- N, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
- mH.sendMessage(msg);
- }
- }
return changes;
}
@@ -5786,7 +5680,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
/** Applies latest configuration and/or visibility updates if needed. */
- private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
+ boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
boolean kept = true;
final ActivityStack mainStack = mRootActivityContainer.getTopDisplayFocusedStack();
// mainStack is null during startup.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4f72d1468bda..e2d592826a3a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1213,10 +1213,29 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
/** Notify the configuration change of this display. */
- void sendNewConfiguration() {
+ void postNewConfigurationToHandler() {
mWmService.mH.obtainMessage(SEND_NEW_CONFIGURATION, this).sendToTarget();
}
+ void sendNewConfiguration() {
+ synchronized (mWmService.mGlobalLock) {
+ final boolean configUpdated = mAcitvityDisplay
+ .updateDisplayOverrideConfigurationLocked();
+ if (!configUpdated) {
+ // Something changed (E.g. device rotation), but no configuration update is needed.
+ // E.g. changing device rotation by 180 degrees. Go ahead and perform surface
+ // placement to unfreeze the display since we froze it when the rotation was updated
+ // in DisplayContent#updateRotationUnchecked.
+ if (mWaitingForConfig) {
+ mWaitingForConfig = false;
+ mWmService.mLastFinishedFreezeSource = "config-unchanged";
+ setLayoutNeeded();
+ mWmService.mWindowPlacerLocked.performSurfacePlacement();
+ }
+ }
+ }
+ }
+
@Override
boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
ConfigurationContainer requestingContainer) {
@@ -1232,8 +1251,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (handled && requestingContainer instanceof ActivityRecord) {
final ActivityRecord activityRecord = (ActivityRecord) requestingContainer;
- final boolean kept = mWmService.mAtmService.updateDisplayOverrideConfigurationLocked(
- config, activityRecord, false /* deferResume */, getDisplayId());
+ final boolean kept = mAcitvityDisplay.updateDisplayOverrideConfigurationLocked(
+ config, activityRecord, false /* deferResume */, null /* result */);
activityRecord.frozenBeforeDestroy = true;
if (!kept) {
mWmService.mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
@@ -1241,8 +1260,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
} else {
// We have a new configuration to push so we need to update ATMS for now.
// TODO: Clean up display configuration push between ATMS and WMS after unification.
- mWmService.mAtmService.updateDisplayOverrideConfigurationLocked(
- config, null /* starting */, false /* deferResume */, getDisplayId());
+ mAcitvityDisplay.updateDisplayOverrideConfigurationLocked(
+ config, null /* starting */, false /* deferResume */, null);
}
return handled;
}
@@ -1332,7 +1351,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
boolean updateRotationAndSendNewConfigIfNeeded() {
final boolean changed = updateRotationUnchecked(false /* forceUpdate */);
if (changed) {
- sendNewConfiguration();
+ postNewConfigurationToHandler();
}
return changed;
}
@@ -1351,7 +1370,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* Update rotation of the DisplayContent with an option to force the update. This updates
* the container's perception of rotation and, depending on the top activities, will freeze
* the screen or start seamless rotation. The display itself gets rotated in
- * {@link #applyRotationLocked} during {@link WindowManagerService#sendNewConfiguration}.
+ * {@link #applyRotationLocked} during {@link DisplayContent#sendNewConfiguration}.
*
* @param forceUpdate Force the rotation update. Sometimes in WM we might skip updating
* orientation because we're waiting for some rotation to finish or display
@@ -3711,7 +3730,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
if (updateOrientationFromAppTokens()) {
setLayoutNeeded();
- sendNewConfiguration();
+ postNewConfigurationToHandler();
}
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 1d76a71aaea1..b1bc21977405 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -569,7 +569,6 @@ public class DockedStackDividerController {
mMaximizeMeetFraction = getClipRevealMeetFraction(stack);
animDuration = (long) (mAnimationDuration * mMaximizeMeetFraction);
}
- mService.mAtmInternal.notifyDockedStackMinimizedChanged(minimizedDock);
final int size = mDockedStackListeners.beginBroadcast();
for (int i = 0; i < size; ++i) {
final IDockedStackListener listener = mDockedStackListeners.getBroadcastItem(i);
@@ -581,6 +580,9 @@ public class DockedStackDividerController {
}
}
mDockedStackListeners.finishBroadcast();
+ // Only notify ATM after we update the remote listeners, otherwise it may trigger another
+ // minimize change, which would lead to an inversion of states send to the listeners
+ mService.mAtmInternal.notifyDockedStackMinimizedChanged(minimizedDock);
}
void notifyDockSideChanged(int newDockSide) {
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
index c0f53b819125..315de91f1b03 100644
--- a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
+++ b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
@@ -16,60 +16,102 @@
package com.android.server.wm;
+import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
+
import android.annotation.NonNull;
-import android.os.SystemProperties;
+import android.annotation.Nullable;
+import android.content.res.Resources;
+import android.provider.DeviceConfig;
import android.util.ArraySet;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+
+import java.io.PrintWriter;
+import java.util.concurrent.Executor;
/**
* A Blacklist for packages that should force the display out of high refresh rate.
*/
class HighRefreshRateBlacklist {
- private static final String SYSPROP_KEY = "ro.window_manager.high_refresh_rate_blacklist";
- private static final String SYSPROP_KEY_LENGTH_SUFFIX = "_length";
- private static final String SYSPROP_KEY_ENTRY_SUFFIX = "_entry";
- private static final int MAX_ENTRIES = 50;
+ private final ArraySet<String> mBlacklistedPackages = new ArraySet<>();
+ @NonNull
+ private final String[] mDefaultBlacklist;
+ private final Object mLock = new Object();
- private ArraySet<String> mBlacklistedPackages = new ArraySet<>();
-
- static HighRefreshRateBlacklist create() {
- return new HighRefreshRateBlacklist(new SystemPropertyGetter() {
+ static HighRefreshRateBlacklist create(@NonNull Resources r) {
+ return new HighRefreshRateBlacklist(r, new DeviceConfigInterface() {
@Override
- public int getInt(String key, int def) {
- return SystemProperties.getInt(key, def);
+ public @Nullable String getProperty(@NonNull String namespace, @NonNull String name) {
+ return DeviceConfig.getProperty(namespace, name);
}
-
- @Override
- public String get(String key) {
- return SystemProperties.get(key);
+ public void addOnPropertiesChangedListener(@NonNull String namespace,
+ @NonNull Executor executor,
+ @NonNull DeviceConfig.OnPropertiesChangedListener listener) {
+ DeviceConfig.addOnPropertiesChangedListener(namespace, executor, listener);
}
});
}
@VisibleForTesting
- HighRefreshRateBlacklist(SystemPropertyGetter propertyGetter) {
+ HighRefreshRateBlacklist(Resources r, DeviceConfigInterface deviceConfig) {
+ mDefaultBlacklist = r.getStringArray(R.array.config_highRefreshRateBlacklist);
+ deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ BackgroundThread.getExecutor(), new OnPropertiesChangedListener());
+ final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+ KEY_HIGH_REFRESH_RATE_BLACKLIST);
+ updateBlacklist(property);
+ }
- // Read and populate the blacklist
- final int length = Math.min(
- propertyGetter.getInt(SYSPROP_KEY + SYSPROP_KEY_LENGTH_SUFFIX, 0),
- MAX_ENTRIES);
- for (int i = 1; i <= length; i++) {
- final String packageName = propertyGetter.get(
- SYSPROP_KEY + SYSPROP_KEY_ENTRY_SUFFIX + i);
- if (!packageName.isEmpty()) {
- mBlacklistedPackages.add(packageName);
+ private void updateBlacklist(@Nullable String property) {
+ synchronized (mLock) {
+ mBlacklistedPackages.clear();
+ if (property != null) {
+ String[] packages = property.split(",");
+ for (String pkg : packages) {
+ String pkgName = pkg.trim();
+ if (!pkgName.isEmpty()) {
+ mBlacklistedPackages.add(pkgName);
+ }
+ }
+ } else {
+ // If there's no config, or the config has been deleted, fallback to the device's
+ // default blacklist
+ for (String pkg : mDefaultBlacklist) {
+ mBlacklistedPackages.add(pkg);
+ }
}
}
}
boolean isBlacklisted(String packageName) {
- return mBlacklistedPackages.contains(packageName);
+ synchronized (mLock) {
+ return mBlacklistedPackages.contains(packageName);
+ }
+ }
+ void dump(PrintWriter pw) {
+ pw.println("High Refresh Rate Blacklist");
+ pw.println(" Packages:");
+ synchronized (mLock) {
+ for (String pkg : mBlacklistedPackages) {
+ pw.println(" " + pkg);
+ }
+ }
}
- interface SystemPropertyGetter {
- int getInt(String key, int def);
- @NonNull String get(String key);
+ interface DeviceConfigInterface {
+ @Nullable String getProperty(@NonNull String namespace, @NonNull String name);
+ void addOnPropertiesChangedListener(@NonNull String namespace, @NonNull Executor executor,
+ @NonNull DeviceConfig.OnPropertiesChangedListener listener);
+ }
+
+ private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
+ public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+ updateBlacklist(
+ properties.getString(KEY_HIGH_REFRESH_RATE_BLACKLIST, null /*default*/));
+ }
}
}
+
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 6b500967f429..b16d9564ea7a 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -133,7 +133,7 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
@Override
public void notifyConfigurationChanged() {
// TODO(multi-display): Notify proper displays that are associated with this input device.
- mService.sendNewConfiguration(DEFAULT_DISPLAY);
+ mService.mRoot.getDisplayContent(DEFAULT_DISPLAY).sendNewConfiguration();
synchronized (mInputDevicesReadyMonitor) {
if (!mInputDevicesReady) {
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index d58c61368f9a..66d42db9b4dd 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -317,11 +317,6 @@ class RootActivityContainer extends ConfigurationContainer
return activityDisplay;
}
- /** Check if display with specified id is added to the list. */
- boolean isDisplayAdded(int displayId) {
- return getActivityDisplayOrCreate(displayId) != null;
- }
-
ActivityRecord getDefaultDisplayHomeActivity() {
return getDefaultDisplayHomeActivityForUser(mCurrentUser);
}
@@ -656,9 +651,13 @@ class RootActivityContainer extends ConfigurationContainer
starting.frozenBeforeDestroy = true;
}
- // Update the configuration of the activities on the display.
- return mService.updateDisplayOverrideConfigurationLocked(config, starting, deferResume,
- displayId);
+ if (displayContent != null && displayContent.mAcitvityDisplay != null) {
+ // Update the configuration of the activities on the display.
+ return displayContent.mAcitvityDisplay.updateDisplayOverrideConfigurationLocked(config,
+ starting, deferResume, null /* result */);
+ } else {
+ return true;
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index afd383616b64..f52bde9a035c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -856,7 +856,7 @@ public class WindowManagerService extends IWindowManager.Stub
final Configuration mTempConfiguration = new Configuration();
- final HighRefreshRateBlacklist mHighRefreshRateBlacklist = HighRefreshRateBlacklist.create();
+ final HighRefreshRateBlacklist mHighRefreshRateBlacklist;
// If true, only the core apps and services are being launched because the device
// is in a special boot mode, such as being encrypted or waiting for a decryption password.
@@ -1143,6 +1143,8 @@ public class WindowManagerService extends IWindowManager.Stub
this, mInputManager, mActivityTaskManager, mH.getLooper());
mDragDropController = new DragDropController(this, mH.getLooper());
+ mHighRefreshRateBlacklist = HighRefreshRateBlacklist.create(context.getResources());
+
mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
@@ -1607,10 +1609,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.isVisibleOrAdding() && displayContent.updateOrientationFromAppTokens()) {
reportNewConfig = true;
}
- }
- if (reportNewConfig) {
- sendNewConfiguration(displayId);
+ if (reportNewConfig) {
+ displayContent.sendNewConfiguration();
+ }
}
Binder.restoreCallingIdentity(origId);
@@ -1648,7 +1650,7 @@ public class WindowManagerService extends IWindowManager.Stub
final Display display = mDisplayManager.getDisplay(displayId);
if (display != null) {
- displayContent = mRoot.createDisplayContent(display, null /* controller */);
+ displayContent = mRoot.createDisplayContent(display, null /* activityDisplay */);
}
}
@@ -2290,13 +2292,15 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.v(TAG_WM, "Relayout complete " + win + ": outFrame=" + outFrame.toShortString());
}
win.mInRelayout = false;
- }
- if (configChanged) {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: sendNewConfiguration");
- sendNewConfiguration(displayId);
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ if (configChanged) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
+ "relayoutWindow: postNewConfigurationToHandler");
+ displayContent.sendNewConfiguration();
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ }
}
+
Binder.restoreCallingIdentity(origId);
return result;
}
@@ -3747,7 +3751,7 @@ public class WindowManagerService extends IWindowManager.Stub
layoutNeeded = true;
}
if (rotationChanged || alwaysSendConfiguration) {
- displayContent.sendNewConfiguration();
+ displayContent.postNewConfigurationToHandler();
}
}
@@ -4289,34 +4293,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- /**
- * Instruct the Activity Manager to fetch and update the current display's configuration and
- * broadcast them to config-changed listeners if appropriate.
- * NOTE: Can't be called with the window manager lock held since it call into activity manager.
- */
- void sendNewConfiguration(int displayId) {
- try {
- final boolean configUpdated = mActivityTaskManager.updateDisplayOverrideConfiguration(
- null /* values */, displayId);
- if (!configUpdated) {
- // Something changed (E.g. device rotation), but no configuration update is needed.
- // E.g. changing device rotation by 180 degrees. Go ahead and perform surface
- // placement to unfreeze the display since we froze it when the rotation was updated
- // in DisplayContent#updateRotationUnchecked.
- synchronized (mGlobalLock) {
- final DisplayContent dc = mRoot.getDisplayContent(displayId);
- if (dc != null && dc.mWaitingForConfig) {
- dc.mWaitingForConfig = false;
- mLastFinishedFreezeSource = "config-unchanged";
- dc.setLayoutNeeded();
- mWindowPlacerLocked.performSurfacePlacement();
- }
- }
- }
- } catch (RemoteException e) {
- }
- }
-
public Configuration computeNewConfiguration(int displayId) {
synchronized (mGlobalLock) {
return computeNewConfigurationLocked(displayId);
@@ -4740,7 +4716,7 @@ public class WindowManagerService extends IWindowManager.Stub
final DisplayContent displayContent = (DisplayContent) msg.obj;
removeMessages(SEND_NEW_CONFIGURATION, displayContent);
if (displayContent.isReady()) {
- sendNewConfiguration(displayContent.getDisplayId());
+ displayContent.sendNewConfiguration();
} else {
// Message could come after display has already been removed.
if (DEBUG_CONFIGURATION) {
@@ -5224,7 +5200,7 @@ public class WindowManagerService extends IWindowManager.Stub
displayContent.mWaitingForConfig = true;
startFreezingDisplayLocked(0 /* exitAnim */,
0 /* enterAnim */, displayContent);
- displayContent.sendNewConfiguration();
+ displayContent.postNewConfigurationToHandler();
}
mWindowPlacerLocked.performSurfacePlacement();
@@ -5571,7 +5547,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (configChanged) {
- displayContent.sendNewConfiguration();
+ displayContent.postNewConfigurationToHandler();
}
mLatencyTracker.onActionEnd(ACTION_ROTATE_SCREEN);
}
@@ -5923,6 +5899,12 @@ public class WindowManagerService extends IWindowManager.Stub
mRoot.dumpTokens(pw, dumpAll);
}
+
+ private void dumpHighRefreshRateBlacklist(PrintWriter pw) {
+ pw.println("WINDOW MANAGER HIGH REFRESH RATE BLACKLIST (dumpsys window refresh)");
+ mHighRefreshRateBlacklist.dump(pw);
+ }
+
private void dumpTraceStatus(PrintWriter pw) {
pw.println("WINDOW MANAGER TRACE (dumpsys window trace)");
pw.print(mWindowTracing.getStatus() + "\n");
@@ -6323,6 +6305,9 @@ public class WindowManagerService extends IWindowManager.Stub
} else if ("trace".equals(cmd)) {
dumpTraceStatus(pw);
return;
+ } else if ("refresh".equals(cmd)) {
+ dumpHighRefreshRateBlacklist(pw);
+ return;
} else {
// Dumping a single name?
if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
@@ -6378,6 +6363,10 @@ public class WindowManagerService extends IWindowManager.Stub
pw.println(separator);
}
dumpTraceStatus(pw);
+ if (dumpAll) {
+ pw.println(separator);
+ }
+ dumpHighRefreshRateBlacklist(pw);
}
}
@@ -6884,7 +6873,7 @@ public class WindowManagerService extends IWindowManager.Stub
final long origId = Binder.clearCallingIdentity();
try {
// direct call since lock is shared.
- sendNewConfiguration(displayId);
+ displayContent.sendNewConfiguration();
} finally {
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 189bff06f7fc..8b1baebbbbc0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2063,7 +2063,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (wasVisible) {
final DisplayContent displayContent = getDisplayContent();
if (displayContent.updateOrientationFromAppTokens()) {
- displayContent.sendNewConfiguration();
+ displayContent.postNewConfigurationToHandler();
}
}
mWmService.updateFocusedWindowLocked(isFocused()
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 48921eae0bf7..de8612aba81b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -228,7 +228,6 @@ import android.view.IWindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManager;
import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -9403,12 +9402,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
Preconditions.checkNotNull(who, "ComponentName is null");
-
- // TODO When InputMethodManager supports per user calls remove this restriction.
- if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
- && !checkCallerIsCurrentUserOrProfile()) {
- return false;
- }
final int callingUserId = mInjector.userHandleGetCallingUserId();
if (packageList != null) {
List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get()
@@ -9464,26 +9457,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int callingUserId = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
List<String> result = null;
- // If we have multiple profiles we return the intersection of the
- // permitted lists. This can happen in cases where we have a device
- // and profile owner.
- int[] profileIds = InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
- ? new int[]{callingUserId}
- : mUserManager.getProfileIdsWithDisabled(callingUserId);
- for (int profileId : profileIds) {
- // Just loop though all admins, only device or profiles
- // owners can have permitted lists set.
- DevicePolicyData policy = getUserDataUnchecked(profileId);
- final int N = policy.mAdminList.size();
- for (int j = 0; j < N; j++) {
- ActiveAdmin admin = policy.mAdminList.get(j);
- List<String> fromAdmin = admin.permittedInputMethods;
- if (fromAdmin != null) {
- if (result == null) {
- result = new ArrayList<String>(fromAdmin);
- } else {
- result.retainAll(fromAdmin);
- }
+ // Only device or profile owners can have permitted lists set.
+ DevicePolicyData policy = getUserDataUnchecked(callingUserId);
+ for (int i = 0; i < policy.mAdminList.size(); i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ List<String> fromAdmin = admin.permittedInputMethods;
+ if (fromAdmin != null) {
+ if (result == null) {
+ result = new ArrayList<String>(fromAdmin);
+ } else {
+ result.retainAll(fromAdmin);
}
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
index 699bec2c9329..261a83c4f67a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
@@ -33,7 +33,6 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.util.ArraySet;
import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSystemProperty;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -61,17 +60,11 @@ public class OverlayPackagesProvider {
@VisibleForTesting
interface Injector {
- boolean isPerProfileImeEnabled();
@NonNull
List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId);
}
private static final class DefaultInjector implements Injector {
- @Override
- public boolean isPerProfileImeEnabled() {
- return InputMethodSystemProperty.PER_PROFILE_IME_ENABLED;
- }
-
@NonNull
@Override
public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
@@ -108,13 +101,7 @@ public class OverlayPackagesProvider {
// Newly installed system apps are uninstalled when they are not required and are either
// disallowed or have a launcher icon.
nonRequiredApps.removeAll(getRequiredApps(provisioningAction, admin.getPackageName()));
- if (mInjector.isPerProfileImeEnabled()) {
- nonRequiredApps.removeAll(getSystemInputMethods(userId));
- } else if (ACTION_PROVISION_MANAGED_DEVICE.equals(provisioningAction)
- || ACTION_PROVISION_MANAGED_USER.equals(provisioningAction)) {
- // Don't delete the system input method packages in case of Device owner provisioning.
- nonRequiredApps.removeAll(getSystemInputMethods(userId));
- }
+ nonRequiredApps.removeAll(getSystemInputMethods(userId));
nonRequiredApps.addAll(getDisallowedApps(provisioningAction));
return nonRequiredApps;
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
index 757a046e9133..a3cc915b3eba 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
@@ -79,7 +79,6 @@ public class OverlayPackagesProviderTest extends AndroidTestCase {
InstrumentationRegistry.getTargetContext().getCacheDir());
setSystemInputMethods();
- setIsPerProfileModeEnabled(false);
setRequiredAppsManagedDevice();
setVendorRequiredAppsManagedDevice();
setDisallowedAppsManagedDevice();
@@ -164,15 +163,6 @@ public class OverlayPackagesProviderTest extends AndroidTestCase {
}
@Test
- public void testProfileOwnerImesAreRequiredForPerProfileImeMode() {
- setSystemAppsWithLauncher("app.a", "app.b");
- setSystemInputMethods("app.a");
- setIsPerProfileModeEnabled(true);
-
- verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_PROFILE, "app.b");
- }
-
- @Test
public void testManagedUserImesAreRequired() {
setSystemAppsWithLauncher("app.a", "app.b");
setSystemInputMethods("app.a");
@@ -344,10 +334,6 @@ public class OverlayPackagesProviderTest extends AndroidTestCase {
when(mInjector.getInputMethodListAsUser(eq(TEST_USER_ID))).thenReturn(inputMethods);
}
- private void setIsPerProfileModeEnabled(boolean enabled) {
- when(mInjector.isPerProfileImeEnabled()).thenReturn(enabled);
- }
-
private void setSystemAppsWithLauncher(String... apps) {
mSystemAppsWithLauncher = apps;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index d3f33a152734..43bcd4fc8436 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -36,7 +36,9 @@ import com.android.internal.util.FastXmlSerializer;
import libcore.io.IoUtils;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -56,6 +58,9 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
public class PackageInstallerSessionTest {
+ @Rule
+ public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
private File mTmpDir;
private AtomicFile mSessionsFile;
private static final String TAG_SESSIONS = "sessions";
@@ -65,7 +70,7 @@ public class PackageInstallerSessionTest {
@Before
public void setUp() throws Exception {
- mTmpDir = IoUtils.createTemporaryDirectory("PackageInstallerSessionTest");
+ mTmpDir = mTemporaryFolder.newFolder("PackageInstallerSessionTest");
mSessionsFile = new AtomicFile(
new File(mTmpDir.getAbsolutePath() + "/sessions.xml"), "package-session");
MockitoAnnotations.initMocks(this);
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 3c3721c6b20a..13a8eb1d7fad 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -43,13 +43,14 @@ import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import libcore.io.IoUtils;
-
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import java.io.File;
+import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
@@ -62,13 +63,16 @@ import java.util.Set;
@RunWith(AndroidJUnit4.class)
@MediumTest
public class PackageParserTest {
+ @Rule
+ public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
private File mTmpDir;
private static final File FRAMEWORK = new File("/system/framework/framework-res.apk");
@Before
- public void setUp() {
+ public void setUp() throws IOException {
// Create a new temporary directory for each of our tests.
- mTmpDir = IoUtils.createTemporaryDirectory("PackageParserTest");
+ mTmpDir = mTemporaryFolder.newFolder("PackageParserTest");
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java b/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java
deleted file mode 100644
index f80afb2ebbbf..000000000000
--- a/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.textservices;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.IntUnaryOperator;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class LazyIntToIntMapTest {
- @Test
- public void testLaziness() {
- final IntUnaryOperator func = mock(IntUnaryOperator.class);
- when(func.applyAsInt(eq(1))).thenReturn(11);
- when(func.applyAsInt(eq(2))).thenReturn(22);
-
- final LazyIntToIntMap map = new LazyIntToIntMap(func);
-
- verify(func, never()).applyAsInt(anyInt());
-
- assertEquals(22, map.get(2));
- verify(func, times(0)).applyAsInt(eq(1));
- verify(func, times(1)).applyAsInt(eq(2));
-
- // Accessing to the same key does not evaluate the function again.
- assertEquals(22, map.get(2));
- verify(func, times(0)).applyAsInt(eq(1));
- verify(func, times(1)).applyAsInt(eq(2));
- }
-
- @Test
- public void testDelete() {
- final IntUnaryOperator func1 = mock(IntUnaryOperator.class);
- when(func1.applyAsInt(eq(1))).thenReturn(11);
- when(func1.applyAsInt(eq(2))).thenReturn(22);
-
- final IntUnaryOperator func2 = mock(IntUnaryOperator.class);
- when(func2.applyAsInt(eq(1))).thenReturn(111);
- when(func2.applyAsInt(eq(2))).thenReturn(222);
-
- final AtomicReference<IntUnaryOperator> funcRef = new AtomicReference<>(func1);
- final LazyIntToIntMap map = new LazyIntToIntMap(i -> funcRef.get().applyAsInt(i));
-
- verify(func1, never()).applyAsInt(anyInt());
- verify(func2, never()).applyAsInt(anyInt());
-
- assertEquals(22, map.get(2));
- verify(func1, times(1)).applyAsInt(eq(2));
- verify(func2, times(0)).applyAsInt(eq(2));
-
- // Swap func1 with func2 then invalidate the key=2
- funcRef.set(func2);
- map.delete(2);
-
- // Calling get(2) again should re-evaluate the value.
- assertEquals(222, map.get(2));
- verify(func1, times(1)).applyAsInt(eq(2));
- verify(func2, times(1)).applyAsInt(eq(2));
-
- // Trying to delete non-existing keys does nothing.
- map.delete(1);
- }
-}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 9ecf19806f7f..f14e8d216cab 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -132,6 +132,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Xml;
+import android.widget.RemoteViews;
import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
@@ -174,6 +175,7 @@ import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@@ -348,12 +350,17 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mHandler = mService.new WorkerHandler(mTestableLooper.getLooper());
// MockPackageManager - default returns ApplicationInfo with matching calling UID
mContext.setMockPackageManager(mPackageManagerClient);
- final ApplicationInfo applicationInfo = new ApplicationInfo();
- applicationInfo.uid = mUid;
+
when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
- .thenReturn(applicationInfo);
+ .thenAnswer((Answer<ApplicationInfo>) invocation -> {
+ Object[] args = invocation.getArguments();
+ return getApplicationInfo((String) args[0], mUid);
+ });
when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
- .thenReturn(applicationInfo);
+ .thenAnswer((Answer<ApplicationInfo>) invocation -> {
+ Object[] args = invocation.getArguments();
+ return getApplicationInfo((String) args[0], mUid);
+ });
when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
final LightsManager mockLightsManager = mock(LightsManager.class);
when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
@@ -389,7 +396,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
-
mService.init(mTestableLooper.getLooper(),
mPackageManager, mPackageManagerClient, mockLightsManager,
mListeners, mAssistants, mConditionProviders,
@@ -413,12 +419,32 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@After
public void tearDown() throws Exception {
- mFile.delete();
+ if (mFile != null) mFile.delete();
clearDeviceConfig();
InstrumentationRegistry.getInstrumentation()
.getUiAutomation().dropShellPermissionIdentity();
}
+ private ApplicationInfo getApplicationInfo(String pkg, int uid) {
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.uid = uid;
+ switch (pkg) {
+ case PKG_N_MR1:
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+ break;
+ case PKG_O:
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
+ break;
+ case PKG_P:
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
+ break;
+ default:
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+ break;
+ }
+ return applicationInfo;
+ }
+
public void waitForIdle() {
mTestableLooper.processAllMessages();
}
@@ -5122,4 +5148,66 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertEquals(1, notifsAfter.length);
assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
}
+
+ @Test
+ public void testRemoveLargeRemoteViews() throws Exception {
+ int removeSize = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
+
+ RemoteViews rv = mock(RemoteViews.class);
+ when(rv.estimateMemoryUsage()).thenReturn(removeSize);
+ when(rv.clone()).thenReturn(rv);
+ RemoteViews rv1 = mock(RemoteViews.class);
+ when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
+ when(rv1.clone()).thenReturn(rv1);
+ RemoteViews rv2 = mock(RemoteViews.class);
+ when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
+ when(rv2.clone()).thenReturn(rv2);
+ RemoteViews rv3 = mock(RemoteViews.class);
+ when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
+ when(rv3.clone()).thenReturn(rv3);
+ RemoteViews rv4 = mock(RemoteViews.class);
+ when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
+ when(rv4.clone()).thenReturn(rv4);
+ // note: different!
+ RemoteViews rv5 = mock(RemoteViews.class);
+ when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
+ when(rv5.clone()).thenReturn(rv5);
+
+ Notification np = new Notification.Builder(mContext, "test")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .setContentText("test")
+ .setCustomContentView(rv)
+ .setCustomBigContentView(rv1)
+ .setCustomHeadsUpContentView(rv2)
+ .build();
+ Notification n = new Notification.Builder(mContext, "test")
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .setContentText("test")
+ .setCustomContentView(rv3)
+ .setCustomBigContentView(rv4)
+ .setCustomHeadsUpContentView(rv5)
+ .setPublicVersion(np)
+ .build();
+
+ assertNotNull(np.contentView);
+ assertNotNull(np.bigContentView);
+ assertNotNull(np.headsUpContentView);
+
+ assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
+ assertNotNull(n.publicVersion.contentView);
+ assertNotNull(n.publicVersion.bigContentView);
+ assertNotNull(n.publicVersion.headsUpContentView);
+
+ mService.fixNotification(n, PKG, "tag", 9, 0);
+
+ assertNull(n.contentView);
+ assertNull(n.bigContentView);
+ assertNotNull(n.headsUpContentView);
+ assertNull(n.publicVersion.contentView);
+ assertNull(n.publicVersion.bigContentView);
+ assertNull(n.publicVersion.headsUpContentView);
+
+ verify(mUsageStats, times(5)).registerImageRemoved(PKG);
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 7cd097ebdc2b..c5e7c47919fc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -668,8 +668,8 @@ public class DisplayContentTests extends WindowTestsBase {
dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
- verify(mWm.mAtmService).updateDisplayOverrideConfigurationLocked(captor.capture(),
- same(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
+ verify(dc.mAcitvityDisplay).updateDisplayOverrideConfigurationLocked(captor.capture(),
+ same(activityRecord), anyBoolean(), same(null));
final Configuration newDisplayConfig = captor.getValue();
assertEquals(Configuration.ORIENTATION_PORTRAIT, newDisplayConfig.orientation);
}
@@ -693,8 +693,8 @@ public class DisplayContentTests extends WindowTestsBase {
assertFalse("Display shouldn't rotate to handle orientation request if fixed to"
+ " user rotation.",
dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
- verify(mWm.mAtmService, never()).updateDisplayOverrideConfigurationLocked(any(),
- eq(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
+ verify(dc.mAcitvityDisplay, never()).updateDisplayOverrideConfigurationLocked(any(),
+ eq(activityRecord), anyBoolean(), same(null));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
index 558672609304..daee9110543d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
@@ -16,71 +16,168 @@
package com.android.server.wm;
+import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
+
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import android.content.res.Resources;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
+import android.util.Pair;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
-import com.android.server.wm.HighRefreshRateBlacklist.SystemPropertyGetter;
+import com.android.internal.R;
+import com.android.server.wm.HighRefreshRateBlacklist.DeviceConfigInterface;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
/**
* Build/Install/Run:
- * atest WmTests:HighRefreshRateBlacklistTest
+ * atest WmTests:HighRefreshRateBlacklistTest
*/
@SmallTest
@Presubmit
-@FlakyTest
public class HighRefreshRateBlacklistTest {
@Test
- public void testBlacklist() {
- HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(
- new SystemPropertyGetter() {
-
- @Override
- public int getInt(String key, int def) {
- if ("ro.window_manager.high_refresh_rate_blacklist_length".equals(key)) {
- return 2;
- }
- return def;
- }
-
- @Override
- public String get(String key) {
- if ("ro.window_manager.high_refresh_rate_blacklist_entry1".equals(key)) {
- return "com.android.sample1";
- }
- if ("ro.window_manager.high_refresh_rate_blacklist_entry2".equals(key)) {
- return "com.android.sample2";
- }
- return "";
- }
- });
+ public void testDefaultBlacklist() {
+ final Resources r = createResources("com.android.sample1", "com.android.sample2");
+ HighRefreshRateBlacklist blacklist =
+ new HighRefreshRateBlacklist(r, new FakeDeviceConfigInterface());
assertTrue(blacklist.isBlacklisted("com.android.sample1"));
assertTrue(blacklist.isBlacklisted("com.android.sample2"));
assertFalse(blacklist.isBlacklisted("com.android.sample3"));
}
@Test
- public void testNoBlacklist() {
- HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(
- new SystemPropertyGetter() {
-
- @Override
- public int getInt(String key, int def) {
- return def;
- }
-
- @Override
- public String get(String key) {
- return "";
- }
- });
+ public void testNoDefaultBlacklist() {
+ final Resources r = createResources();
+ HighRefreshRateBlacklist blacklist =
+ new HighRefreshRateBlacklist(r, new FakeDeviceConfigInterface());
+ assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+ }
+
+ @Test
+ public void testDefaultBlacklistIsOverriddenByDeviceConfig() {
+ final Resources r = createResources("com.android.sample1");
+ final FakeDeviceConfigInterface config = new FakeDeviceConfigInterface();
+ config.setBlacklist("com.android.sample2,com.android.sample3");
+ HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(r, config);
+ assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+ assertTrue(blacklist.isBlacklisted("com.android.sample2"));
+ assertTrue(blacklist.isBlacklisted("com.android.sample3"));
+ }
+
+ @Test
+ public void testDefaultBlacklistIsOverriddenByEmptyDeviceConfig() {
+ final Resources r = createResources("com.android.sample1");
+ final FakeDeviceConfigInterface config = new FakeDeviceConfigInterface();
+ config.setBlacklist("");
+ HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(r, config);
+ assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+ }
+
+ @Test
+ public void testDefaultBlacklistIsOverriddenByDeviceConfigUpdate() {
+ final Resources r = createResources("com.android.sample1");
+ final FakeDeviceConfigInterface config = new FakeDeviceConfigInterface();
+ HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(r, config);
+
+ // First check that the default blacklist is in effect
+ assertTrue(blacklist.isBlacklisted("com.android.sample1"));
+ assertFalse(blacklist.isBlacklisted("com.android.sample2"));
+ assertFalse(blacklist.isBlacklisted("com.android.sample3"));
+
+ // Then confirm that the DeviceConfig list has propagated and taken effect.
+ config.setBlacklist("com.android.sample2,com.android.sample3");
assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+ assertTrue(blacklist.isBlacklisted("com.android.sample2"));
+ assertTrue(blacklist.isBlacklisted("com.android.sample3"));
+
+ // Finally make sure we go back to the default list if the DeviceConfig gets deleted.
+ config.setBlacklist(null);
+ assertTrue(blacklist.isBlacklisted("com.android.sample1"));
+ assertFalse(blacklist.isBlacklisted("com.android.sample2"));
+ assertFalse(blacklist.isBlacklisted("com.android.sample3"));
+ }
+
+ private Resources createResources(String... defaultBlacklist) {
+ Resources r = mock(Resources.class);
+ when(r.getStringArray(R.array.config_highRefreshRateBlacklist))
+ .thenReturn(defaultBlacklist);
+ return r;
+ }
+
+
+ class FakeDeviceConfigInterface implements DeviceConfigInterface {
+ private List<Pair<DeviceConfig.OnPropertiesChangedListener, Executor>> mListeners =
+ new ArrayList<>();
+ private String mBlacklist;
+
+ @Override
+ public String getProperty(String namespace, String name) {
+ if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)
+ || !KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(name)) {
+ throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
+ + "supported.");
+ }
+ return mBlacklist;
+ }
+
+ @Override
+ public void addOnPropertiesChangedListener(String namespace, Executor executor,
+ DeviceConfig.OnPropertiesChangedListener listener) {
+
+ if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)) {
+ throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
+ + "supported.");
+ }
+ mListeners.add(new Pair<>(listener, executor));
+ }
+
+ void setBlacklist(String blacklist) {
+ mBlacklist = blacklist;
+ CountDownLatch latch = new CountDownLatch(mListeners.size());
+ for (Pair<DeviceConfig.OnPropertiesChangedListener, Executor> listenerInfo :
+ mListeners) {
+ final Executor executor = listenerInfo.second;
+ final DeviceConfig.OnPropertiesChangedListener listener = listenerInfo.first;
+ DeviceConfig.Properties properties = createBlacklistProperties(blacklist);
+ executor.execute(() -> {
+ listener.onPropertiesChanged(properties);
+ latch.countDown();
+ });
+ }
+ try {
+ latch.await(10, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Failed to notify all blacklist listeners in time.", e);
+ }
+ }
+
+ private DeviceConfig.Properties createBlacklistProperties(final String blacklist) {
+ DeviceConfig.Properties properties = mock(DeviceConfig.Properties.class);
+ when(properties.getString(anyString(), any())).thenAnswer(invocation -> {
+ final Object[] args = invocation.getArguments();
+ if (KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(args[0])) {
+ return blacklist;
+ } else {
+ return args[1];
+ }
+ });
+ return properties;
+ }
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 7c4198857b5e..7f7a78bd1d17 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -909,6 +909,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
if (!mScreenLocked && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
// If the screen is unlocked, also set current functions.
setScreenUnlockedFunctions();
+ } else {
+ setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
}
break;
case MSG_UPDATE_SCREEN_LOCK:
diff --git a/startop/apps/ColorChanging/.gitignore b/startop/apps/ColorChanging/.gitignore
new file mode 100644
index 000000000000..2b75303ac58f
--- /dev/null
+++ b/startop/apps/ColorChanging/.gitignore
@@ -0,0 +1,13 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
diff --git a/startop/apps/ColorChanging/.idea/encodings.xml b/startop/apps/ColorChanging/.idea/encodings.xml
new file mode 100644
index 000000000000..15a15b218a29
--- /dev/null
+++ b/startop/apps/ColorChanging/.idea/encodings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="Encoding" addBOMForNewFiles="with NO BOM" />
+</project> \ No newline at end of file
diff --git a/startop/apps/ColorChanging/.idea/gradle.xml b/startop/apps/ColorChanging/.idea/gradle.xml
new file mode 100644
index 000000000000..2996d531255e
--- /dev/null
+++ b/startop/apps/ColorChanging/.idea/gradle.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="GradleSettings">
+ <option name="linkedExternalProjectsSettings">
+ <GradleProjectSettings>
+ <compositeConfiguration>
+ <compositeBuild compositeDefinitionSource="SCRIPT" />
+ </compositeConfiguration>
+ <option name="distributionType" value="DEFAULT_WRAPPED" />
+ <option name="externalProjectPath" value="$PROJECT_DIR$" />
+ <option name="resolveModulePerSourceSet" value="false" />
+ </GradleProjectSettings>
+ </option>
+ </component>
+</project> \ No newline at end of file
diff --git a/startop/apps/ColorChanging/.idea/misc.xml b/startop/apps/ColorChanging/.idea/misc.xml
new file mode 100644
index 000000000000..37a750962da6
--- /dev/null
+++ b/startop/apps/ColorChanging/.idea/misc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/build/classes" />
+ </component>
+ <component name="ProjectType">
+ <option name="id" value="Android" />
+ </component>
+</project> \ No newline at end of file
diff --git a/startop/apps/ColorChanging/.idea/runConfigurations.xml b/startop/apps/ColorChanging/.idea/runConfigurations.xml
new file mode 100644
index 000000000000..7f68460d8b38
--- /dev/null
+++ b/startop/apps/ColorChanging/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="RunConfigurationProducerService">
+ <option name="ignoredProducers">
+ <set>
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+ <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+ </set>
+ </option>
+ </component>
+</project> \ No newline at end of file
diff --git a/startop/apps/ColorChanging/README.md b/startop/apps/ColorChanging/README.md
new file mode 100644
index 000000000000..eb8b9cc1103b
--- /dev/null
+++ b/startop/apps/ColorChanging/README.md
@@ -0,0 +1,5 @@
+This directory contains a simple Android app that is meant to help in
+syncing a trace along with a video in Perfetto.
+
+This app changes the colors of the screen that has traces to go along
+with the colors.
diff --git a/startop/apps/ColorChanging/app/.gitignore b/startop/apps/ColorChanging/app/.gitignore
new file mode 100644
index 000000000000..796b96d1c402
--- /dev/null
+++ b/startop/apps/ColorChanging/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/startop/apps/ColorChanging/app/build.gradle b/startop/apps/ColorChanging/app/build.gradle
new file mode 100644
index 000000000000..ab955aaf90ee
--- /dev/null
+++ b/startop/apps/ColorChanging/app/build.gradle
@@ -0,0 +1,29 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.0"
+ defaultConfig {
+ applicationId "com.android.startop.colorchanging"
+ minSdkVersion 15
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test:runner:1.2.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+}
diff --git a/startop/apps/ColorChanging/app/proguard-rules.pro b/startop/apps/ColorChanging/app/proguard-rules.pro
new file mode 100644
index 000000000000..f1b424510da5
--- /dev/null
+++ b/startop/apps/ColorChanging/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/startop/apps/ColorChanging/app/src/androidTest/java/com/android/startop/colorchanging/ExampleInstrumentedTest.java b/startop/apps/ColorChanging/app/src/androidTest/java/com/android/startop/colorchanging/ExampleInstrumentedTest.java
new file mode 100644
index 000000000000..31736f3e2862
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/androidTest/java/com/android/startop/colorchanging/ExampleInstrumentedTest.java
@@ -0,0 +1,27 @@
+package com.android.startop.colorchanging;
+
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("com.android.startop.colorchanging", appContext.getPackageName());
+ }
+}
diff --git a/startop/apps/ColorChanging/app/src/main/AndroidManifest.xml b/startop/apps/ColorChanging/app/src/main/AndroidManifest.xml
new file mode 100644
index 000000000000..37193b5ff596
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.startop.colorchanging">
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+ <activity android:name="com.android.startop.colorchanging.MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest> \ No newline at end of file
diff --git a/startop/apps/ColorChanging/app/src/main/java/com/android/startop/colorchanging/MainActivity.java b/startop/apps/ColorChanging/app/src/main/java/com/android/startop/colorchanging/MainActivity.java
new file mode 100644
index 000000000000..b8f4faf299a9
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/java/com/android/startop/colorchanging/MainActivity.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.startop.colorchanging;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.os.Bundle;
+import android.os.Trace;
+import android.view.View;
+
+public class MainActivity extends AppCompatActivity {
+ View view;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ view = this.getWindow().getDecorView();
+ view.setBackgroundResource(R.color.gray);
+ Trace.beginSection("gray");
+ }
+
+ public void goRed(View v) {
+ Trace.endSection();
+ view.setBackgroundResource(R.color.red);
+ Trace.beginSection("red");
+ }
+
+ public void goOrange(View v) {
+ Trace.endSection();
+ view.setBackgroundResource(R.color.orange);
+ Trace.beginSection("orange");
+ }
+
+ public void goYellow(View v) {
+ Trace.endSection();
+ view.setBackgroundResource(R.color.yellow);
+ Trace.beginSection("yellow");
+ }
+
+ public void goGreen(View v) {
+ Trace.endSection();
+ view.setBackgroundResource(R.color.green);
+ Trace.beginSection("green");
+ }
+
+ public void goBlue(View v) {
+ Trace.endSection();
+ view.setBackgroundResource(R.color.blue);
+ Trace.beginSection("blue");
+ }
+
+ public void goIndigo(View v) {
+ Trace.endSection();
+ view.setBackgroundResource(R.color.indigo);
+ Trace.beginSection("indigo");
+ }
+
+ public void goViolet(View v) {
+ Trace.endSection();
+ view.setBackgroundResource(R.color.violet);
+ Trace.beginSection("violet");
+ }
+
+ public void goCyan(View v) {
+ Trace.endSection();
+ view.setBackgroundResource(R.color.cyan);
+ Trace.beginSection("cyan");
+ }
+
+ public void goBlack(View v) {
+ Trace.endSection();
+ view.setBackgroundResource(R.color.black);
+ Trace.beginSection("black");
+ }
+
+}
diff --git a/startop/apps/ColorChanging/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/startop/apps/ColorChanging/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 000000000000..1f6bb290603d
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path
+ android:fillType="evenOdd"
+ android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
+ android:strokeWidth="1"
+ android:strokeColor="#00000000">
+ <aapt:attr name="android:fillColor">
+ <gradient
+ android:endX="78.5885"
+ android:endY="90.9159"
+ android:startX="48.7653"
+ android:startY="61.0927"
+ android:type="linear">
+ <item
+ android:color="#44000000"
+ android:offset="0.0" />
+ <item
+ android:color="#00000000"
+ android:offset="1.0" />
+ </gradient>
+ </aapt:attr>
+ </path>
+ <path
+ android:fillColor="#FFFFFF"
+ android:fillType="nonZero"
+ android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
+ android:strokeWidth="1"
+ android:strokeColor="#00000000" />
+</vector>
diff --git a/startop/apps/ColorChanging/app/src/main/res/drawable/ic_launcher_background.xml b/startop/apps/ColorChanging/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 000000000000..0d025f9bf6b6
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path
+ android:fillColor="#008577"
+ android:pathData="M0,0h108v108h-108z" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M9,0L9,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,0L19,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,0L29,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,0L39,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,0L49,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,0L59,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,0L69,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,0L79,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M89,0L89,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M99,0L99,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,9L108,9"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,19L108,19"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,29L108,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,39L108,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,49L108,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,59L108,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,69L108,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,79L108,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,89L108,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,99L108,99"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,29L89,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,39L89,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,49L89,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,59L89,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,69L89,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,79L89,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,19L29,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,19L39,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,19L49,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,19L59,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,19L69,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,19L79,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+</vector>
diff --git a/startop/apps/ColorChanging/app/src/main/res/layout/activity_main.xml b/startop/apps/ColorChanging/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 000000000000..fb18df79cce2
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity">
+
+ <Button
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginTop="16dp"
+ android:onClick="goRed"
+ android:text="red"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <Button
+ android:id="@+id/button4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="16dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginRight="16dp"
+ android:onClick="goYellow"
+ android:text="YELLOW"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <Button
+ android:id="@+id/button6"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginTop="32dp"
+ android:onClick="goGreen"
+ android:text="GREEN"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/button" />
+
+ <Button
+ android:id="@+id/button7"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="165dp"
+ android:layout_marginLeft="165dp"
+ android:layout_marginTop="115dp"
+ android:layout_marginEnd="165dp"
+ android:layout_marginRight="165dp"
+ android:onClick="goViolet"
+ android:text="VIOLET"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.428"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/button8" />
+
+ <Button
+ android:id="@+id/button10"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="165dp"
+ android:layout_marginLeft="165dp"
+ android:layout_marginTop="32dp"
+ android:layout_marginEnd="165dp"
+ android:layout_marginRight="165dp"
+ android:onClick="goBlue"
+ android:text="BLUE"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/button8" />
+
+ <Button
+ android:id="@+id/button8"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="165dp"
+ android:layout_marginLeft="165dp"
+ android:layout_marginTop="16dp"
+ android:layout_marginEnd="165dp"
+ android:layout_marginRight="165dp"
+ android:onClick="goOrange"
+ android:text="ORANGE"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <Button
+ android:id="@+id/button11"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="32dp"
+ android:layout_marginEnd="16dp"
+ android:layout_marginRight="16dp"
+ android:onClick="goIndigo"
+ android:text="INDIGO"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/button4" />
+
+ <Button
+ android:id="@+id/button12"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="162dp"
+ android:layout_marginLeft="162dp"
+ android:layout_marginTop="25dp"
+ android:layout_marginEnd="161dp"
+ android:layout_marginRight="161dp"
+ android:onClick="goCyan"
+ android:text="CYAN"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/button7" />
+
+ <Button
+ android:id="@+id/button13"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="162dp"
+ android:layout_marginLeft="162dp"
+ android:layout_marginTop="25dp"
+ android:layout_marginEnd="161dp"
+ android:layout_marginRight="161dp"
+ android:onClick="goBlack"
+ android:text="BLACK"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/button12" />
+</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 000000000000..eca70cfe52ea
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon> \ No newline at end of file
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 000000000000..eca70cfe52ea
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon> \ No newline at end of file
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000000..898f3ed59ac9
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 000000000000..dffca3601eba
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000000..64ba76f75e9c
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 000000000000..dae5e082342f
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000000..e5ed46597ea8
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 000000000000..14ed0af35023
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000000..b0907cac3bfd
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 000000000000..d8ae03154975
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000000..2c18de9e6610
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 000000000000..beed3cdd2c32
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/values/colors.xml b/startop/apps/ColorChanging/app/src/main/res/values/colors.xml
new file mode 100644
index 000000000000..209790fed1cd
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/values/colors.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#008577</color>
+ <color name="colorPrimaryDark">#00574B</color>
+ <color name="colorAccent">#D81B60</color>
+ <color name="black">#000000</color>
+ <color name="red">#F44336</color>
+ <color name="green">#2CF035</color>
+ <color name="blue">#2C70F0</color>
+ <color name="yellow">#F0EA2C</color>
+ <color name="gray">#D3D3D3</color>
+ <color name="orange">#E57E0A</color>
+ <color name="indigo">#4B0082</color>
+ <color name="violet">#EE82EE</color>
+ <color name="cyan">#00E8FF</color>
+</resources>
diff --git a/startop/apps/ColorChanging/app/src/main/res/values/strings.xml b/startop/apps/ColorChanging/app/src/main/res/values/strings.xml
new file mode 100644
index 000000000000..ff062fb274bf
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+ <string name="app_name">ColorChanging</string>
+</resources>
diff --git a/startop/apps/ColorChanging/app/src/main/res/values/styles.xml b/startop/apps/ColorChanging/app/src/main/res/values/styles.xml
new file mode 100644
index 000000000000..5885930df6d1
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="colorPrimary">@color/colorPrimary</item>
+ <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="colorAccent">@color/colorAccent</item>
+ </style>
+
+</resources>
diff --git a/startop/apps/ColorChanging/app/src/test/java/com/android/startop/colorchanging/ExampleUnitTest.java b/startop/apps/ColorChanging/app/src/test/java/com/android/startop/colorchanging/ExampleUnitTest.java
new file mode 100644
index 000000000000..8423674b9d75
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/test/java/com/android/startop/colorchanging/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.android.startop.colorchanging;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+} \ No newline at end of file
diff --git a/startop/apps/ColorChanging/build.gradle b/startop/apps/ColorChanging/build.gradle
new file mode 100644
index 000000000000..a960ab34dc6e
--- /dev/null
+++ b/startop/apps/ColorChanging/build.gradle
@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ google()
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.4.1'
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/startop/apps/ColorChanging/gradle.properties b/startop/apps/ColorChanging/gradle.properties
new file mode 100644
index 000000000000..199d16ede38c
--- /dev/null
+++ b/startop/apps/ColorChanging/gradle.properties
@@ -0,0 +1,20 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+
diff --git a/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.jar b/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000000..f6b961fd5a86
--- /dev/null
+++ b/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.properties b/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000000..09f2718ae856
--- /dev/null
+++ b/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Jun 17 13:40:58 PDT 2019
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/startop/apps/ColorChanging/gradlew b/startop/apps/ColorChanging/gradlew
new file mode 100755
index 000000000000..cccdd3d517fc
--- /dev/null
+++ b/startop/apps/ColorChanging/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/startop/apps/ColorChanging/gradlew.bat b/startop/apps/ColorChanging/gradlew.bat
new file mode 100644
index 000000000000..e95643d6a2ca
--- /dev/null
+++ b/startop/apps/ColorChanging/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/startop/apps/ColorChanging/settings.gradle b/startop/apps/ColorChanging/settings.gradle
new file mode 100644
index 000000000000..e7b4def49cb5
--- /dev/null
+++ b/startop/apps/ColorChanging/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 22a8232d1a0b..ed70a81e01d6 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10834,7 +10834,6 @@ public class TelephonyManager {
* @param callback Callback will be triggered once it succeeds or failed.
* See {@link TelephonyManager.SetOpportunisticSubscriptionResult}
* for more details. Pass null if don't care about the result.
- *
*/
public void setPreferredOpportunisticDataSubscription(int subId, boolean needValidation,
@Nullable @CallbackExecutor Executor executor, @Nullable Consumer<Integer> callback) {
@@ -10842,6 +10841,12 @@ public class TelephonyManager {
try {
IOns iOpportunisticNetworkService = getIOns();
if (iOpportunisticNetworkService == null) {
+ if (executor == null || callback == null) {
+ return;
+ }
+ Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+ callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+ }));
return;
}
ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
@@ -10923,9 +10928,16 @@ public class TelephonyManager {
if (executor == null || callback == null) {
return;
}
- Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
- callback.accept(UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
- }));
+ if (iOpportunisticNetworkService == null) {
+ /* Todo<b/130595455> passing unknown due to lack of good error codes */
+ Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+ callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
+ }));
+ } else {
+ Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+ callback.accept(UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
+ }));
+ }
return;
}
IUpdateAvailableNetworksCallback callbackStub =
diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
index a87e2f57bb5f..cc260ac14147 100644
--- a/test-mock/api/test-current.txt
+++ b/test-mock/api/test-current.txt
@@ -7,6 +7,7 @@ package android.test.mock {
}
@Deprecated public class MockPackageManager extends android.content.pm.PackageManager {
+ method public void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public boolean arePermissionsIndividuallyControlled();
method public String getDefaultBrowserPackageNameAsUser(int);
method public int getInstallReason(String, android.os.UserHandle);
@@ -18,6 +19,7 @@ package android.test.mock {
method @NonNull public String getServicesSystemSharedLibraryPackageName();
method @NonNull public String getSharedSystemSharedLibraryPackageName();
method public void grantRuntimePermission(String, String, android.os.UserHandle);
+ method public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public void revokeRuntimePermission(String, String, android.os.UserHandle);
method public void updatePermissionFlags(String, String, int, int, android.os.UserHandle);
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 1b2a12887aa5..5cc95d9f2bc3 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -208,6 +208,8 @@ import com.android.server.net.NetworkPinner;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.testutils.ExceptionUtils;
import com.android.testutils.HandlerUtilsKt;
+import com.android.testutils.RecorderCallback.CallbackRecord;
+import com.android.testutils.TestableNetworkCallback;
import org.junit.After;
import org.junit.Before;
@@ -234,7 +236,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
-import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
@@ -243,7 +244,8 @@ import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Predicate;
+
+import kotlin.reflect.KClass;
/**
* Tests for {@link ConnectivityService}.
@@ -467,7 +469,7 @@ public class ConnectivityServiceTest {
fail("expected race condition at least once in " + attempts + " attempts");
}
- private class MockNetworkAgent {
+ private class MockNetworkAgent implements TestableNetworkCallback.HasNetwork {
private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS
| NETWORK_VALIDATION_PROBE_HTTP
| NETWORK_VALIDATION_PROBE_HTTPS;
@@ -1703,281 +1705,33 @@ public class ConnectivityServiceTest {
mCm.getDefaultRequest().networkCapabilities));
}
- enum CallbackState {
- NONE,
- AVAILABLE,
- NETWORK_CAPABILITIES,
- LINK_PROPERTIES,
- SUSPENDED,
- RESUMED,
- LOSING,
- LOST,
- UNAVAILABLE,
- BLOCKED_STATUS
- }
-
- private static class CallbackInfo {
- public final CallbackState state;
- public final Network network;
- public final Object arg;
- public CallbackInfo(CallbackState s, Network n, Object o) {
- state = s; network = n; arg = o;
- }
- public String toString() {
- return String.format("%s (%s) (%s)", state, network, arg);
- }
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof CallbackInfo)) return false;
- // Ignore timeMs, since it's unpredictable.
- CallbackInfo other = (CallbackInfo) o;
- return (state == other.state) && Objects.equals(network, other.network);
- }
- @Override
- public int hashCode() {
- return Objects.hash(state, network);
- }
- }
-
/**
* Utility NetworkCallback for testing. The caller must explicitly test for all the callbacks
* this class receives, by calling expectCallback() exactly once each time a callback is
* received. assertNoCallback may be called at any time.
*/
- private class TestNetworkCallback extends NetworkCallback {
- private final LinkedBlockingQueue<CallbackInfo> mCallbacks = new LinkedBlockingQueue<>();
- private Network mLastAvailableNetwork;
-
- protected void setLastCallback(CallbackState state, Network network, Object o) {
- mCallbacks.offer(new CallbackInfo(state, network, o));
- }
-
- @Override
- public void onAvailable(Network network) {
- mLastAvailableNetwork = network;
- setLastCallback(CallbackState.AVAILABLE, network, null);
- }
-
- @Override
- public void onCapabilitiesChanged(Network network, NetworkCapabilities netCap) {
- setLastCallback(CallbackState.NETWORK_CAPABILITIES, network, netCap);
- }
-
- @Override
- public void onLinkPropertiesChanged(Network network, LinkProperties linkProp) {
- setLastCallback(CallbackState.LINK_PROPERTIES, network, linkProp);
- }
-
+ private class TestNetworkCallback extends TestableNetworkCallback {
@Override
- public void onUnavailable() {
- setLastCallback(CallbackState.UNAVAILABLE, null, null);
- }
-
- @Override
- public void onNetworkSuspended(Network network) {
- setLastCallback(CallbackState.SUSPENDED, network, null);
- }
-
- @Override
- public void onNetworkResumed(Network network) {
- setLastCallback(CallbackState.RESUMED, network, null);
- }
-
- @Override
- public void onLosing(Network network, int maxMsToLive) {
- setLastCallback(CallbackState.LOSING, network, maxMsToLive /* autoboxed int */);
- }
-
- @Override
- public void onLost(Network network) {
- mLastAvailableNetwork = null;
- setLastCallback(CallbackState.LOST, network, null);
+ public void assertNoCallback() {
+ // TODO: better support this use case in TestableNetworkCallback
+ waitForIdle();
+ assertNoCallback(0 /* timeout */);
}
@Override
- public void onBlockedStatusChanged(Network network, boolean blocked) {
- setLastCallback(CallbackState.BLOCKED_STATUS, network, blocked);
- }
-
- public Network getLastAvailableNetwork() {
- return mLastAvailableNetwork;
- }
-
- CallbackInfo nextCallback(int timeoutMs) throws InterruptedException {
- CallbackInfo cb = null;
- cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
- if (cb == null) {
- // LinkedBlockingQueue.poll() returns null if it timeouts.
- fail("Did not receive callback after " + timeoutMs + "ms");
- }
- return cb;
- }
-
- CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs)
- throws Exception {
- final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
- CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
- CallbackInfo actual = nextCallback(timeoutMs);
- assertEquals("Unexpected callback:", expected, actual);
-
- if (state == CallbackState.LOSING) {
+ public <T extends CallbackRecord> T expectCallback(final KClass<T> type, final HasNetwork n,
+ final long timeoutMs) {
+ final T callback = super.expectCallback(type, n, timeoutMs);
+ if (callback instanceof CallbackRecord.Losing) {
+ // TODO : move this to the specific test(s) needing this rather than here.
+ final CallbackRecord.Losing losing = (CallbackRecord.Losing) callback;
+ final int maxMsToLive = losing.getMaxMsToLive();
String msg = String.format(
"Invalid linger time value %d, must be between %d and %d",
- actual.arg, 0, mService.mLingerDelayMs);
- int maxMsToLive = (Integer) actual.arg;
+ maxMsToLive, 0, mService.mLingerDelayMs);
assertTrue(msg, 0 <= maxMsToLive && maxMsToLive <= mService.mLingerDelayMs);
}
-
- return actual;
- }
-
- CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) throws Exception {
- return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
- }
-
- CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) throws Exception {
- return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
- }
-
- CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs)
- throws Exception {
- int timeLeft = timeoutMs;
- while (timeLeft > 0) {
- long start = SystemClock.elapsedRealtime();
- CallbackInfo info = nextCallback(timeLeft);
- if (fn.test(info)) {
- return info;
- }
- timeLeft -= (SystemClock.elapsedRealtime() - start);
- }
- fail("Did not receive expected callback after " + timeoutMs + "ms");
- return null;
- }
-
- // Expects onAvailable and the callbacks that follow it. These are:
- // - onSuspended, iff the network was suspended when the callbacks fire.
- // - onCapabilitiesChanged.
- // - onLinkPropertiesChanged.
- // - onBlockedStatusChanged.
- //
- // @param agent the network to expect the callbacks on.
- // @param expectSuspended whether to expect a SUSPENDED callback.
- // @param expectValidated the expected value of the VALIDATED capability in the
- // onCapabilitiesChanged callback.
- // @param timeoutMs how long to wait for the callbacks.
- void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
- boolean expectValidated, boolean expectBlocked, int timeoutMs) throws Exception {
- expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
- if (expectSuspended) {
- expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
- }
- if (expectValidated) {
- expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
- } else {
- expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, agent, timeoutMs);
- }
- expectCallback(CallbackState.LINK_PROPERTIES, agent, timeoutMs);
- expectBlockedStatusCallback(expectBlocked, agent);
- }
-
- // Expects the available callbacks (validated), plus onSuspended.
- void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated)
- throws Exception {
- expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
- }
-
- void expectAvailableCallbacksValidated(MockNetworkAgent agent)
- throws Exception {
- expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
- }
-
- void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) throws Exception {
- expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
- }
-
- void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) throws Exception {
- expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
- }
-
- void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent)
- throws Exception {
- expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
- }
-
- // Expects the available callbacks (where the onCapabilitiesChanged must contain the
- // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
- // one we just sent.
- // TODO: this is likely a bug. Fix it and remove this method.
- void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) throws Exception {
- expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
- NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
- expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
- // Implicitly check the network is allowed to use.
- // TODO: should we need to consider if network is in blocked status in this case?
- expectBlockedStatusCallback(false, agent);
- NetworkCapabilities nc2 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
- assertEquals(nc1, nc2);
- }
-
- // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
- // then expects another onCapabilitiesChanged that has the validated bit set. This is used
- // when a network connects and satisfies a callback, and then immediately validates.
- void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) throws Exception {
- expectAvailableCallbacksUnvalidated(agent);
- expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
- }
-
- NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent)
- throws Exception {
- return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
- }
-
- NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
- int timeoutMs) throws Exception {
- CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
- NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
- assertTrue(nc.hasCapability(capability));
- return nc;
- }
-
- NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent)
- throws Exception {
- return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
- }
-
- NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
- int timeoutMs) throws Exception {
- CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
- NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
- assertFalse(nc.hasCapability(capability));
- return nc;
- }
-
- void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent)
- throws Exception {
- CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
- assertTrue("Received capabilities don't match expectations : " + cbi.arg,
- fn.test((NetworkCapabilities) cbi.arg));
- }
-
- void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent)
- throws Exception {
- CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
- assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
- fn.test((LinkProperties) cbi.arg));
- }
-
- void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent)
- throws Exception {
- CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
- boolean actualBlocked = (boolean) cbi.arg;
- assertEquals(expectBlocked, actualBlocked);
- }
-
- void assertNoCallback() {
- waitForIdle();
- CallbackInfo c = mCallbacks.peek();
- assertNull("Unexpected callback: " + c, c);
+ return callback;
}
}
@@ -2031,16 +1785,16 @@ public class ConnectivityServiceTest {
cv = waitForConnectivityBroadcasts(2);
mWiFiNetworkAgent.disconnect();
- genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
cellNetworkCallback.assertNoCallback();
waitFor(cv);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
cv = waitForConnectivityBroadcasts(1);
mCellNetworkAgent.disconnect();
- genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
- cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
waitFor(cv);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
@@ -2061,21 +1815,21 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connect(true);
genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- genericNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
genericNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
wifiNetworkCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
- cellNetworkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
mWiFiNetworkAgent.disconnect();
- genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
mCellNetworkAgent.disconnect();
- genericNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
- cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
assertNoCallbacks(genericNetworkCallback, wifiNetworkCallback, cellNetworkCallback);
}
@@ -2115,7 +1869,7 @@ public class ConnectivityServiceTest {
// We then get LOSING when wifi validates and cell is outscored.
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// TODO: Investigate sending validated before losing.
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -2124,15 +1878,15 @@ public class ConnectivityServiceTest {
mEthernetNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
// TODO: Investigate sending validated before losing.
- callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mWiFiNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
- defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -2148,7 +1902,7 @@ public class ConnectivityServiceTest {
newNetwork = mWiFiNetworkAgent;
}
- callback.expectCallback(CallbackState.LOSING, oldNetwork);
+ callback.expectCallback(CallbackRecord.LOSING, oldNetwork);
// TODO: should we send an AVAILABLE callback to newNetwork, to indicate that it is no
// longer lingering?
defaultCallback.expectAvailableCallbacksValidated(newNetwork);
@@ -2162,7 +1916,7 @@ public class ConnectivityServiceTest {
// We expect a notification about the capabilities change, and nothing else.
defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_METERED, mWiFiNetworkAgent);
defaultCallback.assertNoCallback();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Wifi no longer satisfies our listen, which is for an unmetered network.
@@ -2171,11 +1925,11 @@ public class ConnectivityServiceTest {
// Disconnect our test networks.
mWiFiNetworkAgent.disconnect();
- defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mCellNetworkAgent.disconnect();
- defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
waitForIdle();
assertEquals(null, mCm.getActiveNetwork());
@@ -2206,8 +1960,8 @@ public class ConnectivityServiceTest {
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -2218,15 +1972,15 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.adjustScore(50);
mWiFiNetworkAgent.connect(false); // Score: 70
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Tear down wifi.
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -2237,19 +1991,19 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// TODO: Investigate sending validated before losing.
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
mCellNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
- defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
waitForIdle();
assertEquals(null, mCm.getActiveNetwork());
@@ -2264,7 +2018,7 @@ public class ConnectivityServiceTest {
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// TODO: Investigate sending validated before losing.
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -2275,13 +2029,13 @@ public class ConnectivityServiceTest {
// TODO: should this cause an AVAILABLE callback, to indicate that the network is no longer
// lingering?
mCm.unregisterNetworkCallback(noopCallback);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
// Similar to the above: lingering can start even after the lingered request is removed.
// Disconnect wifi and switch to cell.
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -2300,12 +2054,12 @@ public class ConnectivityServiceTest {
callback.assertNoCallback();
// Now unregister cellRequest and expect cell to start lingering.
mCm.unregisterNetworkCallback(noopCallback);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
// Let linger run its course.
callback.assertNoCallback();
final int lingerTimeoutMs = mService.mLingerDelayMs + mService.mLingerDelayMs / 4;
- callback.expectCallback(CallbackState.LOST, mCellNetworkAgent, lingerTimeoutMs);
+ callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent, lingerTimeoutMs);
// Register a TRACK_DEFAULT request and check that it does not affect lingering.
TestNetworkCallback trackDefaultCallback = new TestNetworkCallback();
@@ -2314,20 +2068,20 @@ public class ConnectivityServiceTest {
mEthernetNetworkAgent = new MockNetworkAgent(TRANSPORT_ETHERNET);
mEthernetNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mEthernetNetworkAgent);
- callback.expectCallback(CallbackState.LOSING, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mWiFiNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mEthernetNetworkAgent);
trackDefaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mEthernetNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
// Let linger run its course.
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent, lingerTimeoutMs);
// Clean up.
mEthernetNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
- defaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
- trackDefaultCallback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
+ trackDefaultCallback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
mCm.unregisterNetworkCallback(callback);
mCm.unregisterNetworkCallback(defaultCallback);
@@ -2357,7 +2111,7 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.connect(true);
defaultCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
// File a request for cellular, then release it.
@@ -2366,7 +2120,7 @@ public class ConnectivityServiceTest {
NetworkCallback noopCallback = new NetworkCallback();
mCm.requestNetwork(cellRequest, noopCallback);
mCm.unregisterNetworkCallback(noopCallback);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
// Let linger run its course.
callback.assertNoCallback();
@@ -2410,12 +2164,12 @@ public class ConnectivityServiceTest {
// If the user chooses yes on the "No Internet access, stay connected?" dialog, we switch to
// wifi even though it's unvalidated.
mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), true, false);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
// Disconnect wifi, and then reconnect, again with explicitlySelected=true.
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(false);
@@ -2424,14 +2178,14 @@ public class ConnectivityServiceTest {
// If the user chooses no on the "No Internet access, stay connected?" dialog, we ask the
// network to disconnect.
mCm.setAcceptUnvalidated(mWiFiNetworkAgent.getNetwork(), false, false);
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// Reconnect, again with explicitlySelected=true, but this time validate.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, false);
mWiFiNetworkAgent.connect(true);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
@@ -2447,20 +2201,20 @@ public class ConnectivityServiceTest {
// (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
// wifi immediately.
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true, true);
mWiFiNetworkAgent.connect(false);
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- callback.expectCallback(CallbackState.LOSING, mEthernetNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mEthernetNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mEthernetNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mEthernetNetworkAgent);
// Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
// Check that the network is not scored specially and that the device prefers cell data.
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(false, true);
mWiFiNetworkAgent.connect(false);
@@ -2471,8 +2225,8 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.disconnect();
mCellNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
}
private int[] makeIntArray(final int size, final int value) {
@@ -2721,7 +2475,7 @@ public class ConnectivityServiceTest {
// Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
// validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
mWiFiNetworkAgent);
assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
@@ -2729,7 +2483,7 @@ public class ConnectivityServiceTest {
// Disconnect and reconnect wifi with partial connectivity again.
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.connectWithPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
@@ -2741,7 +2495,7 @@ public class ConnectivityServiceTest {
// If the user chooses no, disconnect wifi immediately.
mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
false /* always */);
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// If user accepted partial connectivity before, and device reconnects to that network
// again, but now the network has full connectivity. The network shouldn't contain
@@ -2758,14 +2512,14 @@ public class ConnectivityServiceTest {
waitForIdle();
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
// Wifi should be the default network.
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// The user accepted partial connectivity and selected "don't ask again". Now the user
// reconnects to the partial connectivity network. Switch to wifi as soon as partial
@@ -2780,7 +2534,7 @@ public class ConnectivityServiceTest {
waitForIdle();
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
mWiFiNetworkAgent.setNetworkValid();
@@ -2790,7 +2544,7 @@ public class ConnectivityServiceTest {
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// If the user accepted partial connectivity, and the device auto-reconnects to the partial
// connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
@@ -2805,11 +2559,11 @@ public class ConnectivityServiceTest {
waitForIdle();
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(
NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
}
@Test
@@ -2851,7 +2605,7 @@ public class ConnectivityServiceTest {
false /* always */);
waitForIdle();
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
- captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
NetworkCapabilities nc =
validatedCallback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY,
@@ -2884,7 +2638,7 @@ public class ConnectivityServiceTest {
// Take down network.
// Expect onLost callback.
mWiFiNetworkAgent.disconnect();
- captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// Bring up a network with a captive portal.
// Expect onAvailable callback of listen for NET_CAPABILITY_CAPTIVE_PORTAL.
@@ -2898,7 +2652,7 @@ public class ConnectivityServiceTest {
// Expect onLost callback because network no longer provides NET_CAPABILITY_CAPTIVE_PORTAL.
mWiFiNetworkAgent.setNetworkValid();
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
- captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// Expect NET_CAPABILITY_VALIDATED onAvailable callback.
validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
@@ -2910,7 +2664,7 @@ public class ConnectivityServiceTest {
// Expect NET_CAPABILITY_VALIDATED onLost callback.
mWiFiNetworkAgent.setNetworkInvalid();
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), false);
- validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ validatedCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
}
@Test
@@ -2942,7 +2696,7 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.setNetworkPortal("http://example.com");
mCm.reportNetworkConnectivity(wifiNetwork, false);
captivePortalCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ validatedCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// Check that startCaptivePortalApp sends the expected command to NetworkMonitor.
mCm.startCaptivePortalApp(wifiNetwork);
@@ -2963,7 +2717,7 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.setNetworkValid();
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
- captivePortalCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ captivePortalCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
verify(mNotificationManager, times(1)).notifyAsUser(anyString(),
eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL));
@@ -3103,24 +2857,24 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.setNetworkSpecifier(nsFoo);
cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
for (TestNetworkCallback c: emptyCallbacks) {
- c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
- mWiFiNetworkAgent);
+ c.expectCapabilitiesThat(mWiFiNetworkAgent,
+ (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
}
- cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo),
- mWiFiNetworkAgent);
+ cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
+ (caps) -> caps.getNetworkSpecifier().equals(nsFoo));
assertEquals(nsFoo,
mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
cFoo.assertNoCallback();
mWiFiNetworkAgent.setNetworkSpecifier(nsBar);
- cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ cFoo.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
for (TestNetworkCallback c: emptyCallbacks) {
- c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
- mWiFiNetworkAgent);
+ c.expectCapabilitiesThat(mWiFiNetworkAgent,
+ (caps) -> caps.getNetworkSpecifier().equals(nsBar));
}
- cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar),
- mWiFiNetworkAgent);
+ cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
+ (caps) -> caps.getNetworkSpecifier().equals(nsBar));
assertEquals(nsBar,
mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
cBar.assertNoCallback();
@@ -3128,23 +2882,23 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier());
cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
for (TestNetworkCallback c : emptyCallbacks) {
- c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
- mWiFiNetworkAgent);
+ c.expectCapabilitiesThat(mWiFiNetworkAgent,
+ (caps) -> caps.getNetworkSpecifier() == null);
}
- cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
- mWiFiNetworkAgent);
- cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null,
- mWiFiNetworkAgent);
+ cFoo.expectCapabilitiesThat(mWiFiNetworkAgent,
+ (caps) -> caps.getNetworkSpecifier() == null);
+ cBar.expectCapabilitiesThat(mWiFiNetworkAgent,
+ (caps) -> caps.getNetworkSpecifier() == null);
assertNull(
mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier());
cFoo.assertNoCallback();
cBar.assertNoCallback();
mWiFiNetworkAgent.setNetworkSpecifier(null);
- cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ cFoo.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ cBar.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
for (TestNetworkCallback c: emptyCallbacks) {
- c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent);
+ c.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, mWiFiNetworkAgent);
}
assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar);
@@ -3287,7 +3041,7 @@ public class ConnectivityServiceTest {
// Bring down cell. Expect no default network callback, since it wasn't the default.
mCellNetworkAgent.disconnect();
- cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
defaultNetworkCallback.assertNoCallback();
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
@@ -3302,11 +3056,11 @@ public class ConnectivityServiceTest {
// followed by AVAILABLE cell.
mWiFiNetworkAgent.disconnect();
cellNetworkCallback.assertNoCallback();
- defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ defaultNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
defaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
mCellNetworkAgent.disconnect();
- cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
- defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
+ defaultNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
waitForIdle();
assertEquals(null, mCm.getActiveNetwork());
@@ -3322,7 +3076,7 @@ public class ConnectivityServiceTest {
assertEquals(defaultNetworkCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
vpnNetworkAgent.disconnect();
- defaultNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ defaultNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
waitForIdle();
assertEquals(null, mCm.getActiveNetwork());
}
@@ -3350,14 +3104,15 @@ public class ConnectivityServiceTest {
lp.setInterfaceName("foonet_data0");
mCellNetworkAgent.sendLinkProperties(lp);
// We should get onLinkPropertiesChanged().
- cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
+ mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
// Suspend the network.
mCellNetworkAgent.suspend();
cellNetworkCallback.expectCapabilitiesWithout(NET_CAPABILITY_NOT_SUSPENDED,
mCellNetworkAgent);
- cellNetworkCallback.expectCallback(CallbackState.SUSPENDED, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.SUSPENDED, mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
// Register a garden variety default network request.
@@ -3372,7 +3127,7 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.resume();
cellNetworkCallback.expectCapabilitiesWith(NET_CAPABILITY_NOT_SUSPENDED,
mCellNetworkAgent);
- cellNetworkCallback.expectCallback(CallbackState.RESUMED, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.RESUMED, mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
dfltNetworkCallback = new TestNetworkCallback();
@@ -3435,10 +3190,10 @@ public class ConnectivityServiceTest {
// When wifi connects, cell lingers.
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
fgCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- fgCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ fgCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
fgCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
assertTrue(isForegroundNetwork(mCellNetworkAgent));
assertTrue(isForegroundNetwork(mWiFiNetworkAgent));
@@ -3446,7 +3201,7 @@ public class ConnectivityServiceTest {
// When lingering is complete, cell is still there but is now in the background.
waitForIdle();
int timeoutMs = TEST_LINGER_DELAY_MS + TEST_LINGER_DELAY_MS / 4;
- fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent, timeoutMs);
+ fgCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent, timeoutMs);
// Expect a network capabilities update sans FOREGROUND.
callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
assertFalse(isForegroundNetwork(mCellNetworkAgent));
@@ -3472,7 +3227,7 @@ public class ConnectivityServiceTest {
// Release the request. The network immediately goes into the background, since it was not
// lingering.
mCm.unregisterNetworkCallback(cellCallback);
- fgCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ fgCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
// Expect a network capabilities update sans FOREGROUND.
callback.expectCapabilitiesWithout(NET_CAPABILITY_FOREGROUND, mCellNetworkAgent);
assertFalse(isForegroundNetwork(mCellNetworkAgent));
@@ -3480,8 +3235,8 @@ public class ConnectivityServiceTest {
// Disconnect wifi and check that cell is foreground again.
mWiFiNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- fgCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ fgCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
fgCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertTrue(isForegroundNetwork(mCellNetworkAgent));
@@ -3618,7 +3373,7 @@ public class ConnectivityServiceTest {
testFactory.waitForNetworkRequests(1);
// ... and cell data to be torn down.
- cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
assertLength(1, mCm.getAllNetworks());
testFactory.unregister();
@@ -3709,7 +3464,7 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.setNetworkInvalid();
mCm.reportNetworkConnectivity(wifiNetwork, false);
defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
- validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ validatedWifiCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// Because avoid bad wifi is off, we don't switch to cellular.
defaultCallback.assertNoCallback();
@@ -3753,7 +3508,7 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.setNetworkInvalid();
mCm.reportNetworkConnectivity(wifiNetwork, false);
defaultCallback.expectCapabilitiesWithout(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
- validatedWifiCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ validatedWifiCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// Simulate the user selecting "switch" and checking the don't ask again checkbox.
Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
@@ -3780,7 +3535,7 @@ public class ConnectivityServiceTest {
// If cell goes down, we switch to wifi.
mCellNetworkAgent.disconnect();
- defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
validatedWifiCallback.assertNoCallback();
@@ -3845,7 +3600,7 @@ public class ConnectivityServiceTest {
networkCallback.expectAvailableCallbacks(mWiFiNetworkAgent, false, false, false,
TEST_CALLBACK_TIMEOUT_MS);
mWiFiNetworkAgent.disconnect();
- networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
// Validate that UNAVAILABLE is not called
networkCallback.assertNoCallback();
@@ -3865,7 +3620,7 @@ public class ConnectivityServiceTest {
mCm.requestNetwork(nr, networkCallback, timeoutMs);
// pass timeout and validate that UNAVAILABLE is called
- networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
+ networkCallback.expectCallback(CallbackRecord.UNAVAILABLE, null);
// create a network satisfying request - validate that request not triggered
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -3956,7 +3711,7 @@ public class ConnectivityServiceTest {
// Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
testFactory.triggerUnfulfillable(requests.get(newRequestId));
- networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
+ networkCallback.expectCallback(CallbackRecord.UNAVAILABLE, null);
testFactory.waitForRequests();
// unregister network callback - a no-op (since already freed by the
@@ -4797,7 +4552,7 @@ public class ConnectivityServiceTest {
// Disconnect wifi aware network.
wifiAware.disconnect();
- callback.expectCallbackLike((info) -> info.state == CallbackState.LOST, TIMEOUT_MS);
+ callback.expectCallbackThat(TIMEOUT_MS, (info) -> info instanceof CallbackRecord.Lost);
mCm.unregisterNetworkCallback(callback);
verifyNoNetwork();
@@ -4846,14 +4601,15 @@ public class ConnectivityServiceTest {
// ConnectivityService.
MockNetworkAgent networkAgent = new MockNetworkAgent(TRANSPORT_WIFI, lp);
networkAgent.connect(true);
- networkCallback.expectCallback(CallbackState.AVAILABLE, networkAgent);
- networkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, networkAgent);
- CallbackInfo cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ networkCallback.expectCallback(CallbackRecord.AVAILABLE, networkAgent);
+ networkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, networkAgent);
+ CallbackRecord.LinkPropertiesChanged cbi =
+ networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
networkAgent);
- networkCallback.expectCallback(CallbackState.BLOCKED_STATUS, networkAgent);
+ networkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, networkAgent);
networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, networkAgent);
networkCallback.assertNoCallback();
- checkDirectlyConnectedRoutes(cbi.arg, Arrays.asList(myIpv4Address),
+ checkDirectlyConnectedRoutes(cbi.getLp(), Arrays.asList(myIpv4Address),
Arrays.asList(myIpv4DefaultRoute));
checkDirectlyConnectedRoutes(mCm.getLinkProperties(networkAgent.getNetwork()),
Arrays.asList(myIpv4Address), Arrays.asList(myIpv4DefaultRoute));
@@ -4865,9 +4621,9 @@ public class ConnectivityServiceTest {
newLp.addLinkAddress(myIpv6Address1);
newLp.addLinkAddress(myIpv6Address2);
networkAgent.sendLinkProperties(newLp);
- cbi = networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, networkAgent);
+ cbi = networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, networkAgent);
networkCallback.assertNoCallback();
- checkDirectlyConnectedRoutes(cbi.arg,
+ checkDirectlyConnectedRoutes(cbi.getLp(),
Arrays.asList(myIpv4Address, myIpv6Address1, myIpv6Address2),
Arrays.asList(myIpv4DefaultRoute));
mCm.unregisterNetworkCallback(networkCallback);
@@ -5071,15 +4827,15 @@ public class ConnectivityServiceTest {
assertTrue(ArrayUtils.containsAll(resolvrParams.tlsServers,
new String[] { "2001:db8::1", "192.0.2.1" }));
reset(mMockDnsResolver);
- cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
- cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
+ cellNetworkCallback.expectCallback(CallbackRecord.AVAILABLE, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED,
mCellNetworkAgent);
- CallbackInfo cbi = cellNetworkCallback.expectCallback(
- CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
- cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
+ CallbackRecord.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
+ CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
- assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
- assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ assertFalse(cbi.getLp().isPrivateDnsActive());
+ assertNull(cbi.getLp().getPrivateDnsServerName());
setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
verify(mMockDnsResolver, times(1)).setResolverConfiguration(
@@ -5107,11 +4863,11 @@ public class ConnectivityServiceTest {
setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
// Can't test dns configuration for strict mode without properly mocking
// out the DNS lookups, but can test that LinkProperties is updated.
- cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
- assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
- assertEquals("strict.example.com", ((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ assertTrue(cbi.getLp().isPrivateDnsActive());
+ assertEquals("strict.example.com", cbi.getLp().getPrivateDnsServerName());
}
@Test
@@ -5130,17 +4886,17 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.sendLinkProperties(lp);
mCellNetworkAgent.connect(false);
waitForIdle();
- cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
- cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
+ cellNetworkCallback.expectCallback(CallbackRecord.AVAILABLE, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED,
mCellNetworkAgent);
- CallbackInfo cbi = cellNetworkCallback.expectCallback(
- CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
- cellNetworkCallback.expectCallback(CallbackState.BLOCKED_STATUS, mCellNetworkAgent);
+ CallbackRecord.LinkPropertiesChanged cbi = cellNetworkCallback.expectCallback(
+ CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+ cellNetworkCallback.expectCallback(CallbackRecord.BLOCKED_STATUS, mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
- assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
- assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ assertFalse(cbi.getLp().isPrivateDnsActive());
+ assertNull(cbi.getLp().getPrivateDnsServerName());
Set<InetAddress> dnsServers = new HashSet<>();
- checkDnsServers(cbi.arg, dnsServers);
+ checkDnsServers(cbi.getLp(), dnsServers);
// Send a validation event for a server that is not part of the current
// resolver config. The validation event should be ignored.
@@ -5152,13 +4908,13 @@ public class ConnectivityServiceTest {
LinkProperties lp2 = new LinkProperties(lp);
lp2.addDnsServer(InetAddress.getByName("145.100.185.16"));
mCellNetworkAgent.sendLinkProperties(lp2);
- cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
- assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
- assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ assertFalse(cbi.getLp().isPrivateDnsActive());
+ assertNull(cbi.getLp().getPrivateDnsServerName());
dnsServers.add(InetAddress.getByName("145.100.185.16"));
- checkDnsServers(cbi.arg, dnsServers);
+ checkDnsServers(cbi.getLp(), dnsServers);
// Send a validation event containing a hostname that is not part of
// the current resolver config. The validation event should be ignored.
@@ -5176,39 +4932,39 @@ public class ConnectivityServiceTest {
// private dns fields should be sent.
mService.mNetdEventCallback.onPrivateDnsValidationEvent(
mCellNetworkAgent.getNetwork().netId, "145.100.185.16", "", true);
- cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
- assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
- assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
- checkDnsServers(cbi.arg, dnsServers);
+ assertTrue(cbi.getLp().isPrivateDnsActive());
+ assertNull(cbi.getLp().getPrivateDnsServerName());
+ checkDnsServers(cbi.getLp(), dnsServers);
// The private dns fields in LinkProperties should be preserved when
// the network agent sends unrelated changes.
LinkProperties lp3 = new LinkProperties(lp2);
lp3.setMtu(1300);
mCellNetworkAgent.sendLinkProperties(lp3);
- cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
- assertTrue(((LinkProperties)cbi.arg).isPrivateDnsActive());
- assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
- checkDnsServers(cbi.arg, dnsServers);
- assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
+ assertTrue(cbi.getLp().isPrivateDnsActive());
+ assertNull(cbi.getLp().getPrivateDnsServerName());
+ checkDnsServers(cbi.getLp(), dnsServers);
+ assertEquals(1300, cbi.getLp().getMtu());
// Removing the only validated server should affect the private dns
// fields in LinkProperties.
LinkProperties lp4 = new LinkProperties(lp3);
lp4.removeDnsServer(InetAddress.getByName("145.100.185.16"));
mCellNetworkAgent.sendLinkProperties(lp4);
- cbi = cellNetworkCallback.expectCallback(CallbackState.LINK_PROPERTIES,
+ cbi = cellNetworkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED,
mCellNetworkAgent);
cellNetworkCallback.assertNoCallback();
- assertFalse(((LinkProperties)cbi.arg).isPrivateDnsActive());
- assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
+ assertFalse(cbi.getLp().isPrivateDnsActive());
+ assertNull(cbi.getLp().getPrivateDnsServerName());
dnsServers.remove(InetAddress.getByName("145.100.185.16"));
- checkDnsServers(cbi.arg, dnsServers);
- assertEquals(1300, ((LinkProperties)cbi.arg).getMtu());
+ checkDnsServers(cbi.getLp(), dnsServers);
+ assertEquals(1300, cbi.getLp().getMtu());
}
private void checkDirectlyConnectedRoutes(Object callbackObj,
@@ -5290,19 +5046,19 @@ public class ConnectivityServiceTest {
defaultCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
- genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
genericNotVpnNetworkCallback.assertNoCallback();
- vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
- defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, nc -> null == nc.getUids());
+ defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
ranges.clear();
vpnNetworkAgent.setUids(ranges);
- genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
genericNotVpnNetworkCallback.assertNoCallback();
wifiNetworkCallback.assertNoCallback();
- vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ vpnNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
// TODO : The default network callback should actually get a LOST call here (also see the
// comment below for AVAILABLE). This is because ConnectivityService does not look at UID
@@ -5310,7 +5066,7 @@ public class ConnectivityServiceTest {
// can't currently update their UIDs without disconnecting, so this does not matter too
// much, but that is the reason the test here has to check for an update to the
// capabilities instead of the expected LOST then AVAILABLE.
- defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
ranges.add(new UidRange(uid, uid));
mMockVpn.setUids(ranges);
@@ -5322,23 +5078,23 @@ public class ConnectivityServiceTest {
vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
// TODO : Here like above, AVAILABLE would be correct, but because this can't actually
// happen outside of the test, ConnectivityService does not rematch callbacks.
- defaultCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
mWiFiNetworkAgent.disconnect();
- genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
- wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ genericNotVpnNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
+ wifiNetworkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
vpnNetworkCallback.assertNoCallback();
defaultCallback.assertNoCallback();
vpnNetworkAgent.disconnect();
- genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ genericNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
genericNotVpnNetworkCallback.assertNoCallback();
wifiNetworkCallback.assertNoCallback();
- vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
- defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ vpnNetworkCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
assertEquals(null, mCm.getActiveNetwork());
mCm.unregisterNetworkCallback(genericNetworkCallback);
@@ -5402,7 +5158,7 @@ public class ConnectivityServiceTest {
assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
vpnNetworkAgent.disconnect();
- defaultCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
defaultCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
mCm.unregisterNetworkCallback(defaultCallback);
@@ -5432,7 +5188,7 @@ public class ConnectivityServiceTest {
// Even though the VPN is unvalidated, it becomes the default network for our app.
callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
// TODO: this looks like a spurious callback.
- callback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+ callback.expectCallback(CallbackRecord.NETWORK_CAPS_UPDATED, vpnNetworkAgent);
callback.assertNoCallback();
assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore());
@@ -5456,7 +5212,7 @@ public class ConnectivityServiceTest {
callback.assertNoCallback();
vpnNetworkAgent.disconnect();
- callback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+ callback.expectCallback(CallbackRecord.LOST, vpnNetworkAgent);
callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent);
}
@@ -5496,10 +5252,10 @@ public class ConnectivityServiceTest {
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
@@ -5508,52 +5264,52 @@ public class ConnectivityServiceTest {
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
// Don't disconnect, but note the VPN is not using wifi any more.
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
// Use Wifi but not cell. Note the VPN is now unmetered.
mService.setUnderlyingNetworksForVpn(
new Network[] { mWiFiNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
// Use both again.
mService.setUnderlyingNetworksForVpn(
new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() });
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
// Disconnect cell. Receive update without even removing the dead network from the
// underlying networks – it's dead anyway. Not metered any more.
mCellNetworkAgent.disconnect();
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
// Disconnect wifi too. No underlying networks means this is now metered.
mWiFiNetworkAgent.disconnect();
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
mMockVpn.disconnect();
}
@@ -5592,20 +5348,20 @@ public class ConnectivityServiceTest {
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
mCellNetworkAgent.connect(true);
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
// Connect to WiFi; WiFi is the new default.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
mWiFiNetworkAgent.connect(true);
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
- && caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && caps.hasCapability(NET_CAPABILITY_NOT_METERED));
// Disconnect Cell. The default network did not change, so there shouldn't be any changes in
// the capabilities.
@@ -5614,10 +5370,10 @@ public class ConnectivityServiceTest {
// Disconnect wifi too. Now we have no default network.
mWiFiNetworkAgent.disconnect();
- vpnNetworkCallback.expectCapabilitiesLike((caps) -> caps.hasTransport(TRANSPORT_VPN)
+ vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent,
+ (caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
- && !caps.hasCapability(NET_CAPABILITY_NOT_METERED),
- vpnNetworkAgent);
+ && !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
mMockVpn.disconnect();
}
@@ -5893,7 +5649,7 @@ public class ConnectivityServiceTest {
// Switch to METERED network. Restrict the use of the network.
mWiFiNetworkAgent.disconnect();
- defaultCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
defaultCallback.expectAvailableCallbacksValidatedAndBlocked(mCellNetworkAgent);
// Network becomes NOT_METERED.
@@ -5907,7 +5663,7 @@ public class ConnectivityServiceTest {
defaultCallback.assertNoCallback();
mCellNetworkAgent.disconnect();
- defaultCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ defaultCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
defaultCallback.assertNoCallback();
mCm.unregisterNetworkCallback(defaultCallback);
@@ -5983,7 +5739,7 @@ public class ConnectivityServiceTest {
// the NAT64 prefix was removed because one was never discovered.
cellLp.addLinkAddress(myIpv4);
mCellNetworkAgent.sendLinkProperties(cellLp);
- networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
@@ -5996,7 +5752,7 @@ public class ConnectivityServiceTest {
cellLp.removeLinkAddress(myIpv4);
cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
mCellNetworkAgent.sendLinkProperties(cellLp);
- networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
// When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
@@ -6004,15 +5760,15 @@ public class ConnectivityServiceTest {
assertNull(mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getNat64Prefix());
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
kNat64PrefixString, 96);
- LinkProperties lpBeforeClat = (LinkProperties) networkCallback.expectCallback(
- CallbackState.LINK_PROPERTIES, mCellNetworkAgent).arg;
+ LinkProperties lpBeforeClat = networkCallback.expectCallback(
+ CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent).getLp();
assertEquals(0, lpBeforeClat.getStackedLinks().size());
assertEquals(kNat64Prefix, lpBeforeClat.getNat64Prefix());
verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
// Clat iface comes up. Expect stacked link to be added.
clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
- networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
List<LinkProperties> stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork())
.getStackedLinks();
assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0));
@@ -6020,7 +5776,7 @@ public class ConnectivityServiceTest {
// Change trivial linkproperties and see if stacked link is preserved.
cellLp.addDnsServer(InetAddress.getByName("8.8.8.8"));
mCellNetworkAgent.sendLinkProperties(cellLp);
- networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
List<LinkProperties> stackedLpsAfterChange =
mCm.getLinkProperties(mCellNetworkAgent.getNetwork()).getStackedLinks();
@@ -6038,12 +5794,12 @@ public class ConnectivityServiceTest {
cellLp.addLinkAddress(myIpv4);
cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
mCellNetworkAgent.sendLinkProperties(cellLp);
- networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
// As soon as stop is called, the linkproperties lose the stacked interface.
- networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork());
LinkProperties expected = new LinkProperties(cellLp);
expected.setNat64Prefix(kNat64Prefix);
@@ -6062,41 +5818,39 @@ public class ConnectivityServiceTest {
// Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
kNat64PrefixString, 96);
- networkCallback.expectLinkPropertiesLike((lp) -> lp.getNat64Prefix() == null,
- mCellNetworkAgent);
+ networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
+ (lp) -> lp.getNat64Prefix() == null);
// Remove IPv4 address and expect prefix discovery and clatd to be started again.
cellLp.removeLinkAddress(myIpv4);
cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
mCellNetworkAgent.sendLinkProperties(cellLp);
- networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
kNat64PrefixString, 96);
- networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString());
// Clat iface comes up. Expect stacked link to be added.
clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true);
- networkCallback.expectLinkPropertiesLike(
- (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null,
- mCellNetworkAgent);
+ networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
+ (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null);
// NAT64 prefix is removed. Expect that clat is stopped.
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
kNat64PrefixString, 96);
- networkCallback.expectLinkPropertiesLike(
- (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null,
- mCellNetworkAgent);
+ networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
+ (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null);
verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
- networkCallback.expectLinkPropertiesLike((lp) -> lp.getStackedLinks().size() == 0,
- mCellNetworkAgent);
+ networkCallback.expectLinkPropertiesThat(mCellNetworkAgent,
+ (lp) -> lp.getStackedLinks().size() == 0);
// Clean up.
mCellNetworkAgent.disconnect();
- networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
networkCallback.assertNoCallback();
mCm.unregisterNetworkCallback(networkCallback);
}
@@ -6128,7 +5882,7 @@ public class ConnectivityServiceTest {
reset(mNetworkManagementService);
mWiFiNetworkAgent.connect(true);
networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
verify(mNetworkManagementService, times(1)).addIdleTimer(eq(WIFI_IFNAME), anyInt(),
eq(ConnectivityManager.TYPE_WIFI));
@@ -6137,7 +5891,7 @@ public class ConnectivityServiceTest {
// Disconnect wifi and switch back to cell
reset(mNetworkManagementService);
mWiFiNetworkAgent.disconnect();
- networkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LOST, mWiFiNetworkAgent);
assertNoCallbacks(networkCallback);
verify(mNetworkManagementService, times(1)).removeIdleTimer(eq(WIFI_IFNAME));
verify(mNetworkManagementService, times(1)).addIdleTimer(eq(MOBILE_IFNAME), anyInt(),
@@ -6149,14 +5903,14 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.sendLinkProperties(wifiLp);
mWiFiNetworkAgent.connect(true);
networkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
- networkCallback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LOSING, mCellNetworkAgent);
networkCallback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
// Disconnect cell
reset(mNetworkManagementService);
reset(mMockNetd);
mCellNetworkAgent.disconnect();
- networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ networkCallback.expectCallback(CallbackRecord.LOST, mCellNetworkAgent);
// LOST callback is triggered earlier than removing idle timer. Broadcast should also be
// sent as network being switched. Ensure rule removal for cell will not be triggered
// unexpectedly before network being removed.
diff --git a/tools/aapt2/optimize/ResourcePathShortener.cpp b/tools/aapt2/optimize/ResourcePathShortener.cpp
index 845262bcb0d9..6b11de759d2d 100644
--- a/tools/aapt2/optimize/ResourcePathShortener.cpp
+++ b/tools/aapt2/optimize/ResourcePathShortener.cpp
@@ -23,6 +23,7 @@
#include "ResourceTable.h"
#include "ValueVisitor.h"
+#include "util/Util.h"
static const std::string base64_chars =
@@ -95,8 +96,8 @@ bool ResourcePathShortener::Consume(IAaptContext* context, ResourceTable* table)
android::StringPiece res_subdir, actual_filename, extension;
util::ExtractResFilePathParts(*file_ref->path, &res_subdir, &actual_filename, &extension);
- // Android detects ColorStateLists via pathname, skip res/color/*
- if (res_subdir == android::StringPiece("res/color/"))
+ // Android detects ColorStateLists via pathname, skip res/color*
+ if (util::StartsWith(res_subdir, "res/color"))
continue;
std::string shortened_filename = ShortenFileName(*file_ref->path, num_chars);
diff --git a/tools/aapt2/optimize/ResourcePathShortener_test.cpp b/tools/aapt2/optimize/ResourcePathShortener_test.cpp
index efbef8f40722..1f4569495186 100644
--- a/tools/aapt2/optimize/ResourcePathShortener_test.cpp
+++ b/tools/aapt2/optimize/ResourcePathShortener_test.cpp
@@ -75,6 +75,9 @@ TEST(ResourcePathShortenerTest, SkipColorFileRefPaths) {
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
.AddFileReference("android:color/colorlist", "res/color/colorlist.xml")
+ .AddFileReference("android:color/colorlist",
+ "res/color-mdp-v21/colorlist.xml",
+ test::ParseConfigOrDie("mdp-v21"))
.Build();
std::map<std::string, std::string> path_map;
@@ -82,6 +85,7 @@ TEST(ResourcePathShortenerTest, SkipColorFileRefPaths) {
// Expect that the path map to not contain the ColorStateList
ASSERT_THAT(path_map.find("res/color/colorlist.xml"), Eq(path_map.end()));
+ ASSERT_THAT(path_map.find("res/color-mdp-v21/colorlist.xml"), Eq(path_map.end()));
}
TEST(ResourcePathShortenerTest, KeepExtensions) {