Merge "Revert "Shortcut integration with AppSearch (Part 5)"" into sc-dev
diff --git a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt
index d5ed95f..90dca25 100644
--- a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt
+++ b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt
@@ -159,7 +159,15 @@
PARALLEL_MAX_THREADS, "package-parsing-test",
Process.THREAD_PRIORITY_FOREGROUND)
- fun submit(file: File) = service.submit { queue.put(parse(file)) }
+ fun submit(file: File) {
+ service.submit {
+ try {
+ queue.put(parse(file))
+ } catch (e: Exception) {
+ queue.put(e)
+ }
+ }
+ }
fun take() = queue.poll(QUEUE_POLL_TIMEOUT_SECONDS, TimeUnit.SECONDS)
diff --git a/boot/Android.bp b/boot/Android.bp
index 4f7c44e..71edea2 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -23,7 +23,24 @@
default_applicable_licenses: ["frameworks_base_license"],
}
-boot_image {
- name: "framework-boot-image",
- image_name: "boot",
+// This module provides access to information Soong has related to the
+// whole platform bootclasspath. Currently, that information is provided solely
+// through configuration but additional information will be added here.
+//
+// This will provide support for the following:
+// * Hidden API processing for those parts of the bootclasspath that are not
+// part of an APEX.
+// * Compatibility checking to ensure that the hidden API bits encoded into the
+// dex files by the modularized hidden API processing is compatible with the
+// runtimes of earlier releases which expect the bits to have been computed
+// over the entirety of the bootclasspath in one go not separately.
+// * Dexpreopting apps and other libraries not on the platform bootclasspath.
+// * Generating and installing the appropriate files to the device which will
+// allow it to generate the bootclasspath related environment variables
+// dynamically.
+//
+// This module needs to be present in the build for the above processing to be
+// done correctly.
+platform_bootclasspath {
+ name: "platform-bootclasspath",
}
diff --git a/core/api/current.txt b/core/api/current.txt
index 89cf257..39d0b8c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -303,7 +303,7 @@
field public static final int allowAudioPlaybackCapture = 16844289; // 0x1010601
field public static final int allowBackup = 16843392; // 0x1010280
field public static final int allowClearUserData = 16842757; // 0x1010005
- field public static final int allowClickWhenDisabled = 16844312; // 0x1010618
+ field public static final int allowClickWhenDisabled;
field public static final int allowEmbedded = 16843765; // 0x10103f5
field public static final int allowNativeHeapPointerTagging = 16844306; // 0x1010612
field public static final int allowParallelSyncs = 16843570; // 0x1010332
@@ -334,7 +334,7 @@
field public static final int apiKey = 16843281; // 0x1010211
field public static final int appCategory = 16844101; // 0x1010545
field public static final int appComponentFactory = 16844154; // 0x101057a
- field public static final int attributionTags = 16844354; // 0x1010642
+ field public static final int attributionTags;
field public static final int author = 16843444; // 0x10102b4
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
@@ -400,7 +400,7 @@
field public static final int calendarViewShown = 16843596; // 0x101034c
field public static final int calendarViewStyle = 16843613; // 0x101035d
field public static final int canControlMagnification = 16844039; // 0x1010507
- field public static final int canPauseRecording = 16844314; // 0x101061a
+ field public static final int canPauseRecording;
field public static final int canPerformGestures = 16844045; // 0x101050d
field public static final int canRecord = 16844060; // 0x101051c
field @Deprecated public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
@@ -442,7 +442,7 @@
field public static final int clickable = 16842981; // 0x10100e5
field public static final int clipChildren = 16842986; // 0x10100ea
field public static final int clipOrientation = 16843274; // 0x101020a
- field public static final int clipToOutline = 16844328; // 0x1010628
+ field public static final int clipToOutline;
field public static final int clipToPadding = 16842987; // 0x10100eb
field public static final int closeIcon = 16843905; // 0x1010481
field @Deprecated public static final int codes = 16843330; // 0x1010242
@@ -512,7 +512,7 @@
field public static final int dashGap = 16843175; // 0x10101a7
field public static final int dashWidth = 16843174; // 0x10101a6
field public static final int data = 16842798; // 0x101002e
- field public static final int dataExtractionRules = 16844350; // 0x101063e
+ field public static final int dataExtractionRules;
field public static final int datePickerDialogTheme = 16843948; // 0x10104ac
field public static final int datePickerMode = 16843955; // 0x10104b3
field public static final int datePickerStyle = 16843612; // 0x101035c
@@ -534,8 +534,8 @@
field public static final int detailSocialSummary = 16843428; // 0x10102a4
field public static final int detailsElementBackground = 16843598; // 0x101034e
field public static final int dial = 16843010; // 0x1010102
- field public static final int dialTint = 16844342; // 0x1010636
- field public static final int dialTintMode = 16844343; // 0x1010637
+ field public static final int dialTint;
+ field public static final int dialTintMode;
field public static final int dialogCornerRadius = 16844145; // 0x1010571
field public static final int dialogIcon = 16843252; // 0x10101f4
field public static final int dialogLayout = 16843255; // 0x10101f7
@@ -583,7 +583,7 @@
field public static final int dropDownWidth = 16843362; // 0x1010262
field public static final int duplicateParentState = 16842985; // 0x10100e9
field public static final int duration = 16843160; // 0x1010198
- field public static final int edgeEffectType = 16844329; // 0x1010629
+ field public static final int edgeEffectType;
field public static final int editTextBackground = 16843602; // 0x1010352
field public static final int editTextColor = 16843601; // 0x1010351
field public static final int editTextPreferenceStyle = 16842898; // 0x1010092
@@ -669,7 +669,7 @@
field @Deprecated public static final int fontProviderCerts = 16844125; // 0x101055d
field @Deprecated public static final int fontProviderPackage = 16844119; // 0x1010557
field @Deprecated public static final int fontProviderQuery = 16844113; // 0x1010551
- field public static final int fontProviderSystemFontFamily = 16844322; // 0x1010622
+ field public static final int fontProviderSystemFontFamily;
field public static final int fontStyle = 16844095; // 0x101053f
field public static final int fontVariationSettings = 16844144; // 0x1010570
field public static final int fontWeight = 16844083; // 0x1010533
@@ -733,14 +733,14 @@
field public static final int groupIndicator = 16843019; // 0x101010b
field public static final int gwpAsanMode = 16844310; // 0x1010616
field public static final int hand_hour = 16843011; // 0x1010103
- field public static final int hand_hourTint = 16844344; // 0x1010638
- field public static final int hand_hourTintMode = 16844345; // 0x1010639
+ field public static final int hand_hourTint;
+ field public static final int hand_hourTintMode;
field public static final int hand_minute = 16843012; // 0x1010104
- field public static final int hand_minuteTint = 16844346; // 0x101063a
- field public static final int hand_minuteTintMode = 16844347; // 0x101063b
- field public static final int hand_second = 16844323; // 0x1010623
- field public static final int hand_secondTint = 16844348; // 0x101063c
- field public static final int hand_secondTintMode = 16844349; // 0x101063d
+ field public static final int hand_minuteTint;
+ field public static final int hand_minuteTintMode;
+ field public static final int hand_second;
+ field public static final int hand_secondTint;
+ field public static final int hand_secondTintMode;
field public static final int handle = 16843354; // 0x101025a
field public static final int handleProfiling = 16842786; // 0x1010022
field public static final int hapticFeedbackEnabled = 16843358; // 0x101025e
@@ -824,7 +824,7 @@
field public static final int installLocation = 16843447; // 0x10102b7
field public static final int interactiveUiTimeout = 16844181; // 0x1010595
field public static final int interpolator = 16843073; // 0x1010141
- field public static final int isAccessibilityTool = 16844353; // 0x1010641
+ field public static final int isAccessibilityTool;
field public static final int isAlwaysSyncable = 16843571; // 0x1010333
field public static final int isAsciiCapable = 16843753; // 0x10103e9
field public static final int isAuxiliary = 16843647; // 0x101037f
@@ -866,8 +866,8 @@
field public static final int keyboardNavigationCluster = 16844096; // 0x1010540
field public static final int keycode = 16842949; // 0x10100c5
field public static final int killAfterRestore = 16843420; // 0x101029c
- field public static final int knownCerts = 16844330; // 0x101062a
- field public static final int lStar = 16844359; // 0x1010647
+ field public static final int knownCerts;
+ field public static final int lStar;
field public static final int label = 16842753; // 0x1010001
field public static final int labelFor = 16843718; // 0x10103c6
field @Deprecated public static final int labelTextSize = 16843317; // 0x1010235
@@ -977,8 +977,8 @@
field public static final int maxLines = 16843091; // 0x1010153
field public static final int maxLongVersionCode = 16844163; // 0x1010583
field public static final int maxRecents = 16843846; // 0x1010446
- field public static final int maxResizeHeight = 16844339; // 0x1010633
- field public static final int maxResizeWidth = 16844338; // 0x1010632
+ field public static final int maxResizeHeight;
+ field public static final int maxResizeWidth;
field public static final int maxRows = 16843059; // 0x1010133
field public static final int maxSdkVersion = 16843377; // 0x1010271
field public static final int maxWidth = 16843039; // 0x101011f
@@ -987,7 +987,7 @@
field public static final int measureWithLargestChild = 16843476; // 0x10102d4
field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad
field public static final int mediaRouteTypes = 16843694; // 0x10103ae
- field public static final int memtagMode = 16844324; // 0x1010624
+ field public static final int memtagMode;
field public static final int menuCategory = 16843230; // 0x10101de
field public static final int mimeGroup = 16844309; // 0x1010615
field public static final int mimeType = 16842790; // 0x1010026
@@ -1011,7 +1011,7 @@
field public static final int multiArch = 16843918; // 0x101048e
field public static final int multiprocess = 16842771; // 0x1010013
field public static final int name = 16842755; // 0x1010003
- field public static final int nativeHeapZeroInitialized = 16844325; // 0x1010625
+ field public static final int nativeHeapZeroInitialized;
field public static final int navigationBarColor = 16843858; // 0x1010452
field public static final int navigationBarDividerColor = 16844141; // 0x101056d
field public static final int navigationContentDescription = 16843969; // 0x10104c1
@@ -1081,13 +1081,13 @@
field public static final int panelTextAppearance = 16842850; // 0x1010062
field public static final int parentActivityName = 16843687; // 0x10103a7
field @Deprecated public static final int password = 16843100; // 0x101015c
- field public static final int passwordsActivity = 16844351; // 0x101063f
+ field public static final int passwordsActivity;
field public static final int path = 16842794; // 0x101002a
- field public static final int pathAdvancedPattern = 16844320; // 0x1010620
+ field public static final int pathAdvancedPattern;
field public static final int pathData = 16843781; // 0x1010405
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
- field public static final int pathSuffix = 16844318; // 0x101061e
+ field public static final int pathSuffix;
field public static final int patternPathData = 16843978; // 0x10104ca
field public static final int permission = 16842758; // 0x1010006
field public static final int permissionFlags = 16843719; // 0x10103c7
@@ -1124,7 +1124,7 @@
field public static final int presentationTheme = 16843712; // 0x10103c0
field public static final int preserveLegacyExternalStorage = 16844308; // 0x1010614
field public static final int previewImage = 16843482; // 0x10102da
- field public static final int previewLayout = 16844327; // 0x1010627
+ field public static final int previewLayout;
field public static final int primaryContentAlpha = 16844114; // 0x1010552
field public static final int priority = 16842780; // 0x101001c
field public static final int privateImeOptions = 16843299; // 0x1010223
@@ -1181,8 +1181,8 @@
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
- field public static final int requestOptimizedExternalStorageAccess = 16844357; // 0x1010645
- field public static final int requireDeviceScreenOn = 16844317; // 0x101061d
+ field public static final int requestOptimizedExternalStorageAccess;
+ field public static final int requireDeviceScreenOn;
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
@@ -1207,7 +1207,7 @@
field public static final int right = 16843183; // 0x10101af
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
field public static final int ringtoneType = 16843257; // 0x10101f9
- field public static final int rollbackDataPolicy = 16844311; // 0x1010617
+ field public static final int rollbackDataPolicy;
field public static final int rotation = 16843558; // 0x1010326
field public static final int rotationAnimation = 16844090; // 0x101053a
field public static final int rotationX = 16843559; // 0x1010327
@@ -1268,7 +1268,7 @@
field public static final int segmentedButtonStyle = 16843568; // 0x1010330
field public static final int selectAllOnFocus = 16843102; // 0x101015e
field public static final int selectable = 16843238; // 0x10101e6
- field public static final int selectableAsDefault = 16844352; // 0x1010640
+ field public static final int selectableAsDefault;
field public static final int selectableItemBackground = 16843534; // 0x101030e
field public static final int selectableItemBackgroundBorderless = 16843868; // 0x101045c
field @Deprecated public static final int selectedDateVerticalBar = 16843591; // 0x1010347
@@ -1296,7 +1296,7 @@
field public static final int showDefault = 16843258; // 0x10101fa
field public static final int showDividers = 16843561; // 0x1010329
field public static final int showForAllUsers = 16844015; // 0x10104ef
- field public static final int showInInputMethodPicker = 16844361; // 0x1010649
+ field public static final int showInInputMethodPicker;
field public static final int showMetadataInPreview = 16844079; // 0x101052f
field @Deprecated public static final int showOnLockScreen = 16843721; // 0x10103c9
field public static final int showSilent = 16843259; // 0x10101fb
@@ -1319,17 +1319,17 @@
field public static final int spinnerMode = 16843505; // 0x10102f1
field public static final int spinnerStyle = 16842881; // 0x1010081
field public static final int spinnersShown = 16843595; // 0x101034b
- field public static final int splashScreenTheme = 16844337; // 0x1010631
+ field public static final int splashScreenTheme;
field public static final int splitMotionEvents = 16843503; // 0x10102ef
field public static final int splitName = 16844105; // 0x1010549
field public static final int splitTrack = 16843852; // 0x101044c
field public static final int spotShadowAlpha = 16843967; // 0x10104bf
field public static final int src = 16843033; // 0x1010119
field public static final int ssp = 16843747; // 0x10103e3
- field public static final int sspAdvancedPattern = 16844321; // 0x1010621
+ field public static final int sspAdvancedPattern;
field public static final int sspPattern = 16843749; // 0x10103e5
field public static final int sspPrefix = 16843748; // 0x10103e4
- field public static final int sspSuffix = 16844319; // 0x101061f
+ field public static final int sspSuffix;
field public static final int stackFromBottom = 16843005; // 0x10100fd
field public static final int stackViewStyle = 16843838; // 0x101043e
field public static final int starStyle = 16842882; // 0x1010082
@@ -1402,7 +1402,7 @@
field public static final int supportsRtl = 16843695; // 0x10103af
field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
field public static final int supportsUploading = 16843419; // 0x101029b
- field public static final int suppressesSpellChecker = 16844355; // 0x1010643
+ field public static final int suppressesSpellChecker;
field public static final int switchMinWidth = 16843632; // 0x1010370
field public static final int switchPadding = 16843633; // 0x1010371
field public static final int switchPreferenceStyle = 16843629; // 0x101036d
@@ -1417,8 +1417,8 @@
field public static final int tabWidgetStyle = 16842883; // 0x1010083
field public static final int tag = 16842961; // 0x10100d1
field public static final int targetActivity = 16843266; // 0x1010202
- field public static final int targetCellHeight = 16844341; // 0x1010635
- field public static final int targetCellWidth = 16844340; // 0x1010634
+ field public static final int targetCellHeight;
+ field public static final int targetCellWidth;
field public static final int targetClass = 16842799; // 0x101002f
field @Deprecated public static final int targetDescriptions = 16843680; // 0x10103a0
field public static final int targetId = 16843740; // 0x10103dc
@@ -1588,7 +1588,7 @@
field public static final int useLevel = 16843167; // 0x101019f
field public static final int userVisible = 16843409; // 0x1010291
field public static final int usesCleartextTraffic = 16844012; // 0x10104ec
- field public static final int usesPermissionFlags = 16844356; // 0x1010644
+ field public static final int usesPermissionFlags;
field public static final int value = 16842788; // 0x1010024
field public static final int valueFrom = 16843486; // 0x10102de
field public static final int valueTo = 16843487; // 0x10102df
@@ -1643,10 +1643,10 @@
field public static final int windowAllowReturnTransitionOverlap = 16843835; // 0x101043b
field public static final int windowAnimationStyle = 16842926; // 0x10100ae
field public static final int windowBackground = 16842836; // 0x1010054
- field public static final int windowBackgroundBlurRadius = 16844331; // 0x101062b
+ field public static final int windowBackgroundBlurRadius;
field public static final int windowBackgroundFallback = 16844035; // 0x1010503
- field public static final int windowBlurBehindEnabled = 16844316; // 0x101061c
- field public static final int windowBlurBehindRadius = 16844315; // 0x101061b
+ field public static final int windowBlurBehindEnabled;
+ field public static final int windowBlurBehindRadius;
field public static final int windowClipToOutline = 16843947; // 0x10104ab
field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
field public static final int windowContentOverlay = 16842841; // 0x1010059
@@ -1665,7 +1665,7 @@
field public static final int windowHideAnimation = 16842935; // 0x10100b7
field public static final int windowIsFloating = 16842839; // 0x1010057
field public static final int windowIsTranslucent = 16842840; // 0x1010058
- field public static final int windowLayoutAffinity = 16844313; // 0x1010619
+ field public static final int windowLayoutAffinity;
field public static final int windowLayoutInDisplayCutoutMode = 16844166; // 0x1010586
field public static final int windowLightNavigationBar = 16844140; // 0x101056c
field public static final int windowLightStatusBar = 16844000; // 0x10104e0
@@ -1684,11 +1684,11 @@
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
- field public static final int windowSplashScreenAnimatedIcon = 16844333; // 0x101062d
- field public static final int windowSplashScreenAnimationDuration = 16844334; // 0x101062e
- field public static final int windowSplashScreenBackground = 16844332; // 0x101062c
- field public static final int windowSplashScreenBrandingImage = 16844335; // 0x101062f
- field public static final int windowSplashScreenIconBackgroundColor = 16844336; // 0x1010630
+ field public static final int windowSplashScreenAnimatedIcon;
+ field public static final int windowSplashScreenAnimationDuration;
+ field public static final int windowSplashScreenBackground;
+ field public static final int windowSplashScreenBrandingImage;
+ field public static final int windowSplashScreenIconBackgroundColor;
field @Deprecated public static final int windowSplashscreenContent = 16844132; // 0x1010564
field @Deprecated public static final int windowSwipeToDismiss = 16843763; // 0x10103f3
field public static final int windowTitleBackgroundStyle = 16842844; // 0x101005c
@@ -1736,66 +1736,66 @@
field @Deprecated public static final int secondary_text_dark_nodisable = 17170438; // 0x1060006
field @Deprecated public static final int secondary_text_light = 17170439; // 0x1060007
field @Deprecated public static final int secondary_text_light_nodisable = 17170440; // 0x1060008
- field public static final int system_accent1_0 = 17170485; // 0x1060035
- field public static final int system_accent1_100 = 17170487; // 0x1060037
- field public static final int system_accent1_1000 = 17170496; // 0x1060040
- field public static final int system_accent1_200 = 17170488; // 0x1060038
- field public static final int system_accent1_300 = 17170489; // 0x1060039
- field public static final int system_accent1_400 = 17170490; // 0x106003a
- field public static final int system_accent1_50 = 17170486; // 0x1060036
- field public static final int system_accent1_500 = 17170491; // 0x106003b
- field public static final int system_accent1_600 = 17170492; // 0x106003c
- field public static final int system_accent1_700 = 17170493; // 0x106003d
- field public static final int system_accent1_800 = 17170494; // 0x106003e
- field public static final int system_accent1_900 = 17170495; // 0x106003f
- field public static final int system_accent2_0 = 17170497; // 0x1060041
- field public static final int system_accent2_100 = 17170499; // 0x1060043
- field public static final int system_accent2_1000 = 17170508; // 0x106004c
- field public static final int system_accent2_200 = 17170500; // 0x1060044
- field public static final int system_accent2_300 = 17170501; // 0x1060045
- field public static final int system_accent2_400 = 17170502; // 0x1060046
- field public static final int system_accent2_50 = 17170498; // 0x1060042
- field public static final int system_accent2_500 = 17170503; // 0x1060047
- field public static final int system_accent2_600 = 17170504; // 0x1060048
- field public static final int system_accent2_700 = 17170505; // 0x1060049
- field public static final int system_accent2_800 = 17170506; // 0x106004a
- field public static final int system_accent2_900 = 17170507; // 0x106004b
- field public static final int system_accent3_0 = 17170509; // 0x106004d
- field public static final int system_accent3_100 = 17170511; // 0x106004f
- field public static final int system_accent3_1000 = 17170520; // 0x1060058
- field public static final int system_accent3_200 = 17170512; // 0x1060050
- field public static final int system_accent3_300 = 17170513; // 0x1060051
- field public static final int system_accent3_400 = 17170514; // 0x1060052
- field public static final int system_accent3_50 = 17170510; // 0x106004e
- field public static final int system_accent3_500 = 17170515; // 0x1060053
- field public static final int system_accent3_600 = 17170516; // 0x1060054
- field public static final int system_accent3_700 = 17170517; // 0x1060055
- field public static final int system_accent3_800 = 17170518; // 0x1060056
- field public static final int system_accent3_900 = 17170519; // 0x1060057
- field public static final int system_neutral1_0 = 17170461; // 0x106001d
- field public static final int system_neutral1_100 = 17170463; // 0x106001f
- field public static final int system_neutral1_1000 = 17170472; // 0x1060028
- field public static final int system_neutral1_200 = 17170464; // 0x1060020
- field public static final int system_neutral1_300 = 17170465; // 0x1060021
- field public static final int system_neutral1_400 = 17170466; // 0x1060022
- field public static final int system_neutral1_50 = 17170462; // 0x106001e
- field public static final int system_neutral1_500 = 17170467; // 0x1060023
- field public static final int system_neutral1_600 = 17170468; // 0x1060024
- field public static final int system_neutral1_700 = 17170469; // 0x1060025
- field public static final int system_neutral1_800 = 17170470; // 0x1060026
- field public static final int system_neutral1_900 = 17170471; // 0x1060027
- field public static final int system_neutral2_0 = 17170473; // 0x1060029
- field public static final int system_neutral2_100 = 17170475; // 0x106002b
- field public static final int system_neutral2_1000 = 17170484; // 0x1060034
- field public static final int system_neutral2_200 = 17170476; // 0x106002c
- field public static final int system_neutral2_300 = 17170477; // 0x106002d
- field public static final int system_neutral2_400 = 17170478; // 0x106002e
- field public static final int system_neutral2_50 = 17170474; // 0x106002a
- field public static final int system_neutral2_500 = 17170479; // 0x106002f
- field public static final int system_neutral2_600 = 17170480; // 0x1060030
- field public static final int system_neutral2_700 = 17170481; // 0x1060031
- field public static final int system_neutral2_800 = 17170482; // 0x1060032
- field public static final int system_neutral2_900 = 17170483; // 0x1060033
+ field public static final int system_accent1_0;
+ field public static final int system_accent1_100;
+ field public static final int system_accent1_1000;
+ field public static final int system_accent1_200;
+ field public static final int system_accent1_300;
+ field public static final int system_accent1_400;
+ field public static final int system_accent1_50;
+ field public static final int system_accent1_500;
+ field public static final int system_accent1_600;
+ field public static final int system_accent1_700;
+ field public static final int system_accent1_800;
+ field public static final int system_accent1_900;
+ field public static final int system_accent2_0;
+ field public static final int system_accent2_100;
+ field public static final int system_accent2_1000;
+ field public static final int system_accent2_200;
+ field public static final int system_accent2_300;
+ field public static final int system_accent2_400;
+ field public static final int system_accent2_50;
+ field public static final int system_accent2_500;
+ field public static final int system_accent2_600;
+ field public static final int system_accent2_700;
+ field public static final int system_accent2_800;
+ field public static final int system_accent2_900;
+ field public static final int system_accent3_0;
+ field public static final int system_accent3_100;
+ field public static final int system_accent3_1000;
+ field public static final int system_accent3_200;
+ field public static final int system_accent3_300;
+ field public static final int system_accent3_400;
+ field public static final int system_accent3_50;
+ field public static final int system_accent3_500;
+ field public static final int system_accent3_600;
+ field public static final int system_accent3_700;
+ field public static final int system_accent3_800;
+ field public static final int system_accent3_900;
+ field public static final int system_neutral1_0;
+ field public static final int system_neutral1_100;
+ field public static final int system_neutral1_1000;
+ field public static final int system_neutral1_200;
+ field public static final int system_neutral1_300;
+ field public static final int system_neutral1_400;
+ field public static final int system_neutral1_50;
+ field public static final int system_neutral1_500;
+ field public static final int system_neutral1_600;
+ field public static final int system_neutral1_700;
+ field public static final int system_neutral1_800;
+ field public static final int system_neutral1_900;
+ field public static final int system_neutral2_0;
+ field public static final int system_neutral2_100;
+ field public static final int system_neutral2_1000;
+ field public static final int system_neutral2_200;
+ field public static final int system_neutral2_300;
+ field public static final int system_neutral2_400;
+ field public static final int system_neutral2_50;
+ field public static final int system_neutral2_500;
+ field public static final int system_neutral2_600;
+ field public static final int system_neutral2_700;
+ field public static final int system_neutral2_800;
+ field public static final int system_neutral2_900;
field public static final int tab_indicator_text = 17170441; // 0x1060009
field @Deprecated public static final int tertiary_text_dark = 17170448; // 0x1060010
field @Deprecated public static final int tertiary_text_light = 17170449; // 0x1060011
@@ -1811,9 +1811,9 @@
field public static final int dialog_min_width_minor = 17104900; // 0x1050004
field public static final int notification_large_icon_height = 17104902; // 0x1050006
field public static final int notification_large_icon_width = 17104901; // 0x1050005
- field public static final int system_app_widget_background_radius = 17104904; // 0x1050008
- field public static final int system_app_widget_inner_radius = 17104905; // 0x1050009
- field public static final int system_app_widget_internal_padding = 17104906; // 0x105000a
+ field public static final int system_app_widget_background_radius;
+ field public static final int system_app_widget_inner_radius;
+ field public static final int system_app_widget_internal_padding;
field public static final int thumbnail_height = 17104897; // 0x1050001
field public static final int thumbnail_width = 17104898; // 0x1050002
}
@@ -27093,12 +27093,13 @@
public final class VcnGatewayConnectionConfig {
method @NonNull public int[] getExposedCapabilities();
+ method @NonNull public String getGatewayConnectionName();
method @IntRange(from=android.net.vcn.VcnGatewayConnectionConfig.MIN_MTU_V6) public int getMaxMtu();
method @NonNull public long[] getRetryInterval();
}
public static final class VcnGatewayConnectionConfig.Builder {
- ctor public VcnGatewayConnectionConfig.Builder(@NonNull android.net.vcn.VcnControlPlaneConfig);
+ ctor public VcnGatewayConnectionConfig.Builder(@NonNull String, @NonNull android.net.vcn.VcnControlPlaneConfig);
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int);
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build();
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int);
@@ -27122,7 +27123,7 @@
public abstract static class VcnManager.VcnStatusCallback {
ctor public VcnManager.VcnStatusCallback();
- method public abstract void onGatewayConnectionError(@NonNull int[], int, @Nullable Throwable);
+ method public abstract void onGatewayConnectionError(@NonNull String, int, @Nullable Throwable);
method public abstract void onStatusChanged(int);
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index bfc9144..696494b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -313,15 +313,15 @@
public static final class R.attr {
field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
- field public static final int hotwordDetectionService = 16844326; // 0x1010626
+ field public static final int hotwordDetectionService;
field public static final int isVrOnly = 16844152; // 0x1010578
field public static final int minExtensionVersion = 16844305; // 0x1010611
- field public static final int playHomeTransitionSound = 16844358; // 0x1010646
+ field public static final int playHomeTransitionSound;
field public static final int requiredSystemPropertyName = 16844133; // 0x1010565
field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566
field public static final int sdkVersion = 16844304; // 0x1010610
field public static final int supportsAmbientMode = 16844173; // 0x101058d
- field public static final int throttleDurationMillis = 16844360; // 0x1010648
+ field public static final int throttleDurationMillis;
field public static final int userRestriction = 16844164; // 0x1010584
}
@@ -350,8 +350,8 @@
}
public static final class R.string {
- field public static final int config_customMediaKeyDispatcher = 17039404; // 0x104002c
- field public static final int config_customMediaSessionPolicyProvider = 17039405; // 0x104002d
+ field public static final int config_customMediaKeyDispatcher;
+ field public static final int config_customMediaSessionPolicyProvider;
field public static final int config_defaultAssistant = 17039393; // 0x1040021
field public static final int config_defaultBrowser = 17039394; // 0x1040022
field public static final int config_defaultCallRedirection = 17039397; // 0x1040025
@@ -364,15 +364,15 @@
field public static final int config_helpIntentNameKey = 17039390; // 0x104001e
field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
- field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
- field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
- field public static final int config_systemContacts = 17039403; // 0x104002b
+ field public static final int config_systemAutomotiveCluster;
+ field public static final int config_systemAutomotiveProjection;
+ field public static final int config_systemContacts;
field public static final int config_systemGallery = 17039399; // 0x1040027
- field public static final int config_systemShell = 17039402; // 0x104002a
- field public static final int config_systemSpeechRecognizer = 17039406; // 0x104002e
- field public static final int config_systemTelevisionNotificationHandler = 17039409; // 0x1040031
- field public static final int config_systemWellbeing = 17039408; // 0x1040030
- field public static final int config_systemWifiCoexManager = 17039407; // 0x104002f
+ field public static final int config_systemShell;
+ field public static final int config_systemSpeechRecognizer;
+ field public static final int config_systemTelevisionNotificationHandler;
+ field public static final int config_systemWellbeing;
+ field public static final int config_systemWifiCoexManager;
}
public static final class R.style {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 6745a69..7b6f9b3 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -58,8 +58,8 @@
public static final class R.string {
field public static final int config_defaultAssistant = 17039393; // 0x1040021
field public static final int config_defaultDialer = 17039395; // 0x1040023
- field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
- field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
+ field public static final int config_systemAutomotiveCluster;
+ field public static final int config_systemAutomotiveProjection;
field public static final int config_systemGallery = 17039399; // 0x1040027
}
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 0952b3e..fa9142c 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -896,11 +896,13 @@
};
/**
- * This change id forces the packages it is applied to to be resizable. We only allow resizing
- * in fullscreen windowing mode, but not forcing the app into resizable multi-windowing mode.
+ * This change id forces the packages it is applied to be resizable. It won't change whether
+ * the app can be put into multi-windowing mode, but allow the app to resize when the window
+ * container resizes, such as display size change.
* @hide
*/
@ChangeId
+ @Overridable
@Disabled
@TestApi
public static final long FORCE_RESIZE_APP = 174042936L; // buganizer id
@@ -910,6 +912,7 @@
* @hide
*/
@ChangeId
+ @Overridable
@Disabled
@TestApi
public static final long FORCE_NON_RESIZE_APP = 181136395L; // buganizer id
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 7696cbe..7ecb112 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -42,7 +42,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import libcore.io.IoUtils;
@@ -162,20 +161,18 @@
intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
- Handler handler = BackgroundThread.getHandler();
- mContext.registerReceiverAsUser(
- mPackageReceiver, UserHandle.ALL, intentFilter, null, handler);
+ mContext.registerReceiverAsUser(mPackageReceiver, UserHandle.ALL, intentFilter, null, null);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiver(mExternalReceiver, sdFilter, null, handler);
+ mContext.registerReceiver(mExternalReceiver, sdFilter);
// Register for user-related events
IntentFilter userFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_USER_REMOVED);
- mContext.registerReceiver(mUserRemovedReceiver, userFilter, null, handler);
+ mContext.registerReceiver(mUserRemovedReceiver, userFilter);
}
private void handlePackageEvent(Intent intent, int userId) {
@@ -268,7 +265,7 @@
public void setListener(RegisteredServicesCacheListener<V> listener, Handler handler) {
if (handler == null) {
- handler = BackgroundThread.getHandler();
+ handler = new Handler(mContext.getMainLooper());
}
synchronized (this) {
mHandler = handler;
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index cdd8265..4c6255d 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -376,10 +376,13 @@
int[] stateSpec = new int[numAttrs];
for (int i = 0; i < numAttrs; i++) {
final int stateResId = attrs.getAttributeNameResource(i);
+ if (stateResId == R.attr.lStar) {
+ // Non-finalized resource ids cannot be used in switch statements.
+ continue;
+ }
switch (stateResId) {
case R.attr.color:
case R.attr.alpha:
- case R.attr.lStar:
// Recognized attribute, ignore.
break;
default:
diff --git a/core/java/android/net/vcn/IVcnStatusCallback.aidl b/core/java/android/net/vcn/IVcnStatusCallback.aidl
index 236ae8b..11bc443 100644
--- a/core/java/android/net/vcn/IVcnStatusCallback.aidl
+++ b/core/java/android/net/vcn/IVcnStatusCallback.aidl
@@ -20,7 +20,7 @@
oneway interface IVcnStatusCallback {
void onVcnStatusChanged(int statusCode);
void onGatewayConnectionError(
- in int[] gatewayNetworkCapabilities,
+ in String gatewayConnectionName,
int errorCode,
in String exceptionClass,
in String exceptionMessage);
diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index 52cc218..d41c0b4 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -183,12 +183,25 @@
*
* @param gatewayConnectionConfig the configuration for an individual gateway connection
* @return this {@link Builder} instance, for chaining
+ * @throws IllegalArgumentException if a VcnGatewayConnectionConfig has already been set for
+ * this {@link VcnConfig} with the same GatewayConnection name (as returned via {@link
+ * VcnGatewayConnectionConfig#getGatewayConnectionName()}).
*/
@NonNull
public Builder addGatewayConnectionConfig(
@NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) {
Objects.requireNonNull(gatewayConnectionConfig, "gatewayConnectionConfig was null");
+ for (final VcnGatewayConnectionConfig vcnGatewayConnectionConfig :
+ mGatewayConnectionConfigs) {
+ if (vcnGatewayConnectionConfig
+ .getGatewayConnectionName()
+ .equals(gatewayConnectionConfig.getGatewayConnectionName())) {
+ throw new IllegalArgumentException(
+ "GatewayConnection for specified name already exists");
+ }
+ }
+
mGatewayConnectionConfigs.add(gatewayConnectionConfig);
return this;
}
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index d4e8e2d..75db3820 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -148,6 +148,8 @@
TimeUnit.MINUTES.toMillis(5),
TimeUnit.MINUTES.toMillis(15)
};
+ private static final String GATEWAY_CONNECTION_NAME_KEY = "mGatewayConnectionName";
+ @NonNull private final String mGatewayConnectionName;
private static final String CTRL_PLANE_CONFIG_KEY = "mCtrlPlaneConfig";
@NonNull private VcnControlPlaneConfig mCtrlPlaneConfig;
@@ -166,11 +168,13 @@
/** Builds a VcnGatewayConnectionConfig with the specified parameters. */
private VcnGatewayConnectionConfig(
+ @NonNull String gatewayConnectionName,
@NonNull VcnControlPlaneConfig ctrlPlaneConfig,
@NonNull Set<Integer> exposedCapabilities,
@NonNull Set<Integer> underlyingCapabilities,
@NonNull long[] retryIntervalsMs,
@IntRange(from = MIN_MTU_V6) int maxMtu) {
+ mGatewayConnectionName = gatewayConnectionName;
mCtrlPlaneConfig = ctrlPlaneConfig;
mExposedCapabilities = new TreeSet(exposedCapabilities);
mUnderlyingCapabilities = new TreeSet(underlyingCapabilities);
@@ -192,6 +196,7 @@
final PersistableBundle underlyingCapsBundle =
in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY);
+ mGatewayConnectionName = in.getString(GATEWAY_CONNECTION_NAME_KEY);
mCtrlPlaneConfig = VcnControlPlaneConfig.fromPersistableBundle(ctrlPlaneConfigBundle);
mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
@@ -204,6 +209,7 @@
}
private void validate() {
+ Objects.requireNonNull(mGatewayConnectionName, "gatewayConnectionName was null");
Objects.requireNonNull(mCtrlPlaneConfig, "control plane config was null");
Preconditions.checkArgument(
@@ -242,6 +248,20 @@
}
/**
+ * Returns the configured Gateway Connection name.
+ *
+ * <p>This name is used by the configuring apps to distinguish between
+ * VcnGatewayConnectionConfigs configured on a single {@link VcnConfig}. This will be used as
+ * the identifier in VcnStatusCallback invocations.
+ *
+ * @see VcnManager.VcnStatusCallback#onGatewayConnectionError
+ */
+ @NonNull
+ public String getGatewayConnectionName() {
+ return mGatewayConnectionName;
+ }
+
+ /**
* Returns control plane configuration.
*
* @hide
@@ -364,6 +384,7 @@
new ArrayList<>(mUnderlyingCapabilities),
PersistableBundleUtils.INTEGER_SERIALIZER);
+ result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
result.putPersistableBundle(CTRL_PLANE_CONFIG_KEY, ctrlPlaneConfigBundle);
result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle);
@@ -376,6 +397,7 @@
@Override
public int hashCode() {
return Objects.hash(
+ mGatewayConnectionName,
mExposedCapabilities,
mUnderlyingCapabilities,
Arrays.hashCode(mRetryIntervalsMs),
@@ -389,7 +411,8 @@
}
final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other;
- return mExposedCapabilities.equals(rhs.mExposedCapabilities)
+ return mGatewayConnectionName.equals(rhs.mGatewayConnectionName)
+ && mExposedCapabilities.equals(rhs.mExposedCapabilities)
&& mUnderlyingCapabilities.equals(rhs.mUnderlyingCapabilities)
&& Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
&& mMaxMtu == rhs.mMaxMtu;
@@ -399,6 +422,7 @@
* This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects.
*/
public static final class Builder {
+ @NonNull private final String mGatewayConnectionName;
@NonNull private final VcnControlPlaneConfig mCtrlPlaneConfig;
@NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
@NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet();
@@ -412,12 +436,22 @@
/**
* Construct a Builder object.
*
+ * @param gatewayConnectionName the String GatewayConnection name for this
+ * VcnGatewayConnectionConfig. Each VcnGatewayConnectionConfig within a {@link
+ * VcnConfig} must be given a unique name. This name is used by the caller to
+ * distinguish between VcnGatewayConnectionConfigs configured on a single {@link
+ * VcnConfig}. This will be used as the identifier in VcnStatusCallback invocations.
* @param ctrlPlaneConfig the control plane configuration
* @see VcnControlPlaneConfig
+ * @see VcnManager.VcnStatusCallback#onGatewayConnectionError
*/
- public Builder(@NonNull VcnControlPlaneConfig ctrlPlaneConfig) {
+ public Builder(
+ @NonNull String gatewayConnectionName,
+ @NonNull VcnControlPlaneConfig ctrlPlaneConfig) {
+ Objects.requireNonNull(gatewayConnectionName, "gatewayConnectionName was null");
Objects.requireNonNull(ctrlPlaneConfig, "ctrlPlaneConfig was null");
+ mGatewayConnectionName = gatewayConnectionName;
mCtrlPlaneConfig = ctrlPlaneConfig;
}
@@ -562,6 +596,7 @@
@NonNull
public VcnGatewayConnectionConfig build() {
return new VcnGatewayConnectionConfig(
+ mGatewayConnectionName,
mCtrlPlaneConfig,
mExposedCapabilities,
mUnderlyingCapabilities,
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index abd41da..d09094c 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -445,18 +445,16 @@
* Invoked when a VCN Gateway Connection corresponding to this callback's subscription group
* encounters an error.
*
- * @param networkCapabilities an array of NetworkCapabilities.NET_CAPABILITY_* capabilities
- * for the Gateway Connection that encountered the error, for identification purposes.
- * These will be a sorted list with no duplicates and will match {@link
- * VcnGatewayConnectionConfig#getExposedCapabilities()} for one of the {@link
- * VcnGatewayConnectionConfig}s set in the {@link VcnConfig} for this subscription
- * group.
+ * @param gatewayConnectionName the String GatewayConnection name for the GatewayConnection
+ * encountering an error. This will match the name for exactly one {@link
+ * VcnGatewayConnectionConfig} for the {@link VcnConfig} configured for this callback's
+ * subscription group
* @param errorCode the code to indicate the error that occurred
* @param detail Throwable to provide additional information about the error, or {@code
* null} if none
*/
public abstract void onGatewayConnectionError(
- @NonNull int[] networkCapabilities,
+ @NonNull String gatewayConnectionName,
@VcnErrorCode int errorCode,
@Nullable Throwable detail);
}
@@ -586,7 +584,7 @@
// TODO(b/180521637): use ServiceSpecificException for safer Exception 'parceling'
@Override
public void onGatewayConnectionError(
- @NonNull int[] networkCapabilities,
+ @NonNull String gatewayConnectionName,
@VcnErrorCode int errorCode,
@Nullable String exceptionClass,
@Nullable String exceptionMessage) {
@@ -597,7 +595,7 @@
mExecutor.execute(
() ->
mCallback.onGatewayConnectionError(
- networkCapabilities, errorCode, cause)));
+ gatewayConnectionName, errorCode, cause)));
}
private static Throwable createThrowableByClassName(
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index 2b6f336..0331483 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -124,6 +124,30 @@
public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;
+ /**
+ * Identifiers of models used for power estimation.
+ *
+ * @hide
+ */
+ @IntDef(prefix = {"POWER_MODEL_"}, value = {
+ POWER_MODEL_POWER_PROFILE,
+ POWER_MODEL_MEASURED_ENERGY,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PowerModel {
+ }
+
+ /**
+ * Power model that is based on average consumption rates that hardware components
+ * consume in various states.
+ */
+ public static final int POWER_MODEL_POWER_PROFILE = 0;
+
+ /**
+ * Power model that is based on energy consumption measured by on-device power monitors.
+ */
+ public static final int POWER_MODEL_MEASURED_ENERGY = 1;
+
private final PowerComponents mPowerComponents;
protected BatteryConsumer(@NonNull PowerComponents powerComponents) {
@@ -149,6 +173,16 @@
}
/**
+ * Returns the ID of the model that was used for power estimation.
+ *
+ * @param componentId The ID of the power component, e.g.
+ * {@link BatteryConsumer#POWER_COMPONENT_CPU}.
+ */
+ public @PowerModel int getPowerModel(@BatteryConsumer.PowerComponent int componentId) {
+ return mPowerComponents.getPowerModel(componentId);
+ }
+
+ /**
* Returns the amount of drain attributed to the specified custom drain type.
*
* @param componentId The ID of the custom power component.
@@ -188,9 +222,22 @@
protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
final PowerComponents.Builder mPowerComponentsBuilder;
- public BaseBuilder(int customPowerComponentCount, int customTimeComponentCount) {
+ public BaseBuilder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includePowerModels) {
mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount,
- customTimeComponentCount);
+ customTimeComponentCount, includePowerModels);
+ }
+
+ /**
+ * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
+ *
+ * @param componentId The ID of the power component, e.g.
+ * {@link BatteryConsumer#POWER_COMPONENT_CPU}.
+ * @param componentPower Amount of consumed power in mAh.
+ */
+ @NonNull
+ public T setConsumedPower(@PowerComponent int componentId, double componentPower) {
+ return setConsumedPower(componentId, componentPower, POWER_MODEL_POWER_PROFILE);
}
/**
@@ -202,8 +249,9 @@
*/
@SuppressWarnings("unchecked")
@NonNull
- public T setConsumedPower(@PowerComponent int componentId, double componentPower) {
- mPowerComponentsBuilder.setConsumedPower(componentId, componentPower);
+ public T setConsumedPower(@PowerComponent int componentId, double componentPower,
+ @PowerModel int powerModel) {
+ mPowerComponentsBuilder.setConsumedPower(componentId, componentPower, powerModel);
return (T) this;
}
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index bcd00b2..f288774 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -261,6 +261,7 @@
public static final class Builder {
private final int mCustomPowerComponentCount;
private final int mCustomTimeComponentCount;
+ private final boolean mIncludePowerModels;
private long mStatsStartTimestampMs;
private int mDischargePercentage;
private double mDischargedPowerLowerBoundMah;
@@ -277,8 +278,14 @@
private List<BatteryStats.HistoryTag> mHistoryTagPool;
public Builder(int customPowerComponentCount, int customTimeComponentCount) {
+ this(customPowerComponentCount, customTimeComponentCount, false);
+ }
+
+ public Builder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includePowerModels) {
mCustomPowerComponentCount = customPowerComponentCount;
mCustomTimeComponentCount = customTimeComponentCount;
+ mIncludePowerModels = includePowerModels;
}
/**
@@ -360,7 +367,7 @@
UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
if (builder == null) {
builder = new UidBatteryConsumer.Builder(mCustomPowerComponentCount,
- mCustomTimeComponentCount, batteryStatsUid);
+ mCustomTimeComponentCount, mIncludePowerModels, batteryStatsUid);
mUidBatteryConsumerBuilders.put(uid, builder);
}
return builder;
@@ -376,7 +383,7 @@
SystemBatteryConsumer.Builder builder = mSystemBatteryConsumerBuilders.get(drainType);
if (builder == null) {
builder = new SystemBatteryConsumer.Builder(mCustomPowerComponentCount,
- mCustomTimeComponentCount, drainType);
+ mCustomTimeComponentCount, mIncludePowerModels, drainType);
mSystemBatteryConsumerBuilders.put(drainType, builder);
}
return builder;
@@ -391,7 +398,7 @@
UserBatteryConsumer.Builder builder = mUserBatteryConsumerBuilders.get(userId);
if (builder == null) {
builder = new UserBatteryConsumer.Builder(mCustomPowerComponentCount,
- mCustomTimeComponentCount, userId);
+ mCustomTimeComponentCount, mIncludePowerModels, userId);
mUserBatteryConsumerBuilders.put(userId, builder);
}
return builder;
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
index 85861bc..5080442 100644
--- a/core/java/android/os/BatteryUsageStatsQuery.java
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -60,6 +60,12 @@
*/
public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_HISTORY = 2;
+ /**
+ * Indicates that identifiers of power models used for computations of power
+ * consumption should be included in the BatteryUsageStats.
+ */
+ public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS = 4;
+
private static final long DEFAULT_MAX_STATS_AGE_MS = 5 * 60 * 1000;
private final int mFlags;
@@ -187,6 +193,17 @@
}
/**
+ * Requests to return identifiers of models that were used for estimation
+ * of power consumption.
+ *
+ * Should only be used for testing and debugging.
+ */
+ public Builder includePowerModels() {
+ mFlags |= BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS;
+ return this;
+ }
+
+ /**
* Set the client's tolerance for stale battery stats. The data may be up to
* this many milliseconds out-of-date.
*/
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index d239b23..238f451 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -33,12 +33,14 @@
private final double[] mPowerComponentsMah;
private final long[] mTimeComponentsMs;
private final int mCustomPowerComponentCount;
+ private final byte[] mPowerModels;
PowerComponents(@NonNull Builder builder) {
mCustomPowerComponentCount = builder.mCustomPowerComponentCount;
mPowerComponentsMah = builder.mPowerComponentsMah;
mTimeComponentsMs = builder.mTimeComponentsMs;
mTotalConsumedPowerMah = builder.getTotalPower();
+ mPowerModels = builder.mPowerModels;
}
PowerComponents(@NonNull Parcel source) {
@@ -46,6 +48,12 @@
mCustomPowerComponentCount = source.readInt();
mPowerComponentsMah = source.createDoubleArray();
mTimeComponentsMs = source.createLongArray();
+ if (source.readBoolean()) {
+ mPowerModels = new byte[BatteryConsumer.POWER_COMPONENT_COUNT];
+ source.readByteArray(mPowerModels);
+ } else {
+ mPowerModels = null;
+ }
}
/** Writes contents to Parcel */
@@ -54,6 +62,12 @@
dest.writeInt(mCustomPowerComponentCount);
dest.writeDoubleArray(mPowerComponentsMah);
dest.writeLongArray(mTimeComponentsMs);
+ if (mPowerModels != null) {
+ dest.writeBoolean(true);
+ dest.writeByteArray(mPowerModels);
+ } else {
+ dest.writeBoolean(false);
+ }
}
/**
@@ -103,6 +117,15 @@
}
}
+ @BatteryConsumer.PowerModel
+ int getPowerModel(@BatteryConsumer.PowerComponent int component) {
+ if (mPowerModels == null) {
+ throw new IllegalStateException(
+ "Power model IDs were not requested in the BatteryUsageStatsQuery");
+ }
+ return mPowerModels[component];
+ }
+
/**
* Returns the amount of time used by the specified component, e.g. CPU, WiFi etc.
*
@@ -148,14 +171,21 @@
private final double[] mPowerComponentsMah;
private final int mCustomPowerComponentCount;
private final long[] mTimeComponentsMs;
+ private final byte[] mPowerModels;
- Builder(int customPowerComponentCount, int customTimeComponentCount) {
+ Builder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includePowerModels) {
mCustomPowerComponentCount = customPowerComponentCount;
int powerComponentCount =
BatteryConsumer.POWER_COMPONENT_COUNT + customPowerComponentCount;
mPowerComponentsMah = new double[powerComponentCount];
mTimeComponentsMs =
new long[BatteryConsumer.TIME_COMPONENT_COUNT + customTimeComponentCount];
+ if (includePowerModels) {
+ mPowerModels = new byte[BatteryConsumer.POWER_COMPONENT_COUNT];
+ } else {
+ mPowerModels = null;
+ }
}
/**
@@ -167,7 +197,7 @@
*/
@NonNull
public Builder setConsumedPower(@BatteryConsumer.PowerComponent int componentId,
- double componentPower) {
+ double componentPower, @BatteryConsumer.PowerModel int powerModel) {
if (componentId >= BatteryConsumer.POWER_COMPONENT_COUNT) {
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
@@ -178,6 +208,9 @@
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
}
+ if (mPowerModels != null) {
+ mPowerModels[componentId] = (byte) powerModel;
+ }
return this;
}
diff --git a/core/java/android/os/SystemBatteryConsumer.java b/core/java/android/os/SystemBatteryConsumer.java
index 5f35332..e973e4c 100644
--- a/core/java/android/os/SystemBatteryConsumer.java
+++ b/core/java/android/os/SystemBatteryConsumer.java
@@ -141,8 +141,8 @@
private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
Builder(int customPowerComponentCount, int customTimeComponentCount,
- @DrainType int drainType) {
- super(customPowerComponentCount, customTimeComponentCount);
+ boolean includePowerModels, @DrainType int drainType) {
+ super(customPowerComponentCount, customTimeComponentCount, includePowerModels);
mDrainType = drainType;
}
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index dfa0c39..87c263b 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -140,8 +140,8 @@
private boolean mExcludeFromBatteryUsageStats;
public Builder(int customPowerComponentCount, int customTimeComponentCount,
- @NonNull BatteryStats.Uid batteryStatsUid) {
- super(customPowerComponentCount, customTimeComponentCount);
+ boolean includePowerModels, @NonNull BatteryStats.Uid batteryStatsUid) {
+ super(customPowerComponentCount, customTimeComponentCount, includePowerModels);
mBatteryStatsUid = batteryStatsUid;
mUid = batteryStatsUid.getUid();
}
diff --git a/core/java/android/os/UserBatteryConsumer.java b/core/java/android/os/UserBatteryConsumer.java
index 94e567f..7832208 100644
--- a/core/java/android/os/UserBatteryConsumer.java
+++ b/core/java/android/os/UserBatteryConsumer.java
@@ -77,8 +77,9 @@
private final int mUserId;
private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
- Builder(int customPowerComponentCount, int customTimeComponentCount, int userId) {
- super(customPowerComponentCount, customTimeComponentCount);
+ Builder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includePowerModels, int userId) {
+ super(customPowerComponentCount, customTimeComponentCount, includePowerModels);
mUserId = userId;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 259d3ac..1ff625d3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -8600,8 +8600,6 @@
// available, we cannot compute end-to-end input latency metrics.
return;
}
- final long gpuCompletedTime = data[FrameMetrics.Index.GPU_COMPLETED];
- mReceiver.reportTimeline(inputEventId, gpuCompletedTime, presentTime);
}
}
HardwareRendererObserver mHardwareRendererObserver;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 957e416..6bf4645 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -34,7 +34,7 @@
interface IBatteryStats {
// These first methods are also called by native code, so must
- // be kept in sync with frameworks/native/libs/binder/include/binder/IBatteryStats.h
+ // be kept in sync with frameworks/native/libs/binder/include_batterystats/batterystats/IBatteryStats.h
void noteStartSensor(int uid, int sensor);
void noteStopSensor(int uid, int sensor);
void noteStartVideo(int uid);
diff --git a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
index 586607e..2f49582 100644
--- a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
+++ b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
@@ -44,14 +44,15 @@
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+ final long measuredEnergyUC = batteryStats.getScreenDozeMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredEnergyUC, query);
final long durationMs = calculateDuration(batteryStats, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED);
- final double powerMah = getMeasuredOrEstimatedPower(
- batteryStats.getScreenDozeMeasuredBatteryConsumptionUC(),
- mPowerEstimator, durationMs, query.shouldForceUsePowerProfileModel());
+ final double powerMah = getMeasuredOrEstimatedPower(powerModel,
+ measuredEnergyUC, mPowerEstimator, durationMs);
builder.getOrCreateSystemBatteryConsumerBuilder(
SystemBatteryConsumer.DRAIN_TYPE_AMBIENT_DISPLAY)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, powerMah)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, powerMah, powerModel)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, durationMs);
}
@@ -64,10 +65,12 @@
@Override
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
+ final long measuredEnergyUC = batteryStats.getScreenDozeMeasuredBatteryConsumptionUC();
final long durationMs = calculateDuration(batteryStats, rawRealtimeUs, statsType);
- final double powerMah = getMeasuredOrEstimatedPower(
+ final int powerModel = getPowerModel(measuredEnergyUC);
+ final double powerMah = getMeasuredOrEstimatedPower(powerModel,
batteryStats.getScreenDozeMeasuredBatteryConsumptionUC(),
- mPowerEstimator, durationMs, false);
+ mPowerEstimator, durationMs);
if (powerMah > 0) {
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.AMBIENT_DISPLAY, null, 0);
bs.usagePowerMah = powerMah;
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index b0920b0..ac72d29 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -41,7 +41,6 @@
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
-import android.os.BatteryProperty;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Build;
@@ -58,7 +57,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
@@ -150,14 +148,6 @@
public class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
private static final boolean DEBUG = false;
-
- // TODO(b/169376495): STOPSHIP if true
- private static final boolean DEBUG_FOREGROUND_STATS = true;
-
- private static final boolean ENABLE_FOREGROUND_STATS_COLLECTION =
- DEBUG_FOREGROUND_STATS && SystemProperties.getBoolean(
- "debug.battery_foreground_stats_collection", false);
-
public static final boolean DEBUG_ENERGY = false;
private static final boolean DEBUG_ENERGY_CPU = DEBUG_ENERGY;
private static final boolean DEBUG_BINDER_STATS = false;
@@ -752,37 +742,6 @@
long mTrackRunningHistoryElapsedRealtimeMs = 0;
long mTrackRunningHistoryUptimeMs = 0;
- private static final int FOREGROUND_UID_INITIAL_CAPACITY = 10;
- private static final int INVALID_UID = -1;
-
- private final IntArray mForegroundUids = ENABLE_FOREGROUND_STATS_COLLECTION
- ? new IntArray(FOREGROUND_UID_INITIAL_CAPACITY) : null;
-
- // Last recorded battery energy capacity.
- // This is used for computing foregrund power per application.
- // See: PowerForUid below
- private long mLastBatteryEnergyCapacityNwh = 0;
-
- private static final class PowerForUid {
- public long energyNwh = 0;
- // Same as energyNwh, but not tracked for the first 2 minutes;
- public long filteredEnergyNwh = 0;
- public double totalHours = 0;
- public long baseTimeMs = 0;
-
- double computePower() {
- // units in nW
- return totalHours != 0 ? energyNwh / totalHours : -1.0;
- }
-
- double computeFilteredPower() {
- // units in nW
- return totalHours != 0 ? filteredEnergyNwh / totalHours : -1.0;
- }
- }
- private final HashMap<Integer, PowerForUid> mUidToPower = ENABLE_FOREGROUND_STATS_COLLECTION
- ? new HashMap<>() : null;
-
@NonNull
final BatteryStatsHistory mBatteryStatsHistory;
@@ -1094,7 +1053,6 @@
private int mNumConnectivityChange;
private int mBatteryVoltageMv = -1;
- private int mBatteryChargeUah = -1;
private int mEstimatedBatteryCapacityMah = -1;
private int mMinLearnedBatteryCapacityUah = -1;
@@ -4020,49 +3978,6 @@
// TODO(b/155216561): It is possible for isolated uids to be in a higher
// state than its parent uid. We should track the highest state within the union of host
// and isolated uids rather than only the parent uid.
-
-
- int uidState = mapToInternalProcessState(state);
-
- boolean isForeground = (uidState == Uid.PROCESS_STATE_TOP)
- || (uidState == Uid.PROCESS_STATE_FOREGROUND);
-
-
- if (ENABLE_FOREGROUND_STATS_COLLECTION) {
- boolean previouslyInForegrond = false;
- for (int i = 0; i < mForegroundUids.size(); i++) {
- if (mForegroundUids.get(i) == uid) {
- previouslyInForegrond = true;
- if (!isForeground) {
- // If we were previously in the foreground, remove the uid
- // from the foreground set and dirty the slot.
- mForegroundUids.set(i, INVALID_UID);
- final PowerForUid pfu =
- mUidToPower.computeIfAbsent(uid, unused -> new PowerForUid());
- pfu.baseTimeMs = 0;
- break;
- }
- }
- }
-
- if (!previouslyInForegrond && isForeground) {
- boolean addedToForeground = false;
- // Check if we have a free slot to clobber...
- for (int i = 0; i < mForegroundUids.size(); i++) {
- if (mForegroundUids.get(i) == INVALID_UID) {
- addedToForeground = true;
- mForegroundUids.set(i, uid);
- break;
- }
- }
-
- // ...if not, append to the end of the array.
- if (!addedToForeground) {
- mForegroundUids.add(uid);
- }
- }
- }
-
FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid,
ActivityManager.processStateAmToProto(state));
getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs)
@@ -13547,7 +13462,6 @@
doWrite = true;
resetAllStatsLocked(mSecUptime, mSecRealtime);
if (chargeUah > 0 && level > 0) {
- mBatteryChargeUah = chargeUah;
// Only use the reported coulomb charge value if it is supported and reported.
mEstimatedBatteryCapacityMah = (int) ((chargeUah / 1000) / (level / 100.0));
}
@@ -13720,48 +13634,7 @@
startRecordingHistory(elapsedRealtimeMs, uptimeMs, true);
}
}
-
mBatteryVoltageMv = voltageMv;
-
- if (ENABLE_FOREGROUND_STATS_COLLECTION) {
- if (onBattery) {
- final long energyNwh = (voltageMv * (long) chargeUah);
- final long energyDelta = mLastBatteryEnergyCapacityNwh - energyNwh;
- for (int i = 0; i < mForegroundUids.size(); i++) {
- final int uid = mForegroundUids.get(i);
- if (uid == INVALID_UID) {
- continue;
- }
- final PowerForUid pfu = mUidToPower
- .computeIfAbsent(uid, unused -> new PowerForUid());
- if (pfu.baseTimeMs <= 0) {
- pfu.baseTimeMs = currentTimeMs;
- } else {
- // Check if mLastBatteryEnergyCapacityNwh > energyNwh,
- // to make sure we only count discharges
- if (energyDelta > 0) {
- pfu.energyNwh += energyDelta;
- // Convert from milliseconds to hours
- // 1000 ms per second * 3600 seconds per hour
- pfu.totalHours += ((double) (currentTimeMs - pfu.baseTimeMs)
- / (1.0 * 1000 * 60 * 60));
- // Now convert from 2 minutes to hours
- // 2 minutes = 1/30 of an hour
- if (pfu.totalHours > (2.0 / 60)) {
- pfu.filteredEnergyNwh += energyDelta;
- }
-
- }
- pfu.baseTimeMs = currentTimeMs;
- }
- }
- mLastBatteryEnergyCapacityNwh = energyNwh;
- } else if (onBattery != mOnBattery) {
- // Transition to onBattery = false
- mUidToPower.values().forEach(v -> v.baseTimeMs = 0);
- }
- }
-
mCurrentBatteryLevel = level;
if (mDischargePlugLevel < 0) {
mDischargePlugLevel = level;
@@ -16679,48 +16552,6 @@
}
public void dumpLocked(Context context, PrintWriter pw, int flags, int reqUid, long histStart) {
- if (ENABLE_FOREGROUND_STATS_COLLECTION) {
- long actualChargeUah = -1;
- long actualEnergyNwh = -1;
- try {
- IBatteryPropertiesRegistrar registrar =
- IBatteryPropertiesRegistrar.Stub.asInterface(
- ServiceManager.getService("batteryproperties"));
- if (registrar != null) {
- BatteryProperty prop = new BatteryProperty();
- if (registrar.getProperty(
- BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER, prop) == 0) {
- actualChargeUah = prop.getLong();
- }
- prop = new BatteryProperty();
- if (registrar.getProperty(
- BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER, prop) == 0) {
- actualEnergyNwh = prop.getLong();
- }
- }
- } catch (RemoteException e) {
- // Ignore.
- }
- pw.printf("ActualCharge (uAh): %d\n", (int) actualChargeUah);
- pw.printf("ActualEnergy (nWh): %d\n", actualEnergyNwh);
- pw.printf("mBatteryCharge (uAh): %d\n", mBatteryChargeUah);
- pw.printf("mBatteryVolts (mV): %d\n", mBatteryVoltageMv);
- pw.printf("est energy (nWh): %d\n", mBatteryVoltageMv * (long) mBatteryChargeUah);
- pw.printf("mEstimatedBatteryCapacity (mAh): %d\n", mEstimatedBatteryCapacityMah);
- pw.printf("mMinLearnedBatteryCapacity (uAh): %d\n", mMinLearnedBatteryCapacityUah);
- pw.printf("mMaxLearnedBatteryCapacity (uAh): %d\n", mMaxLearnedBatteryCapacityUah);
- pw.printf("est. capacity: %f\n",
- (float) actualChargeUah / (mEstimatedBatteryCapacityMah * 1000));
- pw.printf("mCurrentBatteryLevel: %d\n", mCurrentBatteryLevel);
- pw.println("Total Power per app:");
- mUidToPower.entrySet().forEach(e ->
- pw.printf("Uid: %d, Total watts (nW): %f\n",
- e.getKey(), e.getValue().computePower()));
- pw.println("Total Power per app after first 2 minutes initial launch:");
- mUidToPower.entrySet().forEach(e ->
- pw.printf("Uid: %d, Total watts (nW): %f\n",
- e.getKey(), e.getValue().computeFilteredPower()));
- }
if (DEBUG) {
pw.println("mOnBatteryTimeBase:");
mOnBatteryTimeBase.dump(pw, " ");
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index f8ae0c1..49c564b 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -132,9 +132,12 @@
// TODO(b/174186358): read extra time component number from configuration
final int customTimeComponentCount = 0;
- final BatteryUsageStats.Builder batteryUsageStatsBuilder =
- new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount)
- .setStatsStartTimestamp(mStats.getStartClockTime());
+ final boolean includePowerModels = (query.getFlags()
+ & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;
+
+ final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder(
+ customPowerComponentCount, customTimeComponentCount, includePowerModels);
+ batteryUsageStatsBuilder.setStatsStartTimestamp(mStats.getStartClockTime());
SparseArray<? extends BatteryStats.Uid> uidStats = mStats.getUidStats();
for (int i = uidStats.size() - 1; i >= 0; i--) {
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 75a9813..a418dff 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -15,8 +15,6 @@
*/
package com.android.internal.os;
-import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
-
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryStats.ControllerActivityCounter;
@@ -75,12 +73,13 @@
}
}
- final long measuredChargeUC = query.shouldForceUsePowerProfileModel() ?
- POWER_DATA_UNAVAILABLE : batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
+ final long measuredChargeUC = batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredChargeUC, query);
final ControllerActivityCounter activityCounter =
batteryStats.getBluetoothControllerActivity();
final long systemDurationMs = calculateDuration(activityCounter);
- final double systemPowerMah = calculatePowerMah(measuredChargeUC, activityCounter);
+ final double systemPowerMah =
+ calculatePowerMah(powerModel, measuredChargeUC, activityCounter);
// Subtract what the apps used, but clamp to 0.
final long systemComponentDurationMs = Math.max(0, systemDurationMs - total.durationMs);
@@ -92,23 +91,22 @@
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH,
systemComponentDurationMs)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
- Math.max(systemPowerMah, total.powerMah))
+ Math.max(systemPowerMah, total.powerMah), powerModel)
.setPowerConsumedByApps(total.powerMah);
}
private void calculateApp(UidBatteryConsumer.Builder app, PowerAndDuration total,
BatteryUsageStatsQuery query) {
-
- final long measuredChargeUC = query.shouldForceUsePowerProfileModel() ?
- POWER_DATA_UNAVAILABLE :
+ final long measuredChargeUC =
app.getBatteryStatsUid().getBluetoothMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredChargeUC, query);
final ControllerActivityCounter activityCounter =
app.getBatteryStatsUid().getBluetoothControllerActivity();
final long durationMs = calculateDuration(activityCounter);
- final double powerMah = calculatePowerMah(measuredChargeUC, activityCounter);
+ final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter);
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH, durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerMah);
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH, powerMah, powerModel);
total.durationMs += durationMs;
total.powerMah += powerMah;
@@ -132,10 +130,12 @@
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.BLUETOOTH, null, 0);
final long measuredChargeUC = batteryStats.getBluetoothMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredChargeUC);
final ControllerActivityCounter activityCounter =
batteryStats.getBluetoothControllerActivity();
final long systemDurationMs = calculateDuration(activityCounter);
- final double systemPowerMah = calculatePowerMah(measuredChargeUC, activityCounter);
+ final double systemPowerMah =
+ calculatePowerMah(powerModel, measuredChargeUC, activityCounter);
// Subtract what the apps used, but clamp to 0.
final double powerMah = Math.max(0, systemPowerMah - total.powerMah);
@@ -165,9 +165,10 @@
PowerAndDuration total) {
final long measuredChargeUC = u.getBluetoothMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(measuredChargeUC);
final ControllerActivityCounter activityCounter = u.getBluetoothControllerActivity();
final long durationMs = calculateDuration(activityCounter);
- final double powerMah = calculatePowerMah(measuredChargeUC, activityCounter);
+ final double powerMah = calculatePowerMah(powerModel, measuredChargeUC, activityCounter);
app.bluetoothRunningTimeMs = durationMs;
app.bluetoothPowerMah = powerMah;
@@ -189,10 +190,12 @@
}
/** Returns bluetooth power usage based on the best data available. */
- private double calculatePowerMah(long measuredChargeUC, ControllerActivityCounter counter) {
- if (measuredChargeUC != POWER_DATA_UNAVAILABLE) {
+ private double calculatePowerMah(@BatteryConsumer.PowerModel int powerModel,
+ long measuredChargeUC, ControllerActivityCounter counter) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
return uCtoMah(measuredChargeUC);
}
+
if (counter == null) {
return 0;
}
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index b15543a..4aafec5 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -91,10 +91,12 @@
private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
BatteryUsageStatsQuery query, Result result) {
- calculatePowerAndDuration(u, BatteryStats.STATS_SINCE_CHARGED,
- query.shouldForceUsePowerProfileModel(), result);
+ final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculatePowerAndDuration(u, powerModel, consumptionUC, BatteryStats.STATS_SINCE_CHARGED,
+ result);
- app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah)
+ app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, result.powerMah, powerModel)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, result.durationMs)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND,
result.durationFgMs)
@@ -114,7 +116,9 @@
}
private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType, Result result) {
- calculatePowerAndDuration(u, statsType, false, result);
+ final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculatePowerAndDuration(u, powerModel, consumptionUC, statsType, result);
app.cpuPowerMah = result.powerMah;
app.cpuTimeMs = result.durationMs;
@@ -122,16 +126,20 @@
app.packageWithHighestDrain = result.packageWithHighestDrain;
}
- private void calculatePowerAndDuration(BatteryStats.Uid u, int statsType,
- boolean forceUsePowerProfileModel, Result result) {
+ private void calculatePowerAndDuration(BatteryStats.Uid u,
+ @BatteryConsumer.PowerModel int powerModel, long consumptionUC, int statsType,
+ Result result) {
long durationMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
final double powerMah;
- final long consumptionUC = u.getCpuMeasuredBatteryConsumptionUC();
- if (forceUsePowerProfileModel || consumptionUC == BatteryStats.POWER_DATA_UNAVAILABLE) {
- powerMah = calculateUidModeledPowerMah(u, statsType);
- } else {
- powerMah = uCtoMah(consumptionUC);
+ switch(powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ powerMah = uCtoMah(consumptionUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ powerMah = calculateUidModeledPowerMah(u, statsType);
+ break;
}
if (DEBUG && (durationMs != 0 || powerMah != 0)) {
diff --git a/core/java/com/android/internal/os/GnssPowerCalculator.java b/core/java/com/android/internal/os/GnssPowerCalculator.java
index 97c4fd8..0e0870d 100644
--- a/core/java/com/android/internal/os/GnssPowerCalculator.java
+++ b/core/java/com/android/internal/os/GnssPowerCalculator.java
@@ -52,28 +52,30 @@
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, query,
- averageGnssPowerMa);
+ final long consumptionUC =
+ app.getBatteryStatsUid().getGnssMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateApp(app, app.getBatteryStatsUid(), powerModel, rawRealtimeUs,
+ averageGnssPowerMa, consumptionUC);
}
}
private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
- long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
- double averageGnssPowerMa) {
+ @BatteryConsumer.PowerModel int powerModel, long rawRealtimeUs,
+ double averageGnssPowerMa, long measuredChargeUC) {
final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);
-
- final long measuredChargeUC = u.getGnssMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable = !query.shouldForceUsePowerProfileModel()
- && measuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE;
-
final double powerMah;
- if (isMeasuredPowerAvailable) {
- powerMah = uCtoMah(measuredChargeUC);
- } else {
- powerMah = computePower(durationMs, averageGnssPowerMa);
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ powerMah = uCtoMah(measuredChargeUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ powerMah = computePower(durationMs, averageGnssPowerMa);
}
+
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_GNSS, durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS, powerMah);
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS, powerMah, powerModel);
}
@Override
@@ -83,24 +85,28 @@
for (int i = sippers.size() - 1; i >= 0; i--) {
final BatterySipper app = sippers.get(i);
if (app.drainType == BatterySipper.DrainType.APP) {
- calculateApp(app, app.uidObj, rawRealtimeUs, statsType, averageGnssPowerMa, false);
+ final long consumptionUC =
+ app.uidObj.getGnssMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateApp(app, app.uidObj, powerModel, rawRealtimeUs, averageGnssPowerMa,
+ consumptionUC);
}
}
}
- protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
- int statsType, double averageGnssPowerMa, boolean shouldForceUsePowerProfileModel) {
+ private void calculateApp(BatterySipper app, BatteryStats.Uid u,
+ @BatteryConsumer.PowerModel int powerModel, long rawRealtimeUs,
+ double averageGnssPowerMa, long measuredChargeUC) {
final long durationMs = computeDuration(u, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED);
- final long measuredChargeUC = u.getGnssMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable = shouldForceUsePowerProfileModel
- && measuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE;
-
final double powerMah;
- if (isMeasuredPowerAvailable) {
- powerMah = uCtoMah(measuredChargeUC);
- } else {
- powerMah = computePower(durationMs, averageGnssPowerMa);
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ powerMah = uCtoMah(measuredChargeUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ powerMah = computePower(durationMs, averageGnssPowerMa);
}
app.gpsTimeMs = durationMs;
diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
index f6ef30c..d441d45 100644
--- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
+++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java
@@ -97,37 +97,41 @@
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
final BatteryStats.Uid uid = app.getBatteryStatsUid();
- calculateApp(app, uid, powerPerPacketMah, total,
- query.shouldForceUsePowerProfileModel());
+ calculateApp(app, uid, powerPerPacketMah, total, query);
}
- calculateRemaining(total, batteryStats, rawRealtimeUs,
- query.shouldForceUsePowerProfileModel());
+ final long consumptionUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateRemaining(total, powerModel, batteryStats, rawRealtimeUs, consumptionUC);
if (total.remainingPowerMah != 0 || total.totalAppPowerMah != 0) {
builder.getOrCreateSystemBatteryConsumerBuilder(
- SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO)
+ SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_MOBILE_RADIO,
total.durationMs)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
- total.remainingPowerMah + total.totalAppPowerMah)
+ total.remainingPowerMah + total.totalAppPowerMah,
+ powerModel)
.setPowerConsumedByApps(total.totalAppPowerMah);
}
}
private void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
double powerPerPacketMah, PowerAndDuration total,
- boolean shouldForceUsePowerProfileModel) {
+ BatteryUsageStatsQuery query) {
final long radioActiveDurationMs = calculateDuration(u, BatteryStats.STATS_SINCE_CHARGED);
total.totalAppDurationMs += radioActiveDurationMs;
- final double powerMah = calculatePower(u, powerPerPacketMah, radioActiveDurationMs,
- shouldForceUsePowerProfileModel);
+ final long consumptionUC = u.getMobileRadioMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ final double powerMah = calculatePower(u, powerModel, powerPerPacketMah,
+ radioActiveDurationMs, consumptionUC);
total.totalAppPowerMah += powerMah;
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_MOBILE_RADIO,
- radioActiveDurationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, powerMah);
+ radioActiveDurationMs)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO, powerMah,
+ powerModel);
}
@Override
@@ -140,12 +144,14 @@
final BatterySipper app = sippers.get(i);
if (app.drainType == BatterySipper.DrainType.APP) {
final BatteryStats.Uid u = app.uidObj;
- calculateApp(app, u, statsType, mobilePowerPerPacket, total, false);
+ calculateApp(app, u, statsType, mobilePowerPerPacket, total);
}
}
BatterySipper radio = new BatterySipper(BatterySipper.DrainType.CELL, null, 0);
- calculateRemaining(total, batteryStats, rawRealtimeUs, false);
+ final long consumptionUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateRemaining(total, powerModel, batteryStats, rawRealtimeUs, consumptionUC);
if (total.remainingPowerMah != 0) {
if (total.signalDurationMs != 0) {
radio.noCoveragePercent =
@@ -162,12 +168,13 @@
}
private void calculateApp(BatterySipper app, BatteryStats.Uid u, int statsType,
- double powerPerPacketMah, PowerAndDuration total,
- boolean shouldForceUsePowerProfileModel) {
+ double powerPerPacketMah, PowerAndDuration total) {
app.mobileActive = calculateDuration(u, statsType);
- app.mobileRadioPowerMah = calculatePower(u, powerPerPacketMah, app.mobileActive,
- shouldForceUsePowerProfileModel);
+ final long consumptionUC = u.getMobileRadioMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ app.mobileRadioPowerMah = calculatePower(u, powerModel, powerPerPacketMah, app.mobileActive,
+ consumptionUC);
total.totalAppDurationMs += app.mobileActive;
// Add cost of mobile traffic.
@@ -193,13 +200,9 @@
return u.getMobileRadioActiveTime(statsType) / 1000;
}
- private double calculatePower(BatteryStats.Uid u, double powerPerPacketMah,
- long radioActiveDurationMs, boolean shouldForceUsePowerProfileModel) {
-
- final long measuredChargeUC = u.getMobileRadioMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable = !shouldForceUsePowerProfileModel
- && measuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE;
- if (isMeasuredPowerAvailable) {
+ private double calculatePower(BatteryStats.Uid u, @BatteryConsumer.PowerModel int powerModel,
+ double powerPerPacketMah, long radioActiveDurationMs, long measuredChargeUC) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
return uCtoMah(measuredChargeUC);
}
@@ -220,23 +223,20 @@
}
}
- private void calculateRemaining(MobileRadioPowerCalculator.PowerAndDuration total,
- BatteryStats batteryStats, long rawRealtimeUs,
- boolean shouldForceUsePowerProfileModel) {
+ private void calculateRemaining(PowerAndDuration total,
+ @BatteryConsumer.PowerModel int powerModel, BatteryStats batteryStats,
+ long rawRealtimeUs, long consumptionUC) {
long signalTimeMs = 0;
double powerMah = 0;
- final long measuredChargeUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable = !shouldForceUsePowerProfileModel
- && measuredChargeUC != BatteryStats.POWER_DATA_UNAVAILABLE;
- if (isMeasuredPowerAvailable) {
- powerMah = uCtoMah(measuredChargeUC);
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
+ powerMah = uCtoMah(consumptionUC);
}
for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) {
long strengthTimeMs = batteryStats.getPhoneSignalStrengthTime(i, rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED) / 1000;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
final double p = calcIdlePowerAtSignalStrengthMah(strengthTimeMs, i);
if (DEBUG && p != 0) {
Log.d(TAG, "Cell strength #" + i + ": time=" + strengthTimeMs + " power="
@@ -256,7 +256,7 @@
BatteryStats.STATS_SINCE_CHARGED) / 1000;
long remainingActiveTimeMs = radioActiveTimeMs - total.totalAppDurationMs;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
final double p = calcScanTimePowerMah(scanningTimeMs);
if (DEBUG && p != 0) {
Log.d(TAG, "Cell radio scanning: time=" + scanningTimeMs + " power=" + formatCharge(
diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java
index 72385e2..d139b4f 100644
--- a/core/java/com/android/internal/os/PowerCalculator.java
+++ b/core/java/com/android/internal/os/PowerCalculator.java
@@ -15,6 +15,8 @@
*/
package com.android.internal.os;
+import android.annotation.NonNull;
+import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
@@ -114,20 +116,49 @@
public void reset() {
}
+ protected static @BatteryConsumer.PowerModel int getPowerModel(
+ long measuredEnergyUC, @NonNull BatteryUsageStatsQuery query) {
+ if (measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE
+ && !query.shouldForceUsePowerProfileModel()) {
+ return BatteryConsumer.POWER_MODEL_MEASURED_ENERGY;
+ }
+ return BatteryConsumer.POWER_MODEL_POWER_PROFILE;
+ }
+
+ protected static @BatteryConsumer.PowerModel int getPowerModel(long measuredEnergyUC) {
+ return measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE
+ ? BatteryConsumer.POWER_MODEL_MEASURED_ENERGY
+ : BatteryConsumer.POWER_MODEL_POWER_PROFILE;
+ }
+
/**
* Returns either the measured energy converted to mAh or a usage-based estimate.
*/
- protected static double getMeasuredOrEstimatedPower(long measuredEnergyUC,
- UsageBasedPowerEstimator powerEstimator, long durationMs,
- boolean forceUsePowerProfileModel) {
- if (measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE
- && !forceUsePowerProfileModel) {
- return uCtoMah(measuredEnergyUC);
+ protected static double getMeasuredOrEstimatedPower(@BatteryConsumer.PowerModel int powerModel,
+ long measuredEnergyUC, UsageBasedPowerEstimator powerEstimator, long durationMs) {
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ return uCtoMah(measuredEnergyUC);
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ return powerEstimator.calculatePower(durationMs);
}
- return powerEstimator.calculatePower(durationMs);
}
/**
+ * Returns either the measured energy converted to mAh or a usage-based estimate.
+ */
+ protected static double getMeasuredOrEstimatedPower(
+ long measuredEnergyUC, UsageBasedPowerEstimator powerEstimator, long durationMs) {
+ if (measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE) {
+ return uCtoMah(measuredEnergyUC);
+ } else {
+ return powerEstimator.calculatePower(durationMs);
+ }
+ }
+
+
+ /**
* Converts charge in mAh to string.
*/
public static String formatCharge(double power) {
diff --git a/core/java/com/android/internal/os/ScreenPowerCalculator.java b/core/java/com/android/internal/os/ScreenPowerCalculator.java
index ad57444..0267def 100644
--- a/core/java/com/android/internal/os/ScreenPowerCalculator.java
+++ b/core/java/com/android/internal/os/ScreenPowerCalculator.java
@@ -62,9 +62,10 @@
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
final PowerAndDuration totalPowerAndDuration = new PowerAndDuration();
- final boolean useEnergyData = calculateTotalDurationAndPower(totalPowerAndDuration,
- batteryStats, rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED,
- query.shouldForceUsePowerProfileModel());
+ final long consumptionUC = batteryStats.getScreenOnMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateTotalDurationAndPower(totalPowerAndDuration, powerModel, batteryStats,
+ rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED, consumptionUC);
double totalAppPower = 0;
@@ -73,29 +74,32 @@
// but the method depends on the data source.
final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
builder.getUidBatteryConsumerBuilders();
- if (useEnergyData) {
- final PowerAndDuration appPowerAndDuration = new PowerAndDuration();
- for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
- final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateAppUsingMeasuredEnergy(appPowerAndDuration, app.getBatteryStatsUid(),
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ final PowerAndDuration appPowerAndDuration = new PowerAndDuration();
+ for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
+ final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
+ calculateAppUsingMeasuredEnergy(appPowerAndDuration, app.getBatteryStatsUid(),
+ rawRealtimeUs);
+ app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN,
+ appPowerAndDuration.durationMs)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN,
+ appPowerAndDuration.powerMah, powerModel);
+ totalAppPower += appPowerAndDuration.powerMah;
+ }
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ smearScreenBatteryDrain(uidBatteryConsumerBuilders, totalPowerAndDuration,
rawRealtimeUs);
- app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN,
- appPowerAndDuration.durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN,
- appPowerAndDuration.powerMah);
- totalAppPower += appPowerAndDuration.powerMah;
- }
- } else {
- smearScreenBatteryDrain(uidBatteryConsumerBuilders, totalPowerAndDuration,
- rawRealtimeUs);
- totalAppPower = totalPowerAndDuration.powerMah;
+ totalAppPower = totalPowerAndDuration.powerMah;
}
builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_SCREEN)
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE,
totalPowerAndDuration.durationMs)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE,
- Math.max(totalPowerAndDuration.powerMah, totalAppPower))
+ Math.max(totalPowerAndDuration.powerMah, totalAppPower), powerModel)
.setPowerConsumedByApps(totalAppPower);
}
@@ -106,8 +110,10 @@
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
final PowerAndDuration totalPowerAndDuration = new PowerAndDuration();
- final boolean useEnergyData = calculateTotalDurationAndPower(totalPowerAndDuration,
- batteryStats, rawRealtimeUs, statsType, false);
+ final long consumptionUC = batteryStats.getScreenOnMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateTotalDurationAndPower(totalPowerAndDuration, powerModel, batteryStats,
+ rawRealtimeUs, statsType, consumptionUC);
if (totalPowerAndDuration.powerMah == 0) {
return;
}
@@ -121,41 +127,42 @@
// Now deal with each app's BatterySipper. The results are stored in the screenPowerMah
// field, which is considered smeared, but the method depends on the data source.
- if (useEnergyData) {
- final PowerAndDuration appPowerAndDuration = new PowerAndDuration();
- for (int i = sippers.size() - 1; i >= 0; i--) {
- final BatterySipper app = sippers.get(i);
- if (app.drainType == BatterySipper.DrainType.APP) {
- calculateAppUsingMeasuredEnergy(appPowerAndDuration, app.uidObj, rawRealtimeUs);
- app.screenPowerMah = appPowerAndDuration.powerMah;
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ final PowerAndDuration appPowerAndDuration = new PowerAndDuration();
+ for (int i = sippers.size() - 1; i >= 0; i--) {
+ final BatterySipper app = sippers.get(i);
+ if (app.drainType == BatterySipper.DrainType.APP) {
+ calculateAppUsingMeasuredEnergy(appPowerAndDuration, app.uidObj,
+ rawRealtimeUs);
+ app.screenPowerMah = appPowerAndDuration.powerMah;
+ }
}
- }
- } else {
- smearScreenBatterySipper(sippers, bs, rawRealtimeUs);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ smearScreenBatterySipper(sippers, bs, rawRealtimeUs);
}
}
/**
- * Stores duration and power information in totalPowerAndDuration and returns true if measured
- * energy data is available and should be used by the model.
+ * Stores duration and power information in totalPowerAndDuration.
*/
- private boolean calculateTotalDurationAndPower(PowerAndDuration totalPowerAndDuration,
- BatteryStats batteryStats, long rawRealtimeUs, int statsType,
- boolean forceUsePowerProfileModel) {
+ private void calculateTotalDurationAndPower(PowerAndDuration totalPowerAndDuration,
+ @BatteryConsumer.PowerModel int powerModel, BatteryStats batteryStats,
+ long rawRealtimeUs, int statsType, long consumptionUC) {
totalPowerAndDuration.durationMs = calculateDuration(batteryStats, rawRealtimeUs,
statsType);
- if (!forceUsePowerProfileModel) {
- final long chargeUC = batteryStats.getScreenOnMeasuredBatteryConsumptionUC();
- if (chargeUC != BatteryStats.POWER_DATA_UNAVAILABLE) {
- totalPowerAndDuration.powerMah = uCtoMah(chargeUC);
- return true;
- }
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ totalPowerAndDuration.powerMah = uCtoMah(consumptionUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ totalPowerAndDuration.powerMah = calculateTotalPowerFromBrightness(batteryStats,
+ rawRealtimeUs, statsType, totalPowerAndDuration.durationMs);
}
-
- totalPowerAndDuration.powerMah = calculateTotalPowerFromBrightness(batteryStats,
- rawRealtimeUs, statsType, totalPowerAndDuration.durationMs);
- return false;
}
private void calculateAppUsingMeasuredEnergy(PowerAndDuration appPowerAndDuration,
@@ -245,7 +252,8 @@
final long durationMs = activityTimeArray.get(app.getUid(), 0);
final double powerMah = totalScreenPowerMah * durationMs / totalActivityTimeMs;
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN, durationMs)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, powerMah);
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN, powerMah,
+ BatteryConsumer.POWER_MODEL_POWER_PROFILE);
}
}
}
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index d95506b..11219ec 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -15,8 +15,6 @@
*/
package com.android.internal.os;
-import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
-
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
@@ -92,10 +90,12 @@
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), rawRealtimeUs,
- BatteryStats.STATS_SINCE_CHARGED,
- batteryStats.hasWifiActivityReporting(),
- query.shouldForceUsePowerProfileModel());
+ final long consumptionUC =
+ app.getBatteryStatsUid().getWifiMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateApp(powerDurationAndTraffic, app.getBatteryStatsUid(), powerModel,
+ rawRealtimeUs, BatteryStats.STATS_SINCE_CHARGED,
+ batteryStats.hasWifiActivityReporting(), consumptionUC);
totalAppDurationMs += powerDurationAndTraffic.durationMs;
totalAppPowerMah += powerDurationAndTraffic.powerMah;
@@ -103,7 +103,7 @@
app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
powerDurationAndTraffic.durationMs);
app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI,
- powerDurationAndTraffic.powerMah);
+ powerDurationAndTraffic.powerMah, powerModel);
if (app.getUid() == Process.WIFI_UID) {
systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
@@ -111,17 +111,17 @@
}
}
- calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs,
- BatteryStats.STATS_SINCE_CHARGED,
- batteryStats.hasWifiActivityReporting(),
- query.shouldForceUsePowerProfileModel(),
- totalAppDurationMs, totalAppPowerMah);
+ final long consumptionUC = batteryStats.getWifiMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC, query);
+ calculateRemaining(powerDurationAndTraffic, powerModel, batteryStats, rawRealtimeUs,
+ BatteryStats.STATS_SINCE_CHARGED, batteryStats.hasWifiActivityReporting(),
+ totalAppDurationMs, totalAppPowerMah, consumptionUC);
systemBatteryConsumerBuilder
.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI,
powerDurationAndTraffic.durationMs)
.setConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI,
- totalAppPowerMah + powerDurationAndTraffic.powerMah)
+ totalAppPowerMah + powerDurationAndTraffic.powerMah, powerModel)
.setPowerConsumedByApps(totalAppPowerMah);
}
@@ -144,8 +144,11 @@
for (int i = sippers.size() - 1; i >= 0; i--) {
final BatterySipper app = sippers.get(i);
if (app.drainType == BatterySipper.DrainType.APP) {
- calculateApp(powerDurationAndTraffic, app.uidObj, rawRealtimeUs, statsType,
- batteryStats.hasWifiActivityReporting(), /* force use power model*/ false);
+ final long consumptionUC =
+ app.uidObj.getWifiMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateApp(powerDurationAndTraffic, app.uidObj, powerModel, rawRealtimeUs,
+ statsType, batteryStats.hasWifiActivityReporting(), consumptionUC);
totalAppDurationMs += powerDurationAndTraffic.durationMs;
totalAppPowerMah += powerDurationAndTraffic.powerMah;
@@ -164,9 +167,11 @@
}
}
- calculateRemaining(powerDurationAndTraffic, batteryStats, rawRealtimeUs, statsType,
- batteryStats.hasWifiActivityReporting(), /* force use power model*/ false,
- totalAppDurationMs, totalAppPowerMah);
+ final long consumptionUC = batteryStats.getWifiMeasuredBatteryConsumptionUC();
+ final int powerModel = getPowerModel(consumptionUC);
+ calculateRemaining(powerDurationAndTraffic, powerModel, batteryStats, rawRealtimeUs,
+ statsType, batteryStats.hasWifiActivityReporting(), totalAppDurationMs,
+ totalAppPowerMah, consumptionUC);
bs.wifiRunningTimeMs += powerDurationAndTraffic.durationMs;
bs.wifiPowerMah += powerDurationAndTraffic.powerMah;
@@ -176,9 +181,10 @@
}
}
- private void calculateApp(PowerDurationAndTraffic powerDurationAndTraffic, BatteryStats.Uid u,
- long rawRealtimeUs, int statsType,
- boolean hasWifiActivityReporting, boolean shouldForceUsePowerProfileModel) {
+ private void calculateApp(PowerDurationAndTraffic powerDurationAndTraffic,
+ BatteryStats.Uid u, @BatteryConsumer.PowerModel int powerModel,
+ long rawRealtimeUs, int statsType, boolean hasWifiActivityReporting,
+ long consumptionUC) {
powerDurationAndTraffic.wifiRxPackets = u.getNetworkActivityPackets(
BatteryStats.NETWORK_WIFI_RX_DATA,
@@ -193,11 +199,8 @@
BatteryStats.NETWORK_WIFI_TX_DATA,
statsType);
- final long measuredChargeUC = u.getWifiMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable
- = !shouldForceUsePowerProfileModel && measuredChargeUC != POWER_DATA_UNAVAILABLE;
- if (isMeasuredPowerAvailable) {
- powerDurationAndTraffic.powerMah = uCtoMah(measuredChargeUC);
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
+ powerDurationAndTraffic.powerMah = uCtoMah(consumptionUC);
}
if (hasWifiActivityReporting && mHasWifiPowerController) {
@@ -208,7 +211,7 @@
final long rxTime = counter.getRxTimeCounter().getCountLocked(statsType);
powerDurationAndTraffic.durationMs = idleTime + rxTime + txTime;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
powerDurationAndTraffic.powerMah
= calcPowerFromControllerDataMah(rxTime, txTime, idleTime);
}
@@ -223,7 +226,7 @@
final long wifiRunningTime = u.getWifiRunningTime(rawRealtimeUs, statsType) / 1000;
powerDurationAndTraffic.durationMs = wifiRunningTime;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
final long wifiScanTimeMs = u.getWifiScanTime(rawRealtimeUs, statsType) / 1000;
long batchTimeMs = 0;
for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
@@ -243,19 +246,17 @@
}
private void calculateRemaining(PowerDurationAndTraffic powerDurationAndTraffic,
- BatteryStats stats, long rawRealtimeUs, int statsType,
- boolean hasWifiActivityReporting, boolean shouldForceUsePowerProfileModel,
- long totalAppDurationMs, double totalAppPowerMah) {
+ @BatteryConsumer.PowerModel int powerModel, BatteryStats stats, long rawRealtimeUs,
+ int statsType, boolean hasWifiActivityReporting, long totalAppDurationMs,
+ double totalAppPowerMah, long consumptionUC) {
long totalDurationMs;
double totalPowerMah = 0;
- final long measuredChargeUC = stats.getWifiMeasuredBatteryConsumptionUC();
- final boolean isMeasuredPowerAvailable
- = !shouldForceUsePowerProfileModel && measuredChargeUC != POWER_DATA_UNAVAILABLE;
- if (isMeasuredPowerAvailable) {
- totalPowerMah = uCtoMah(measuredChargeUC);
+ if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) {
+ totalPowerMah = uCtoMah(consumptionUC);
}
+
if (hasWifiActivityReporting && mHasWifiPowerController) {
final BatteryStats.ControllerActivityCounter counter =
stats.getWifiControllerActivity();
@@ -266,7 +267,7 @@
totalDurationMs = idleTimeMs + rxTimeMs + txTimeMs;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
totalPowerMah = counter.getPowerCounter().getCountLocked(statsType)
/ (double) (1000 * 60 * 60);
if (totalPowerMah == 0) {
@@ -276,7 +277,7 @@
}
} else {
totalDurationMs = stats.getGlobalWifiRunningTime(rawRealtimeUs, statsType) / 1000;
- if (!isMeasuredPowerAvailable) {
+ if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
totalPowerMah = calcGlobalPowerWithoutControllerDataMah(totalDurationMs);
}
}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 6f9a381..f0a7a36 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -26,6 +26,7 @@
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"
+#include <android/media/AudioVibratorInfo.h>
#include <audiomanager/AudioManager.h>
#include <media/AudioPolicy.h>
#include <media/AudioSystem.h>
@@ -176,7 +177,12 @@
jmethodID postRoutingUpdatedFromNative;
} gAudioPolicyEventHandlerMethods;
-static struct { jmethodID add; } gListMethods;
+jclass gListClass;
+static struct {
+ jmethodID add;
+ jmethodID get;
+ jmethodID size;
+} gListMethods;
static jclass gAudioDescriptorClass;
static jmethodID gAudiODescriptorCstor;
@@ -195,6 +201,13 @@
jclass gAudioProfileClass;
jmethodID gAudioProfileCstor;
+jclass gVibratorClass;
+static struct {
+ jmethodID getId;
+ jmethodID getResonantFrequency;
+ jmethodID getQFactor;
+} gVibratorMethods;
+
static Mutex gLock;
enum AudioError {
@@ -2627,6 +2640,29 @@
return jStatus;
}
+static jint android_media_AudioSystem_setVibratorInfos(JNIEnv *env, jobject thiz,
+ jobject jVibrators) {
+ if (!env->IsInstanceOf(jVibrators, gListClass)) {
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+ const jint size = env->CallIntMethod(jVibrators, gListMethods.size);
+ std::vector<media::AudioVibratorInfo> vibratorInfos;
+ for (jint i = 0; i < size; ++i) {
+ ScopedLocalRef<jobject> jVibrator(env,
+ env->CallObjectMethod(jVibrators, gListMethods.get, i));
+ if (!env->IsInstanceOf(jVibrator.get(), gVibratorClass)) {
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+ media::AudioVibratorInfo vibratorInfo;
+ vibratorInfo.id = env->CallIntMethod(jVibrator.get(), gVibratorMethods.getId);
+ vibratorInfo.resonantFrequency =
+ env->CallFloatMethod(jVibrator.get(), gVibratorMethods.getResonantFrequency);
+ vibratorInfo.qFactor = env->CallFloatMethod(jVibrator.get(), gVibratorMethods.getQFactor);
+ vibratorInfos.push_back(vibratorInfo);
+ }
+ return (jint)check_AudioSystem_Command(AudioSystem::setVibratorInfos(vibratorInfos));
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] =
@@ -2757,7 +2793,9 @@
(void *)android_media_AudioSystem_setUserIdDeviceAffinities},
{"removeUserIdDeviceAffinities", "(I)I",
(void *)android_media_AudioSystem_removeUserIdDeviceAffinities},
- {"setCurrentImeUid", "(I)I", (void *)android_media_AudioSystem_setCurrentImeUid}};
+ {"setCurrentImeUid", "(I)I", (void *)android_media_AudioSystem_setCurrentImeUid},
+ {"setVibratorInfos", "(Ljava/util/List;)I",
+ (void *)android_media_AudioSystem_setVibratorInfos}};
static const JNINativeMethod gEventHandlerMethods[] = {
{"native_setup",
@@ -2959,7 +2997,10 @@
android::GetMethodIDOrDie(env, gClsAudioRecordRoutingProxy, "native_release", "()V");
jclass listClass = FindClassOrDie(env, "java/util/List");
+ gListClass = MakeGlobalRefOrDie(env, listClass);
gListMethods.add = GetMethodIDOrDie(env, listClass, "add", "(Ljava/lang/Object;)Z");
+ gListMethods.get = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;");
+ gListMethods.size = GetMethodIDOrDie(env, listClass, "size", "()I");
jclass audioProfileClass = FindClassOrDie(env, "android/media/AudioProfile");
gAudioProfileClass = MakeGlobalRefOrDie(env, audioProfileClass);
@@ -2969,6 +3010,13 @@
gAudioDescriptorClass = MakeGlobalRefOrDie(env, audioDescriptorClass);
gAudiODescriptorCstor = GetMethodIDOrDie(env, audioDescriptorClass, "<init>", "(II[B)V");
+ jclass vibratorClass = FindClassOrDie(env, "android/os/Vibrator");
+ gVibratorClass = MakeGlobalRefOrDie(env, vibratorClass);
+ gVibratorMethods.getId = GetMethodIDOrDie(env, vibratorClass, "getId", "()I");
+ gVibratorMethods.getResonantFrequency =
+ GetMethodIDOrDie(env, vibratorClass, "getResonantFrequency", "()F");
+ gVibratorMethods.getQFactor = GetMethodIDOrDie(env, vibratorClass, "getQFactor", "()F");
+
AudioSystem::addErrorCallback(android_media_AudioSystem_error_callback);
RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3ebb10e..c144451 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2758,8 +2758,12 @@
<permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"
android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier" />
- <!-- Allows an application to start foreground services from background, can only be granted to
- privileged apps or app that is SMS/EMERGENCY/SYSTEM GALLERY roles. -->
+ <!-- Allows an application to start foreground services from the background at any time.
+ <em>This permission is not for use by third-party applications</em>,
+ with the only exception being if the app is the default SMS app.
+ Otherwise, it's only usable by privileged apps, app verifier app, and apps with
+ any of the EMERGENCY or SYSTEM GALLERY roles.
+ -->
<permission android:name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"
android:protectionLevel="signature|privileged|vendorPrivileged|oem|verifier|role"/>
@@ -5580,7 +5584,6 @@
@hide <p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"
android:protectionLevel="signature|privileged" />
- <uses-permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"/>
<!-- @SystemApi Allows an app to override compat change config on release builds.
Only ChangeIds that are annotated as @Overridable can be overridden on release builds.
@hide -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9e159f9..6cccdb5 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3030,12 +3030,12 @@
<!-- ===============================================================
Resources added in version S of the platform
- NOTE: add <public> elements within a <public-group> like so:
+ NOTE: add <public> elements within a <staging-public-group> like so:
- <public-group type="attr" first-id="0x01010531">
+ <staging-public-group type="attr" first-id="0x01010531">
<public name="exampleAttr1" />
<public name="exampleAttr2" />
- </public-group>
+ </staging-public-group>
To add a new public-group block, choose an id value that is 1 greater
than the last of that item above. For example, the last "attr" id
@@ -3044,7 +3044,7 @@
=============================================================== -->
<eat-comment />
- <public-group type="attr" first-id="0x01010617">
+ <staging-public-group type="attr" first-id="0x01010617">
<public name="rollbackDataPolicy" />
<public name="allowClickWhenDisabled" />
<public name="windowLayoutAffinity" />
@@ -3099,13 +3099,13 @@
<!-- @hide @SystemApi -->
<public name="throttleDurationMillis" />
<public name="showInInputMethodPicker" />
- </public-group>
+ </staging-public-group>
- <public-group type="drawable" first-id="0x010800b5">
+ <staging-public-group type="drawable" first-id="0x010800b5">
<!-- drawable definitions go here -->
- </public-group>
+ </staging-public-group>
- <public-group type="color" first-id="0x0106001d">
+ <staging-public-group type="color" first-id="0x0106001d">
<!-- color definitions go here -->
<!-- Material design dynamic system palette:-->
@@ -3171,26 +3171,26 @@
<public name="system_accent3_800" />
<public name="system_accent3_900" />
<public name="system_accent3_1000" />
- </public-group>
+ </staging-public-group>
- <public-group type="dimen" first-id="0x01050008">
+ <staging-public-group type="dimen" first-id="0x01050008">
<!-- dimension definitions go here -->
<!-- System-provided dimensions for app widgets. -->
<public name="system_app_widget_background_radius" />
<public name="system_app_widget_inner_radius" />
<public name="system_app_widget_internal_padding" />
- </public-group>
+ </staging-public-group>
- <public-group type="bool" first-id="0x01110007">
+ <staging-public-group type="bool" first-id="0x01110007">
<!-- boolean definitions go here -->
- </public-group>
+ </staging-public-group>
- <public-group type="style" first-id="0x010302e5">
+ <staging-public-group type="style" first-id="0x010302e5">
<!-- style definitions go here -->
- </public-group>
+ </staging-public-group>
- <public-group type="string" first-id="0x01040028">
+ <staging-public-group type="string" first-id="0x01040028">
<!-- @hide @SystemApi @TestApi -->
<public name="config_systemAutomotiveCluster" />
<!-- @hide @SystemApi @TestApi -->
@@ -3211,11 +3211,11 @@
<public name="config_systemWellbeing" />
<!-- @hide @SystemApi -->
<public name="config_systemTelevisionNotificationHandler" />
- </public-group>
+ </staging-public-group>
- <public-group type="id" first-id="0x01020055">
+ <staging-public-group type="id" first-id="0x01020055">
<!-- id definitions go here -->
- </public-group>
+ </staging-public-group>
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetrics.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetrics.java
index dbe5773..0f3bb1d 100644
--- a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetrics.java
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetrics.java
@@ -16,261 +16,99 @@
package com.android.frameworks.core.batterystatsloadtests;
-import android.os.Process;
-
-import com.android.internal.os.BatterySipper;
-import com.android.internal.os.BatteryStatsHelper;
+import android.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
+import android.os.UidBatteryConsumer;
+import android.util.DebugUtils;
+import android.util.Range;
import java.util.ArrayList;
import java.util.List;
public class PowerMetrics {
- private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar";
- private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media";
- private static final String PACKAGE_SYSTEMUI = "com.android.systemui";
- private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER,
- PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI};
enum MetricKind {
POWER,
DURATION,
}
- public static final String METRIC_APP_POWER = "appPower";
- public static final String METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL = "appPowerExcludeSystem";
- public static final String METRIC_APP_POWER_EXCLUDE_SMEARED = "appPowerExcludeSmeared";
- public static final String METRIC_SCREEN_POWER = "screenPower";
- public static final String METRIC_WIFI_POWER = "wifiPower";
- public static final String METRIC_SYSTEM_SERVICE_CPU_POWER = "systemService";
- public static final String METRIC_OTHER_POWER = "otherPower";
- public static final String METRIC_CPU_POWER = "cpuPower";
- public static final String METRIC_RAM_POWER = "ramPower";
- public static final String METRIC_WAKELOCK_POWER = "wakelockPower";
- public static final String METRIC_MOBILE_RADIO_POWER = "mobileRadioPower";
- public static final String METRIC_BLUETOOTH_POWER = "bluetoothPower";
- public static final String METRIC_GPS_POWER = "gpsPower";
- public static final String METRIC_CAMERA_POWER = "cameraPower";
- public static final String METRIC_FLASHLIGHT_POWER = "flashlightPower";
- public static final String METRIC_SENSORS_POWER = "sensorsPower";
- public static final String METRIC_AUDIO_POWER = "audioPower";
- public static final String METRIC_VIDEO_POWER = "videoPower";
- public static final String METRIC_CPU_TIME = "cpuTime";
- public static final String METRIC_CPU_FOREGROUND_TIME = "cpuForegroundTime";
- public static final String METRIC_WAKELOCK_TIME = "wakelockTime";
- public static final String METRIC_WIFI_RUNNING_TIME = "wifiRunningTime";
- public static final String METRIC_BLUETOOTH_RUNNING_TIME = "bluetoothRunningTime";
- public static final String METRIC_GPS_TIME = "gpsTime";
- public static final String METRIC_CAMERA_TIME = "cameraTime";
- public static final String METRIC_FLASHLIGHT_TIME = "flashlightTime";
- public static final String METRIC_AUDIO_TIME = "audioTime";
- public static final String METRIC_VIDEO_TIME = "videoTime";
-
public static class Metric {
- public String metricType;
+ public String metricName;
public MetricKind metricKind;
- public String title;
+ public String statusKeyPrefix;
public double value;
public double total;
}
- private final double mMinDrainedPower;
- private final double mMaxDrainedPower;
+ private final double mDrainedPower;
private List<Metric> mMetrics = new ArrayList<>();
- public PowerMetrics(BatteryStatsHelper batteryStatsHelper, int uid) {
- mMinDrainedPower = batteryStatsHelper.getMinDrainedPower();
- mMaxDrainedPower = batteryStatsHelper.getMaxDrainedPower();
+ public PowerMetrics(BatteryUsageStats batteryUsageStats, int uid) {
+ final Range<Double> dischargedPowerRange = batteryUsageStats.getDischargedPowerRange();
+ mDrainedPower = (dischargedPowerRange.getLower() + dischargedPowerRange.getUpper()) / 2;
+ double[] totalPowerPerComponentMah = new double[BatteryConsumer.POWER_COMPONENT_COUNT];
+ long[] totalDurationPerComponentMs = new long[BatteryConsumer.POWER_COMPONENT_COUNT];
- List<BatterySipper> usageList = batteryStatsHelper.getUsageList();
-
- double totalPowerMah = 0;
- double totalSmearedPowerMah = 0;
- double totalPowerExcludeSystemMah = 0;
- double totalScreenPower = 0;
- double totalProportionalSmearMah = 0;
- double totalCpuPowerMah = 0;
- double totalSystemServiceCpuPowerMah = 0;
- double totalUsagePowerMah = 0;
- double totalWakeLockPowerMah = 0;
- double totalMobileRadioPowerMah = 0;
- double totalWifiPowerMah = 0;
- double totalBluetoothPowerMah = 0;
- double totalGpsPowerMah = 0;
- double totalCameraPowerMah = 0;
- double totalFlashlightPowerMah = 0;
- double totalSensorPowerMah = 0;
- double totalAudioPowerMah = 0;
- double totalVideoPowerMah = 0;
-
- long totalCpuTimeMs = 0;
- long totalCpuFgTimeMs = 0;
- long totalWakeLockTimeMs = 0;
- long totalWifiRunningTimeMs = 0;
- long totalBluetoothRunningTimeMs = 0;
- long totalGpsTimeMs = 0;
- long totalCameraTimeMs = 0;
- long totalFlashlightTimeMs = 0;
- long totalAudioTimeMs = 0;
- long totalVideoTimeMs = 0;
-
- BatterySipper uidSipper = null;
- for (BatterySipper sipper : usageList) {
- if (sipper.drainType == BatterySipper.DrainType.SCREEN) {
- totalScreenPower = sipper.sumPower();
+ UidBatteryConsumer selectedBatteryConsumer = null;
+ for (UidBatteryConsumer uidBatteryConsumer : batteryUsageStats.getUidBatteryConsumers()) {
+ if (uidBatteryConsumer.getUid() == uid) {
+ selectedBatteryConsumer = uidBatteryConsumer;
}
- if (isHiddenDrainType(sipper.drainType)) {
- continue;
+ for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT;
+ component++) {
+ totalPowerPerComponentMah[component] += uidBatteryConsumer.getConsumedPower(
+ component);
}
- if (sipper.drainType == BatterySipper.DrainType.APP && sipper.getUid() == uid) {
- uidSipper = sipper;
+ for (int component = 0; component < BatteryConsumer.TIME_COMPONENT_COUNT; component++) {
+ totalDurationPerComponentMs[component] +=
+ uidBatteryConsumer.getUsageDurationMillis(component);
}
-
- totalPowerMah += sipper.sumPower();
- totalSmearedPowerMah += sipper.totalSmearedPowerMah;
- totalProportionalSmearMah += sipper.proportionalSmearMah;
-
- if (!isSystemSipper(sipper)) {
- totalPowerExcludeSystemMah += sipper.totalSmearedPowerMah;
- }
-
- totalCpuPowerMah += sipper.cpuPowerMah;
- totalSystemServiceCpuPowerMah += sipper.systemServiceCpuPowerMah;
- totalUsagePowerMah += sipper.usagePowerMah;
- totalWakeLockPowerMah += sipper.wakeLockPowerMah;
- totalMobileRadioPowerMah += sipper.mobileRadioPowerMah;
- totalWifiPowerMah += sipper.wifiPowerMah;
- totalBluetoothPowerMah += sipper.bluetoothPowerMah;
- totalGpsPowerMah += sipper.gpsPowerMah;
- totalCameraPowerMah += sipper.cameraPowerMah;
- totalFlashlightPowerMah += sipper.flashlightPowerMah;
- totalSensorPowerMah += sipper.sensorPowerMah;
- totalAudioPowerMah += sipper.audioPowerMah;
- totalVideoPowerMah += sipper.videoPowerMah;
-
- totalCpuTimeMs += sipper.cpuTimeMs;
- totalCpuFgTimeMs += sipper.cpuFgTimeMs;
- totalWakeLockTimeMs += sipper.wakeLockTimeMs;
- totalWifiRunningTimeMs += sipper.wifiRunningTimeMs;
- totalBluetoothRunningTimeMs += sipper.bluetoothRunningTimeMs;
- totalGpsTimeMs += sipper.gpsTimeMs;
- totalCameraTimeMs += sipper.cameraTimeMs;
- totalFlashlightTimeMs += sipper.flashlightTimeMs;
- totalAudioTimeMs += sipper.audioTimeMs;
- totalVideoTimeMs += sipper.videoTimeMs;
}
- if (uidSipper == null) {
+ if (selectedBatteryConsumer == null) {
return;
}
- addMetric(METRIC_APP_POWER, MetricKind.POWER, "Total power",
- uidSipper.totalSmearedPowerMah, totalSmearedPowerMah);
- addMetric(METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL, MetricKind.POWER,
- "Total power excluding system",
- uidSipper.totalSmearedPowerMah, totalPowerExcludeSystemMah);
- addMetric(METRIC_SCREEN_POWER, MetricKind.POWER, "Screen, smeared",
- uidSipper.screenPowerMah, totalScreenPower);
- addMetric(METRIC_OTHER_POWER, MetricKind.POWER, "Other, smeared",
- uidSipper.proportionalSmearMah, totalProportionalSmearMah);
- addMetric(METRIC_APP_POWER_EXCLUDE_SMEARED, MetricKind.POWER, "Excluding smeared",
- uidSipper.totalPowerMah, totalPowerMah);
- addMetric(METRIC_CPU_POWER, MetricKind.POWER, "CPU",
- uidSipper.cpuPowerMah, totalCpuPowerMah);
- addMetric(METRIC_SYSTEM_SERVICE_CPU_POWER, MetricKind.POWER, "System services",
- uidSipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah);
- addMetric(METRIC_RAM_POWER, MetricKind.POWER, "RAM",
- uidSipper.usagePowerMah, totalUsagePowerMah);
- addMetric(METRIC_WAKELOCK_POWER, MetricKind.POWER, "Wake lock",
- uidSipper.wakeLockPowerMah, totalWakeLockPowerMah);
- addMetric(METRIC_MOBILE_RADIO_POWER, MetricKind.POWER, "Mobile radio",
- uidSipper.mobileRadioPowerMah, totalMobileRadioPowerMah);
- addMetric(METRIC_WIFI_POWER, MetricKind.POWER, "WiFi",
- uidSipper.wifiPowerMah, totalWifiPowerMah);
- addMetric(METRIC_BLUETOOTH_POWER, MetricKind.POWER, "Bluetooth",
- uidSipper.bluetoothPowerMah, totalBluetoothPowerMah);
- addMetric(METRIC_GPS_POWER, MetricKind.POWER, "GPS",
- uidSipper.gpsPowerMah, totalGpsPowerMah);
- addMetric(METRIC_CAMERA_POWER, MetricKind.POWER, "Camera",
- uidSipper.cameraPowerMah, totalCameraPowerMah);
- addMetric(METRIC_FLASHLIGHT_POWER, MetricKind.POWER, "Flashlight",
- uidSipper.flashlightPowerMah, totalFlashlightPowerMah);
- addMetric(METRIC_SENSORS_POWER, MetricKind.POWER, "Sensors",
- uidSipper.sensorPowerMah, totalSensorPowerMah);
- addMetric(METRIC_AUDIO_POWER, MetricKind.POWER, "Audio",
- uidSipper.audioPowerMah, totalAudioPowerMah);
- addMetric(METRIC_VIDEO_POWER, MetricKind.POWER, "Video",
- uidSipper.videoPowerMah, totalVideoPowerMah);
+ for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
+ addMetric(getPowerMetricName(component), MetricKind.POWER,
+ selectedBatteryConsumer.getConsumedPower(component),
+ totalPowerPerComponentMah[component]);
+ }
- addMetric(METRIC_CPU_TIME, MetricKind.DURATION, "CPU time",
- uidSipper.cpuTimeMs, totalCpuTimeMs);
- addMetric(METRIC_CPU_FOREGROUND_TIME, MetricKind.DURATION, "CPU foreground time",
- uidSipper.cpuFgTimeMs, totalCpuFgTimeMs);
- addMetric(METRIC_WAKELOCK_TIME, MetricKind.DURATION, "Wake lock time",
- uidSipper.wakeLockTimeMs, totalWakeLockTimeMs);
- addMetric(METRIC_WIFI_RUNNING_TIME, MetricKind.DURATION, "WiFi running time",
- uidSipper.wifiRunningTimeMs, totalWifiRunningTimeMs);
- addMetric(METRIC_BLUETOOTH_RUNNING_TIME, MetricKind.DURATION, "Bluetooth time",
- uidSipper.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs);
- addMetric(METRIC_GPS_TIME, MetricKind.DURATION, "GPS time",
- uidSipper.gpsTimeMs, totalGpsTimeMs);
- addMetric(METRIC_CAMERA_TIME, MetricKind.DURATION, "Camera time",
- uidSipper.cameraTimeMs, totalCameraTimeMs);
- addMetric(METRIC_FLASHLIGHT_TIME, MetricKind.DURATION, "Flashlight time",
- uidSipper.flashlightTimeMs, totalFlashlightTimeMs);
- addMetric(METRIC_AUDIO_TIME, MetricKind.DURATION, "Audio time",
- uidSipper.audioTimeMs, totalAudioTimeMs);
- addMetric(METRIC_VIDEO_TIME, MetricKind.DURATION, "Video time",
- uidSipper.videoTimeMs, totalVideoTimeMs);
+ for (int component = 0; component < BatteryConsumer.TIME_COMPONENT_COUNT; component++) {
+ addMetric(getTimeMetricName(component), MetricKind.DURATION,
+ selectedBatteryConsumer.getUsageDurationMillis(component),
+ totalDurationPerComponentMs[component]);
+ }
+ }
+
+ static String getTimeMetricName(int componentId) {
+ return "TIME_" + DebugUtils.constantToString(BatteryConsumer.class,
+ "TIME_COMPONENT_", componentId);
+ }
+
+ static String getPowerMetricName(int componentId) {
+ return "POWER_" + DebugUtils.constantToString(BatteryConsumer.class,
+ "POWER_COMPONENT_", componentId);
}
public List<Metric> getMetrics() {
return mMetrics;
}
- public double getMinDrainedPower() {
- return mMinDrainedPower;
+ public double getDrainedPower() {
+ return mDrainedPower;
}
- public double getMaxDrainedPower() {
- return mMaxDrainedPower;
- }
-
- protected boolean isHiddenDrainType(BatterySipper.DrainType drainType) {
- return drainType == BatterySipper.DrainType.IDLE
- || drainType == BatterySipper.DrainType.CELL
- || drainType == BatterySipper.DrainType.SCREEN
- || drainType == BatterySipper.DrainType.UNACCOUNTED
- || drainType == BatterySipper.DrainType.OVERCOUNTED
- || drainType == BatterySipper.DrainType.BLUETOOTH
- || drainType == BatterySipper.DrainType.WIFI;
- }
-
- private boolean isSystemSipper(BatterySipper sipper) {
- final int uid = sipper.uidObj == null ? -1 : sipper.getUid();
- if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) {
- return true;
- } else if (sipper.mPackages != null) {
- for (final String packageName : sipper.mPackages) {
- for (final String systemPackage : PACKAGES_SYSTEM) {
- if (systemPackage.equals(packageName)) {
- return true;
- }
- }
- }
- }
-
- return false;
- }
-
- private void addMetric(String metricType, MetricKind metricKind, String title, double amount,
+ private void addMetric(String metricType, MetricKind metricKind, double amount,
double totalAmount) {
Metric metric = new Metric();
- metric.metricType = metricType;
+ metric.metricName = metricType;
metric.metricKind = metricKind;
- metric.title = title;
+ metric.statusKeyPrefix = metricKind.toString().toLowerCase();
metric.value = amount;
metric.total = totalAmount;
mMetrics.add(metric);
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetricsCollector.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetricsCollector.java
index 254458c..5b5da60 100644
--- a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetricsCollector.java
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetricsCollector.java
@@ -19,47 +19,43 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.app.Activity;
import android.app.Instrumentation;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.BatteryConsumer;
import android.os.BatteryManager;
-import android.os.BatteryStats;
+import android.os.BatteryStatsManager;
import android.os.Bundle;
+import android.os.ConditionVariable;
import android.os.Process;
import android.os.SystemClock;
-import android.os.UserManager;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.TimeUtils;
import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.compatibility.common.util.SystemUtil;
-import com.android.internal.os.BatteryStatsHelper;
-import com.android.internal.os.LoggingPrintStream;
-
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
-import java.io.PrintStream;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
public class PowerMetricsCollector implements TestRule {
private final String mTag;
private final float mBatteryDrainThresholdPct;
private final int mTimeoutMillis;
+ private final Instrumentation mInstrumentation;
private final Context mContext;
- private final UserManager mUserManager;
private final int mUid;
- private final BatteryStatsHelper mStatsHelper;
- private final CountDownLatch mSuspendingBatteryInput = new CountDownLatch(1);
+ private final ConditionVariable mSuspendingBatteryInput = new ConditionVariable();
private long mStartTime;
private volatile float mInitialBatteryLevel;
@@ -68,29 +64,34 @@
private PowerMetrics mInitialPowerMetrics;
private PowerMetrics mFinalPowerMetrics;
private List<PowerMetrics.Metric> mPowerMetricsDelta;
- private Intent mBatteryStatus;
+ private final BatteryStatsManager mBatteryStatsManager;
+ private final BroadcastReceiver mBatteryLevelReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ handleBatteryStatus(intent);
+ }
+ };
+ private final Bundle mStatus = new Bundle();
+ private final StringWriter mReportStringWriter = new StringWriter();
+ private final IndentingPrintWriter mReportWriter =
+ new IndentingPrintWriter(mReportStringWriter);
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
- BroadcastReceiver batteryBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- handleBatteryStatus(intent);
- }
- };
- mBatteryStatus = mContext.registerReceiver(batteryBroadcastReceiver,
- new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
disableCharger();
try {
- prepareBatteryLevelMonitor();
mStartTime = SystemClock.uptimeMillis();
+ mContext.registerReceiver(mBatteryLevelReceiver,
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
base.evaluate();
captureFinalPowerStatsData();
+ mStatus.putString("report", mReportStringWriter.toString());
+ mInstrumentation.sendStatus(Activity.RESULT_OK, mStatus);
} finally {
- mContext.unregisterReceiver(batteryBroadcastReceiver);
+ mContext.unregisterReceiver(mBatteryLevelReceiver);
enableCharger();
}
}
@@ -102,35 +103,41 @@
mBatteryDrainThresholdPct = batteryDrainThresholdPct;
mTimeoutMillis = timeoutMillis;
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- mContext = instrumentation.getContext();
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ mContext = mInstrumentation.getContext();
mUid = Process.myUid();
- mUserManager = mContext.getSystemService(UserManager.class);
- // TODO(b/175324611): Use BatteryUsageStats instead
- mStatsHelper = new BatteryStatsHelper(mContext, false /* collectBatteryBroadcast */);
- mStatsHelper.create((Bundle) null);
+ mBatteryStatsManager = mContext.getSystemService(BatteryStatsManager.class);
}
- private void disableCharger() throws InterruptedException {
- SystemUtil.runShellCommand("dumpsys battery suspend_input");
- final boolean success = mSuspendingBatteryInput.await(10, TimeUnit.SECONDS);
- assertTrue("Timed out waiting for battery input to be suspended", success);
+ private void disableCharger() {
+ final BroadcastReceiver receiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!isCharging(intent)) {
+ mInitialBatteryLevel = mCurrentBatteryLevel = getBatteryLevel(intent);
+ mSuspendingBatteryInput.open();
+ }
+ }
+ };
+ final Intent intent = mContext.registerReceiver(
+ receiver,
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+
+ if (isCharging(intent)) {
+ mBatteryStatsManager.suspendBatteryInput();
+ final boolean success = mSuspendingBatteryInput.block(10000);
+ assertTrue("Timed out waiting for battery input to be suspended", success);
+ }
+
+ mContext.unregisterReceiver(receiver);
}
private void enableCharger() {
- SystemUtil.runShellCommand("dumpsys battery reset");
+ mBatteryStatsManager.resetBattery(/* forceUpdate */false);
}
private PowerMetrics readBatteryStatsData() {
- mStatsHelper.clearStats();
- mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
- mUserManager.getUserProfiles());
- return new PowerMetrics(mStatsHelper, mUid);
- }
-
- protected void prepareBatteryLevelMonitor() {
- handleBatteryStatus(mBatteryStatus);
- mInitialBatteryLevel = mCurrentBatteryLevel;
+ return new PowerMetrics(mBatteryStatsManager.getBatteryUsageStats(), mUid);
}
protected void handleBatteryStatus(Intent intent) {
@@ -138,36 +145,35 @@
return;
}
- final boolean isCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
-
- if (mSuspendingBatteryInput.getCount() > 0) {
- if (!isCharging) {
- mSuspendingBatteryInput.countDown();
- }
- return;
- }
-
- if (isCharging) {
+ if (isCharging(intent)) {
fail("Device must remain disconnected from the power source "
+ "for the duration of the test");
}
- int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
- int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
-
- mCurrentBatteryLevel = level * 100 / (float) scale;
+ mCurrentBatteryLevel = getBatteryLevel(intent);
Log.i(mTag, "Battery level = " + mCurrentBatteryLevel);
// We delay tracking until the battery level drops. If the resolution of
// battery level is 1%, and the initially reported level is 73, we don't know whether
// it's 73.1 or 73.7. Once it drops to 72, we can be confident that the real battery
- // level it is very close to 72.0 and can start tracking.
+ // level is very close to 72.0 and can start tracking.
if (mInitialPowerMetrics == null && mCurrentBatteryLevel < mInitialBatteryLevel) {
mInitialBatteryLevel = mCurrentBatteryLevel;
mInitialPowerMetrics = readBatteryStatsData();
}
}
+ private boolean isCharging(Intent intent) {
+ return intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0;
+ }
+
+ private float getBatteryLevel(Intent intent) {
+ int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
+ int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
+
+ return level * 100 / (float) scale;
+ }
+
private void captureFinalPowerStatsData() {
if (mFinalPowerMetrics != null) {
return;
@@ -181,7 +187,7 @@
for (PowerMetrics.Metric initialMetric : initialPowerMetrics) {
PowerMetrics.Metric finalMetric = null;
for (PowerMetrics.Metric metric : finalPowerMetrics) {
- if (metric.title.equals(initialMetric.title)) {
+ if (metric.metricName.equals(initialMetric.metricName)) {
finalMetric = metric;
break;
}
@@ -189,9 +195,9 @@
if (finalMetric != null) {
PowerMetrics.Metric delta = new PowerMetrics.Metric();
- delta.metricType = initialMetric.metricType;
+ delta.metricName = initialMetric.metricName;
delta.metricKind = initialMetric.metricKind;
- delta.title = initialMetric.title;
+ delta.statusKeyPrefix = initialMetric.statusKeyPrefix;
delta.total = finalMetric.total - initialMetric.total;
delta.value = finalMetric.value - initialMetric.value;
mPowerMetricsDelta.add(delta);
@@ -230,73 +236,80 @@
return mIterations;
}
- public void dumpMetrics() {
- dumpMetrics(new LoggingPrintStream() {
- @Override
- protected void log(String line) {
- Log.i(mTag, line);
- }
- });
+ public void report(String line) {
+ mReportWriter.println(line);
}
- public void dumpMetrics(PrintStream out) {
+ public void reportMetrics() {
List<PowerMetrics.Metric> initialPowerMetrics = mInitialPowerMetrics.getMetrics();
List<PowerMetrics.Metric> finalPowerMetrics = mFinalPowerMetrics.getMetrics();
- out.println("== Power metrics at test start");
- dumpPowerStatsData(out, initialPowerMetrics);
+ mReportWriter.println("Power metrics at test start");
+ mReportWriter.increaseIndent();
+ reportPowerStatsData(initialPowerMetrics);
+ mReportWriter.decreaseIndent();
- out.println("== Power metrics at test end");
- dumpPowerStatsData(out, finalPowerMetrics);
+ mReportWriter.println("Power metrics at test end");
+ mReportWriter.increaseIndent();
+ reportPowerStatsData(finalPowerMetrics);
+ mReportWriter.decreaseIndent();
- out.println("== Power metrics delta");
- dumpPowerStatsData(out, mPowerMetricsDelta);
+ mReportWriter.println("Power metrics delta");
+ mReportWriter.increaseIndent();
+ reportPowerStatsData(mPowerMetricsDelta);
+ mReportWriter.decreaseIndent();
}
- protected void dumpPowerStatsData(PrintStream out, List<PowerMetrics.Metric> metrics) {
+ protected void reportPowerStatsData(List<PowerMetrics.Metric> metrics) {
Locale locale = Locale.getDefault();
for (PowerMetrics.Metric metric : metrics) {
double proportion = metric.total != 0 ? metric.value * 100 / metric.total : 0;
switch (metric.metricKind) {
case POWER:
- out.println(
- String.format(locale, " %-30s %7.1f mAh %4.1f%%", metric.title,
+ mReportWriter.println(
+ String.format(locale, "%-40s %7.1f mAh %4.1f%%", metric.metricName,
metric.value, proportion));
break;
case DURATION:
- out.println(
- String.format(locale, " %-30s %,7d ms %4.1f%%", metric.title,
+ mReportWriter.println(
+ String.format(locale, "%-40s %,7d ms %4.1f%%", metric.metricName,
(long) metric.value, proportion));
break;
}
}
}
- public void dumpMetricAsPercentageOfDrainedPower(String metricType) {
- double minDrainedPower =
- mFinalPowerMetrics.getMinDrainedPower() - mInitialPowerMetrics.getMinDrainedPower();
- double maxDrainedPower =
- mFinalPowerMetrics.getMaxDrainedPower() - mInitialPowerMetrics.getMaxDrainedPower();
+ public void reportMetricAsPercentageOfDrainedPower(
+ @BatteryConsumer.PowerComponent int component) {
+ double drainedPower =
+ mFinalPowerMetrics.getDrainedPower() - mInitialPowerMetrics.getDrainedPower();
- PowerMetrics.Metric metric = getMetric(metricType);
+ PowerMetrics.Metric metric = getPowerMetric(component);
double metricDelta = metric.value;
- if (maxDrainedPower - minDrainedPower < 0.1f) {
- Log.i(mTag, String.format(Locale.getDefault(),
- "%s power consumed by the test: %.1f of %.1f mAh (%.1f%%)",
- metric.title, metricDelta, maxDrainedPower,
- metricDelta / maxDrainedPower * 100));
- } else {
- Log.i(mTag, String.format(Locale.getDefault(),
- "%s power consumed by the test: %.1f of %.1f - %.1f mAh (%.1f%% - %.1f%%)",
- metric.title, metricDelta, minDrainedPower, maxDrainedPower,
- metricDelta / minDrainedPower * 100, metricDelta / maxDrainedPower * 100));
- }
+ final double percent = metricDelta / drainedPower * 100;
+ mStatus.putDouble(metric.statusKeyPrefix, metricDelta);
+ mStatus.putDouble(metric.statusKeyPrefix + "_pct", percent);
+
+ mReportWriter.println(String.format(Locale.getDefault(),
+ "%s power consumed by the test: %.1f of %.1f mAh (%.1f%%)",
+ metric.metricName, metricDelta, drainedPower, percent));
}
- public PowerMetrics.Metric getMetric(String metricType) {
+ public PowerMetrics.Metric getPowerMetric(@BatteryConsumer.PowerComponent int component) {
+ final String name = PowerMetrics.getPowerMetricName(component);
for (PowerMetrics.Metric metric : mPowerMetricsDelta) {
- if (metric.metricType.equals(metricType)) {
+ if (metric.metricName.equals(name)) {
+ return metric;
+ }
+ }
+ return null;
+ }
+
+ public PowerMetrics.Metric getTimeMetric(@BatteryConsumer.TimeComponent int component) {
+ final String name = PowerMetrics.getTimeMetricName(component);
+ for (PowerMetrics.Metric metric : mPowerMetricsDelta) {
+ if (metric.metricName.equals(name)) {
return metric;
}
}
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/SystemServiceCallLoadTest.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/SystemServiceCallLoadTest.java
index 488469d..1ebc743 100644
--- a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/SystemServiceCallLoadTest.java
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/SystemServiceCallLoadTest.java
@@ -23,7 +23,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
-import android.util.Log;
+import android.os.BatteryConsumer;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -58,12 +58,12 @@
assertNotNull(resolveInfo);
}
- mPowerMetricsCollector.dumpMetrics();
+ mPowerMetricsCollector.reportMetrics();
- Log.i(TAG, "==");
- Log.i(TAG, "Total system server calls made " + mPowerMetricsCollector.getIterationCount());
+ mPowerMetricsCollector.report(
+ "Total system server calls made: " + mPowerMetricsCollector.getIterationCount());
- mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower(
- PowerMetrics.METRIC_SYSTEM_SERVICE_CPU_POWER);
+ mPowerMetricsCollector.reportMetricAsPercentageOfDrainedPower(
+ BatteryConsumer.POWER_COMPONENT_SYSTEM_SERVICES);
}
}
diff --git a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/WiFiLoadTest.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/WiFiLoadTest.java
index 27495da..15bb3fc 100644
--- a/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/WiFiLoadTest.java
+++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/WiFiLoadTest.java
@@ -16,7 +16,7 @@
package com.android.frameworks.core.batterystatsloadtests;
-import android.util.Log;
+import android.os.BatteryConsumer;
import org.junit.Rule;
import org.junit.Test;
@@ -59,14 +59,15 @@
}
}
- mPowerMetricsCollector.dumpMetrics();
+ mPowerMetricsCollector.reportMetrics();
- Log.i(TAG, "==");
- Log.i(TAG, "WiFi running time: " + (long) mPowerMetricsCollector.getMetric(
- PowerMetrics.METRIC_WIFI_RUNNING_TIME).value);
- Log.i(TAG, "Total bytes read over WiFi: " + totalBytesRead);
+ mPowerMetricsCollector.report(
+ "WiFi running time: " + (long) mPowerMetricsCollector.getTimeMetric(
+ BatteryConsumer.POWER_COMPONENT_WIFI).value);
- mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower(
- PowerMetrics.METRIC_WIFI_POWER);
+ mPowerMetricsCollector.report("Total bytes read over WiFi: " + totalBytesRead);
+
+ mPowerMetricsCollector.reportMetricAsPercentageOfDrainedPower(
+ BatteryConsumer.POWER_COMPONENT_WIFI);
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java
index c67f901..cf47efd 100644
--- a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java
@@ -19,7 +19,6 @@
import static com.google.common.truth.Truth.assertThat;
import android.os.BatteryConsumer;
-import android.os.BatteryUsageStatsQuery;
import android.os.SystemBatteryConsumer;
import android.view.Display;
@@ -71,6 +70,8 @@
// 100,000,00 uC / 1000 (micro-/milli-) / 360 (seconds/hour) = 27.777778 mAh
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE))
.isWithin(PRECISION).of(27.777778);
+ assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_USAGE))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
}
@Test
@@ -85,8 +86,7 @@
AmbientDisplayPowerCalculator calculator =
new AmbientDisplayPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
- calculator);
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
SystemBatteryConsumer consumer =
mStatsRule.getSystemBatteryConsumer(
@@ -95,5 +95,7 @@
.isEqualTo(90 * MINUTE_IN_MS);
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE))
.isWithin(PRECISION).of(15.0);
+ assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_USAGE))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
index 80ab36e..1e614c4 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
@@ -43,6 +43,12 @@
import java.util.Arrays;
public class BatteryUsageStatsRule implements TestRule {
+ public static final BatteryUsageStatsQuery POWER_PROFILE_MODEL_ONLY =
+ new BatteryUsageStatsQuery.Builder()
+ .powerProfileModeledOnly()
+ .includePowerModels()
+ .build();
+
private final PowerProfile mPowerProfile;
private final MockClocks mMockClocks = new MockClocks();
private final MockBatteryStatsImpl mBatteryStats = new MockBatteryStatsImpl(mMockClocks) {
@@ -156,7 +162,8 @@
}
BatteryUsageStats apply(PowerCalculator... calculators) {
- return apply(BatteryUsageStatsQuery.DEFAULT, calculators);
+ return apply(new BatteryUsageStatsQuery.Builder().includePowerModels().build(),
+ calculators);
}
BatteryUsageStats apply(BatteryUsageStatsQuery query, PowerCalculator... calculators) {
@@ -165,8 +172,10 @@
final int customMeasuredEnergiesCount = customMeasuredEnergiesMicroJoules != null
? customMeasuredEnergiesMicroJoules.length
: 0;
+ final boolean includePowerModels = (query.getFlags()
+ & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;
BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(
- customMeasuredEnergiesCount, 0);
+ customMeasuredEnergiesCount, 0, includePowerModels);
SparseArray<? extends BatteryStats.Uid> uidStats = mBatteryStats.getUidStats();
for (int i = 0; i < uidStats.size(); i++) {
builder.getOrCreateUidBatteryConsumerBuilder(uidStats.valueAt(i));
diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
index 2769b16..1a87c10 100644
--- a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
@@ -19,6 +19,8 @@
import static com.google.common.truth.Truth.assertThat;
import android.annotation.Nullable;
+import android.bluetooth.BluetoothActivityEnergyInfo;
+import android.bluetooth.UidTraffic;
import android.os.BatteryConsumer;
import android.os.BatteryUsageStatsQuery;
import android.os.Process;
@@ -41,7 +43,8 @@
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
.setAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE, 10.0)
.setAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX, 50.0)
- .setAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX, 100.0);
+ .setAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX, 100.0)
+ .initMeasuredEnergyStatsLocked(0);
@Test
public void testTimerBasedModel() {
@@ -60,16 +63,15 @@
BluetoothPowerCalculator calculator =
new BluetoothPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
- calculator);
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
assertThat(mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID)).isNull();
assertBluetoothPowerAndDuration(
mStatsRule.getUidBatteryConsumer(APP_UID),
- 0.24722, 15000);
+ 0.24722, 15000, BatteryConsumer.POWER_MODEL_POWER_PROFILE);
assertBluetoothPowerAndDuration(
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH),
- 0.51944, 9000, 0.51944, 0.36111);
+ 0.51944, 9000, 0.51944, 0.36111, BatteryConsumer.POWER_MODEL_POWER_PROFILE);
}
@Test
@@ -89,16 +91,40 @@
BluetoothPowerCalculator calculator =
new BluetoothPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
+
+ assertThat(mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID)).isNull();
+ assertBluetoothPowerAndDuration(
+ mStatsRule.getUidBatteryConsumer(APP_UID),
+ 0.2, 15000, BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+ assertBluetoothPowerAndDuration(
+ mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH),
+ 0.45, 9000, 0.45, 0.3, BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+ }
+
+ @Test
+ public void testMeasuredEnergyBasedModel() {
+ final BluetoothActivityEnergyInfo info = new BluetoothActivityEnergyInfo(1000,
+ BluetoothActivityEnergyInfo.BT_STACK_STATE_STATE_ACTIVE, 7000, 5000, 0, 100000);
+ info.setUidTraffic(new UidTraffic[]{
+ new UidTraffic(Process.BLUETOOTH_UID, 1000, 2000),
+ new UidTraffic(APP_UID, 3000, 4000)
+ });
+ mStatsRule.getBatteryStats().updateBluetoothStateLocked(info, 1200000, 1000, 1000);
+
+ final BluetoothPowerCalculator calculator =
+ new BluetoothPowerCalculator(mStatsRule.getPowerProfile());
+
+ mStatsRule.apply(new BatteryUsageStatsQuery.Builder().includePowerModels().build(),
calculator);
assertThat(mStatsRule.getUidBatteryConsumer(Process.BLUETOOTH_UID)).isNull();
assertBluetoothPowerAndDuration(
mStatsRule.getUidBatteryConsumer(APP_UID),
- 0.2, 15000);
+ 0.22950, 8416, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
assertBluetoothPowerAndDuration(
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH),
- 0.45, 9000, 0.45, 0.3);
+ 0.43712, 3584, 0.43712, 0.33329, BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
}
private void setDurationsAndPower(
@@ -111,12 +137,14 @@
}
private void assertBluetoothPowerAndDuration(@Nullable BatteryConsumer batteryConsumer,
- double powerMah, int durationMs) {
+ double powerMah, int durationMs, @BatteryConsumer.PowerModel int powerModel) {
assertThat(batteryConsumer).isNotNull();
double consumedPower = batteryConsumer.getConsumedPower(
BatteryConsumer.POWER_COMPONENT_BLUETOOTH);
assertThat(consumedPower).isWithin(PRECISION).of(powerMah);
+ assertThat(batteryConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_BLUETOOTH))
+ .isEqualTo(powerModel);
long usageDurationMillis = batteryConsumer.getUsageDurationMillis(
BatteryConsumer.TIME_COMPONENT_BLUETOOTH);
@@ -125,8 +153,9 @@
}
private void assertBluetoothPowerAndDuration(@Nullable SystemBatteryConsumer batteryConsumer,
- double powerMah, int durationMs, double consumedPower, double attributedPower) {
- assertBluetoothPowerAndDuration(batteryConsumer, powerMah, durationMs);
+ double powerMah, int durationMs, double consumedPower, double attributedPower,
+ @BatteryConsumer.PowerModel int powerModel) {
+ assertBluetoothPowerAndDuration(batteryConsumer, powerMah, durationMs, powerModel);
assertThat(batteryConsumer.getConsumedPower())
.isWithin(PRECISION).of(consumedPower);
diff --git a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
index 496415a..31abbc2 100644
--- a/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/CpuPowerCalculatorTest.java
@@ -26,7 +26,6 @@
import static org.mockito.Mockito.when;
import android.os.BatteryConsumer;
-import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.UidBatteryConsumer;
@@ -142,14 +141,15 @@
CpuPowerCalculator calculator =
new CpuPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
- calculator);
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
UidBatteryConsumer uidConsumer1 = mStatsRule.getUidBatteryConsumer(APP_UID1);
assertThat(uidConsumer1.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU))
.isEqualTo(3333);
assertThat(uidConsumer1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
.isWithin(PRECISION).of(1.092233);
+ assertThat(uidConsumer1.getPowerModel(BatteryConsumer.POWER_COMPONENT_CPU))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
assertThat(uidConsumer1.getPackageWithHighestDrain()).isEqualTo("bar");
UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
@@ -157,6 +157,8 @@
.isEqualTo(7777);
assertThat(uidConsumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
.isWithin(PRECISION).of(2.672322);
+ assertThat(uidConsumer2.getPowerModel(BatteryConsumer.POWER_COMPONENT_CPU))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
assertThat(uidConsumer2.getPackageWithHighestDrain()).isNull();
}
@@ -210,6 +212,8 @@
.isEqualTo(3333);
assertThat(uidConsumer1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
.isWithin(PRECISION).of(3.18877);
+ assertThat(uidConsumer1.getPowerModel(BatteryConsumer.POWER_COMPONENT_CPU))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
assertThat(uidConsumer1.getPackageWithHighestDrain()).isEqualTo("bar");
UidBatteryConsumer uidConsumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
@@ -217,6 +221,8 @@
.isEqualTo(7777);
assertThat(uidConsumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU))
.isWithin(PRECISION).of(7.44072);
+ assertThat(uidConsumer2.getPowerModel(BatteryConsumer.POWER_COMPONENT_CPU))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
assertThat(uidConsumer2.getPackageWithHighestDrain()).isNull();
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/GnssPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/GnssPowerCalculatorTest.java
index eed61cb..95c3b4e 100644
--- a/core/tests/coretests/src/com/android/internal/os/GnssPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/GnssPowerCalculatorTest.java
@@ -19,7 +19,6 @@
import static com.google.common.truth.Truth.assertThat;
import android.os.BatteryConsumer;
-import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.UidBatteryConsumer;
@@ -54,14 +53,15 @@
GnssPowerCalculator calculator =
new GnssPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
- calculator);
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
UidBatteryConsumer consumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(consumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_GNSS))
.isEqualTo(1000);
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS))
.isWithin(PRECISION).of(0.1);
+ assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_GNSS))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
}
@Test
@@ -87,11 +87,15 @@
.isEqualTo(1000);
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS))
.isWithin(PRECISION).of(2.77777);
+ assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_GNSS))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
UidBatteryConsumer consumer2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
assertThat(consumer2.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_GNSS))
.isEqualTo(2000);
assertThat(consumer2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_GNSS))
.isWithin(PRECISION).of(5.55555);
+ assertThat(consumer2.getPowerModel(BatteryConsumer.POWER_COMPONENT_GNSS))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
index 813bc9f..3505e8c 100644
--- a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
@@ -26,7 +26,6 @@
import android.net.NetworkCapabilities;
import android.net.NetworkStats;
import android.os.BatteryConsumer;
-import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.SystemBatteryConsumer;
import android.os.UidBatteryConsumer;
@@ -99,13 +98,14 @@
MobileRadioPowerCalculator calculator =
new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
- calculator);
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
SystemBatteryConsumer consumer =
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_MOBILE_RADIO);
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isWithin(PRECISION).of(2.2444);
+ assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
assertThat(consumer.getConsumedPower())
.isWithin(PRECISION).of(2.2444);
assertThat(consumer.getPowerConsumedByApps())
@@ -114,6 +114,8 @@
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isWithin(PRECISION).of(0.8);
+ assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
}
@Test
@@ -163,11 +165,15 @@
// 100000000 uAs * (1 mA / 1000 uA) * (1 h / 3600 s) + 1.53934 (apps)= 4.31711 mAh
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isWithin(PRECISION).of(4.31711);
+ assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
assertThat(consumer.getPowerConsumedByApps())
.isWithin(PRECISION).of(1.53934);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isWithin(PRECISION).of(1.53934);
+ assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java
index d296afa..9cd6ea8 100644
--- a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java
@@ -20,7 +20,6 @@
import android.app.ActivityManager;
import android.os.BatteryConsumer;
-import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.SystemBatteryConsumer;
import android.os.UidBatteryConsumer;
@@ -91,6 +90,8 @@
// 600000000 uAs * (1 mA / 1000 uA) * (1 h / 3600 s) = 166.66666 mAh
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE))
.isWithin(PRECISION).of(166.66666);
+ assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_USAGE))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
assertThat(consumer.getConsumedPower())
.isWithin(PRECISION).of(166.66666);
assertThat(consumer.getPowerConsumedByApps())
@@ -105,6 +106,8 @@
// Uid1 charge = 200000000 + 5 / 45 * 300000000 mAs = 64.81 mAh
assertThat(uid1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
.isWithin(PRECISION).of(64.81481);
+ assertThat(uid1.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
UidBatteryConsumer uid2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
assertThat(uid2.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN))
@@ -115,6 +118,8 @@
// Uid2 charge = 40 / 45 * 300000000 + 100000000 mAs = 101.85 mAh
assertThat(uid2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
.isWithin(PRECISION).of(101.85185);
+ assertThat(uid2.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
}
@Test
@@ -144,8 +149,7 @@
ScreenPowerCalculator calculator =
new ScreenPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
- calculator);
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
SystemBatteryConsumer consumer =
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_SCREEN);
@@ -153,6 +157,8 @@
.isEqualTo(80 * MINUTE_IN_MS);
assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE))
.isWithin(PRECISION).of(92.0);
+ assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_USAGE))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
assertThat(consumer.getConsumedPower())
.isWithin(PRECISION).of(92.0);
assertThat(consumer.getPowerConsumedByApps())
@@ -166,6 +172,8 @@
// Uid1 charge = 20 / 80 * 92.0 = 23.0 mAh
assertThat(uid1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
.isWithin(PRECISION).of(23.0);
+ assertThat(uid1.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
UidBatteryConsumer uid2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
assertThat(uid2.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_SCREEN))
@@ -175,6 +183,8 @@
// Uid2 charge = 60 / 80 * 92.0 = 69.0 mAh
assertThat(uid2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
.isWithin(PRECISION).of(69.0);
+ assertThat(uid2.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
}
private void setProcState(int uid, int procState, boolean resumed, long realtimeMs,
diff --git a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
index 5df91dd..2e501db 100644
--- a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
@@ -24,7 +24,6 @@
import android.net.NetworkCapabilities;
import android.net.NetworkStats;
import android.os.BatteryConsumer;
-import android.os.BatteryUsageStatsQuery;
import android.os.Process;
import android.os.SystemBatteryConsumer;
import android.os.UidBatteryConsumer;
@@ -85,14 +84,15 @@
batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000);
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
- calculator);
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
.isEqualTo(1423);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
.isWithin(PRECISION).of(0.2214666);
+ assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
SystemBatteryConsumer systemConsumer =
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
@@ -100,6 +100,8 @@
.isEqualTo(5577);
assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
.isWithin(PRECISION).of(1.11153);
+ assertThat(systemConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
assertThat(systemConsumer.getPowerConsumedByApps())
.isWithin(PRECISION).of(0.466333);
}
@@ -120,6 +122,8 @@
/* Same ratio as in testPowerControllerBasedModel_nonMeasured but scaled by 1_000_000uC. */
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
.isWithin(PRECISION).of(0.2214666 / (0.2214666 + 0.645200) * 1_000_000 / 3600000);
+ assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
SystemBatteryConsumer systemConsumer =
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
@@ -128,6 +132,8 @@
/* Same ratio as in testPowerControllerBasedModel_nonMeasured but scaled by 1_000_000uC. */
assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
.isWithin(PRECISION).of(1.11153 / (0.2214666 + 0.645200) * 1_000_000 / 3600000);
+ assertThat(systemConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
assertThat(systemConsumer.getPowerConsumedByApps())
.isWithin(PRECISION).of(0.14946);
}
@@ -153,14 +159,15 @@
batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000);
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
- mStatsRule.apply(new BatteryUsageStatsQuery.Builder().powerProfileModeledOnly().build(),
- calculator);
+ mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_WIFI))
.isEqualTo(1000);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
.isWithin(PRECISION).of(0.8231573);
+ assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
SystemBatteryConsumer systemConsumer =
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
@@ -168,6 +175,8 @@
.isEqualTo(2222);
assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
.isWithin(PRECISION).of(2.575000);
+ assertThat(systemConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
assertThat(systemConsumer.getPowerConsumedByApps())
.isWithin(PRECISION).of(1.69907);
}
@@ -189,6 +198,8 @@
/* Same ratio as in testTimerBasedModel_nonMeasured but scaled by 1_000_000uC. */
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
.isWithin(PRECISION).of(0.8231573 / (0.8231573 + 0.8759216) * 1_000_000 / 3600000);
+ assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
SystemBatteryConsumer systemConsumer =
mStatsRule.getSystemBatteryConsumer(SystemBatteryConsumer.DRAIN_TYPE_WIFI);
@@ -197,6 +208,8 @@
/* Same ratio as in testTimerBasedModel_nonMeasured but scaled by 1_000_000uC. */
assertThat(systemConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_WIFI))
.isWithin(PRECISION).of(2.575000 / (0.8231573 + 0.8759216) * 1_000_000 / 3600000);
+ assertThat(systemConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_WIFI))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
assertThat(systemConsumer.getPowerConsumedByApps())
.isWithin(PRECISION).of(0.277777);
}
diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
index 94d5c22..fb08974 100644
--- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java
+++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
@@ -49,23 +49,12 @@
private Runnable mOnUpdate;
private long mStartTime;
private boolean mForceSoftware;
- private final ValueAnimator mSparkle = ValueAnimator.ofFloat(0, 1);
+ private boolean mAnimateSparkle;
RippleAnimationSession(@NonNull AnimationProperties<Float, Paint> properties,
boolean forceSoftware) {
mProperties = properties;
mForceSoftware = forceSoftware;
-
- mSparkle.addUpdateListener(anim -> {
- final long now = AnimationUtils.currentAnimationTimeMillis();
- final long elapsed = now - mStartTime - ENTER_ANIM_DURATION;
- final float phase = (float) elapsed / 800;
- mProperties.getShader().setNoisePhase(phase);
- notifyUpdate();
- });
- mSparkle.setDuration(ENTER_ANIM_DURATION);
- mSparkle.setInterpolator(LINEAR_INTERPOLATOR);
- mSparkle.setRepeatCount(ValueAnimator.INFINITE);
}
@NonNull RippleAnimationSession enter(Canvas canvas) {
@@ -99,6 +88,16 @@
return this;
}
+ public boolean shouldAnimateSparkle() {
+ return mAnimateSparkle;
+ }
+
+ public float getSparklePhase() {
+ final long now = AnimationUtils.currentAnimationTimeMillis();
+ final long elapsed = now - mStartTime;
+ return (float) elapsed / 800;
+ }
+
private boolean isHwAccelerated(Canvas canvas) {
return canvas.isHardwareAccelerated() && !mForceSoftware;
}
@@ -115,7 +114,7 @@
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- mSparkle.end();
+ mAnimateSparkle = false;
Consumer<RippleAnimationSession> onEnd = mOnSessionEnd;
if (onEnd != null) onEnd.accept(RippleAnimationSession.this);
}
@@ -149,7 +148,7 @@
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- mSparkle.end();
+ mAnimateSparkle = false;
Consumer<RippleAnimationSession> onEnd = mOnSessionEnd;
if (onEnd != null) onEnd.accept(RippleAnimationSession.this);
}
@@ -176,9 +175,7 @@
expand.addListener(new AnimatorListener(this));
expand.setInterpolator(FAST_OUT_LINEAR_IN);
expand.start();
- if (!mSparkle.isRunning()) {
- mSparkle.start();
- }
+ mAnimateSparkle = true;
}
private void enterSoftware() {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 3bd0a43..8b8cbbc 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -48,7 +48,6 @@
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.Build;
-import android.os.SystemProperties;
import android.util.AttributeSet;
import android.view.animation.LinearInterpolator;
@@ -152,8 +151,7 @@
private static final int MAX_RIPPLES = 10;
private static final LinearInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
/** Temporary flag for teamfood. **/
- private static final boolean FORCE_PATTERNED_STYLE =
- SystemProperties.getBoolean("persist.material.patternedripple", false);
+ private static final boolean FORCE_PATTERNED_STYLE = true;
private final Rect mTempRect = new Rect();
@@ -861,6 +859,15 @@
}
for (int i = 0; i < mRunningAnimations.size(); i++) {
RippleAnimationSession s = mRunningAnimations.get(i);
+ if (s.shouldAnimateSparkle()) {
+ final float phase = s.getSparklePhase();
+ if (useCanvasProps) {
+ s.getCanvasProperties().getShader().setNoisePhase(phase);
+ } else {
+ s.getProperties().getShader().setNoisePhase(phase);
+ }
+ invalidateSelf();
+ }
if (useCanvasProps) {
RippleAnimationSession.AnimationProperties<CanvasProperty<Float>,
CanvasProperty<Paint>>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index af4ccad..5c3af3e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -42,7 +42,7 @@
* Controller class of PiP animations (both from and to PiP mode).
*/
public class PipAnimationController {
- private static final float FRACTION_START = 0f;
+ static final float FRACTION_START = 0f;
private static final float FRACTION_END = 1f;
public static final int ANIM_TYPE_BOUNDS = 0;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 99ec100..f6b63eb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -25,6 +25,7 @@
import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
+import static com.android.wm.shell.pip.PipAnimationController.FRACTION_START;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN;
@@ -352,9 +353,19 @@
// updated right after applying the windowing mode change.
final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
mPictureInPictureParams, destinationBounds);
- scheduleAnimateResizePip(mPipBoundsState.getBounds(), destinationBounds,
+ final PipAnimationController.PipTransitionAnimator<?> animator =
+ scheduleAnimateResizePip(mPipBoundsState.getBounds(), destinationBounds,
0 /* startingAngle */, sourceHintRect, direction,
animationDurationMs, null /* updateBoundsCallback */);
+ if (animator != null) {
+ // Even though the animation was started above, re-apply the transaction for the
+ // first frame using the SurfaceControl.Transaction supplied by the
+ // SyncTransactionQueue. This is necessary because the initial surface transform
+ // may not be applied until the next frame if a different Transaction than the one
+ // supplied is used, resulting in 1 frame not being cropped to the source rect
+ // hint during expansion that causes a visible jank/flash. See b/184166183.
+ animator.applySurfaceControlTransaction(mLeash, t, FRACTION_START);
+ }
mState = State.EXITING_PIP;
});
}
@@ -768,22 +779,24 @@
* Animates resizing of the pinned stack given the duration and start bounds.
* This always animates the angle to zero from the starting angle.
*/
- private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
- float startingAngle, Rect sourceHintRect,
+ private @Nullable PipAnimationController.PipTransitionAnimator<?> scheduleAnimateResizePip(
+ Rect currentBounds, Rect destinationBounds, float startingAngle, Rect sourceHintRect,
@PipAnimationController.TransitionDirection int direction, int durationMs,
Consumer<Rect> updateBoundsCallback) {
if (!mState.isInPip()) {
// TODO: tend to use shouldBlockResizeRequest here as well but need to consider
// the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
// container transaction callback and we want to set the mState immediately.
- return;
+ return null;
}
- animateResizePip(currentBounds, destinationBounds, sourceHintRect, direction, durationMs,
+ final PipAnimationController.PipTransitionAnimator<?> animator = animateResizePip(
+ currentBounds, destinationBounds, sourceHintRect, direction, durationMs,
startingAngle);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(destinationBounds);
}
+ return animator;
}
/**
@@ -968,28 +981,26 @@
destinationBounds.height());
mSurfaceTransactionHelper.scale(t, snapshotSurface, snapshotSrc, snapshotDest);
- mMainExecutor.execute(() -> {
- // Start animation to fade out the snapshot.
- final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f);
- animator.setDuration(mEnterAnimationDuration);
- animator.addUpdateListener(animation -> {
- final float alpha = (float) animation.getAnimatedValue();
- final SurfaceControl.Transaction transaction =
- mSurfaceControlTransactionFactory.getTransaction();
- transaction.setAlpha(snapshotSurface, alpha);
- transaction.apply();
- });
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- final SurfaceControl.Transaction tx =
- mSurfaceControlTransactionFactory.getTransaction();
- tx.remove(snapshotSurface);
- tx.apply();
- }
- });
- animator.start();
+ // Start animation to fade out the snapshot.
+ final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f);
+ animator.setDuration(mEnterAnimationDuration);
+ animator.addUpdateListener(animation -> {
+ final float alpha = (float) animation.getAnimatedValue();
+ final SurfaceControl.Transaction transaction =
+ mSurfaceControlTransactionFactory.getTransaction();
+ transaction.setAlpha(snapshotSurface, alpha);
+ transaction.apply();
});
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ final SurfaceControl.Transaction tx =
+ mSurfaceControlTransactionFactory.getTransaction();
+ tx.remove(snapshotSurface);
+ tx.apply();
+ }
+ });
+ animator.start();
});
} else {
applyFinishBoundsResize(wct, direction);
@@ -1050,26 +1061,28 @@
return WINDOWING_MODE_UNDEFINED;
}
- private void animateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
+ private @Nullable PipAnimationController.PipTransitionAnimator<?> animateResizePip(
+ Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
@PipAnimationController.TransitionDirection int direction, int durationMs,
float startingAngle) {
// Could happen when exitPip
if (mToken == null || mLeash == null) {
Log.w(TAG, "Abort animation, invalid leash");
- return;
+ return null;
}
final int rotationDelta = mWaitForFixedRotation
? ((mNextRotation - mPipBoundsState.getDisplayLayout().rotation()) + 4) % 4
: Surface.ROTATION_0;
Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
? mPipBoundsState.getBounds() : currentBounds;
- mPipAnimationController
+ final PipAnimationController.PipTransitionAnimator<?> animator = mPipAnimationController
.getAnimator(mTaskInfo, mLeash, baseBounds, currentBounds, destinationBounds,
- sourceHintRect, direction, startingAngle, rotationDelta)
- .setTransitionDirection(direction)
+ sourceHintRect, direction, startingAngle, rotationDelta);
+ animator.setTransitionDirection(direction)
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(durationMs)
.start();
+ return animator;
}
/**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 8134d6f..7220379 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -27,6 +27,7 @@
import android.media.audiofx.AudioEffect;
import android.media.audiopolicy.AudioMix;
import android.os.Build;
+import android.os.Vibrator;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.Pair;
@@ -1937,6 +1938,14 @@
public static native int getDevicesForRoleAndCapturePreset(
int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices);
+ /**
+ * @hide
+ * Set the vibrators' information. The value will be used to initialize HapticGenerator.
+ * @param vibrators a list of all available vibrators
+ * @return command completion status
+ */
+ public static native int setVibratorInfos(@NonNull List<Vibrator> vibrators);
+
// Items shared with audio service
/**
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 822d22b..4968bd1 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -1684,7 +1684,6 @@
private MediaCodecInfo mCodecInfo;
private final Object mCodecInfoLock = new Object();
private MediaCrypto mCrypto;
- private String mPlaybackId;
private static final int EVENT_CALLBACK = 1;
private static final int EVENT_SET_CALLBACK = 2;
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 2448d48..50a326e 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -219,6 +219,15 @@
private Map<String, Object> mMap;
/**
+ * A key describing the log session ID for MediaCodec. The log session ID is a random 32-byte
+ * hexadecimal string that is used to associate metrics from multiple media codec instances
+ * to the same playback or recording session.
+ * The associated value is a string.
+ * @hide
+ */
+ public static final String LOG_SESSION_ID = "log-session-id";
+
+ /**
* A key describing the mime type of the MediaFormat.
* The associated value is a string.
*/
diff --git a/native/android/OWNERS b/native/android/OWNERS
index d414ed4..6f7def8 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -2,3 +2,7 @@
per-file libandroid_net.map.txt, net.c = codewiz@google.com, jchalard@google.com, junyulai@google.com
per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
per-file system_fonts.cpp = file:/graphics/java/android/graphics/fonts/OWNERS
+
+per-file native_window_jni.cpp = file:/services/core/java/com/android/server/wm/OWNERS
+per-file native_activity.cpp = file:/services/core/java/com/android/server/wm/OWNERS
+per-file surface_control.cpp = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index c6472de..bcc22f6 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1405,6 +1405,8 @@
<string name="user_switch_to_user">Switch to <xliff:g id="user_name" example="John Doe">%s</xliff:g></string>
<!-- Dialog message when creating a new user [CHAR LIMIT=40] -->
<string name="creating_new_user_dialog_message">Creating new user…</string>
+ <!-- Text shown to notify that the creation of new user has failed. [CHAR LIMIT=40] -->
+ <string name="add_user_failed">Failed to create a new user</string>
<!-- Title for the preference to enter the nickname of the user to display in the user switcher [CHAR LIMIT=25]-->
<string name="user_nickname">Nickname</string>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 6cf2bb6..b6b5ae5 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -458,6 +458,9 @@
<!-- Permission required for CTS test - SystemMediaRouter2Test -->
<uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
+ <!-- Permission required for CTS test - CtsRotationResolverServiceDeviceTestCases -->
+ <uses-permission android:name="android.permission.MANAGE_ROTATION_RESOLVER" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/res/drawable/ic_fingerprint.xml b/packages/SystemUI/res/drawable/ic_fingerprint.xml
index e5f3360..91d72a7 100644
--- a/packages/SystemUI/res/drawable/ic_fingerprint.xml
+++ b/packages/SystemUI/res/drawable/ic_fingerprint.xml
@@ -15,45 +15,25 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32dp"
- android:height="32dp"
+ android:width="72dp"
+ android:height="72dp"
android:tint="?attr/wallpaperTextColor"
- android:alpha=".75"
- android:viewportHeight="32.0"
- android:viewportWidth="32.0">
+ android:viewportWidth="72"
+ android:viewportHeight="72">
<path
- android:fillColor="#ffffff"
- android:pathData="M23.7,5.9c-0.1,0.0 -0.2,0.0 -0.3,-0.1C21.0,4.5 18.6,3.9 16.0,3.9c-2.5,0.0
- -4.6,0.6 -6.9,1.9C8.8,6.0 8.3,5.9 8.1,5.5C7.9,5.2 8.0,4.7 8.4,4.5c2.5,-1.4 4.9,-2.1 7.7,
- -2.1c2.8,0.0 5.4,0.7 8.0,2.1c0.4,0.2 0.5,0.6 0.3,1.0C24.2,5.7 24.0,5.9 23.7,5.9z" />
- <path
- android:fillColor="#ffffff"
- android:pathData="M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,
- -1.9 2.9,-3.4 4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8
- -0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0
- -12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z" />
- <path
- android:fillColor="#ffffff"
- android:pathData="M13.3,29.6c-0.2,0.0 -0.4,-0.1 -0.5,-0.2c-1.1,-1.2 -1.7,-2.0 -2.6,
- -3.6c-0.9,-1.7 -1.4,-3.7 -1.4,-5.9c0.0,-4.1 3.3,-7.4 7.4,-7.4c4.1,0.0 7.4,3.3 7.4,7.4c0.0,
- 0.4 -0.3,0.7 -0.7,0.7s-0.7,-0.3 -0.7,-0.7c0.0,-3.3 -2.7,-5.9 -5.9,-5.9c-3.3,0.0 -5.9,
- 2.7 -5.9,5.9c0.0,2.0 0.4,3.8 1.2,5.2c0.8,1.6 1.4,2.2 2.4,3.3c0.3,0.3 0.3,0.8 0.0,1.0
- C13.7,29.5 13.5,29.6 13.3,29.6z" />
- <path
- android:fillColor="#ffffff"
- android:pathData="M22.6,27.1c-1.6,0.0 -2.9,-0.4 -4.1,-1.2c-1.9,-1.4 -3.1,-3.6 -3.1,
- -6.0c0.0,-0.4 0.3,-0.7 0.7,-0.7s0.7,0.3 0.7,0.7c0.0,1.9 0.9,3.7 2.5,4.8c0.9,0.6 1.9,
- 1.0 3.2,1.0c0.3,0.0 0.8,0.0 1.3,-0.1c0.4,-0.1 0.8,0.2 0.8,0.6c0.1,0.4 -0.2,0.8 -0.6,
- 0.8C23.4,27.1 22.8,27.1 22.6,27.1z" />
- <path
- android:fillColor="#ffffff"
- android:pathData="M20.0,29.9c-0.1,0.0 -0.1,0.0 -0.2,0.0c-2.1,-0.6 -3.4,-1.4 -4.8,-2.9c-1.8,
- -1.9 -2.8,-4.4 -2.8,-7.1c0.0,-2.2 1.8,-4.1 4.1,-4.1c2.2,0.0 4.1,1.8 4.1,4.1c0.0,1.4 1.2,
- 2.6 2.6,2.6c1.4,0.0 2.6,-1.2 2.6,-2.6c0.0,-5.1 -4.2,-9.3 -9.3,-9.3c-3.6,0.0 -6.9,2.1 -8.4,
- 5.4C7.3,17.1 7.0,18.4 7.0,19.8c0.0,1.1 0.1,2.7 0.9,4.9c0.1,0.4 -0.1,0.8 -0.4,0.9c-0.4,
- 0.1 -0.8,-0.1 -0.9,-0.4c-0.6,-1.8 -0.9,-3.6 -0.9,-5.4c0.0,-1.6 0.3,-3.1 0.9,-4.4c1.7,
- -3.8 5.6,-6.3 9.8,-6.3c5.9,0.0 10.7,4.8 10.7,10.7c0.0,2.2 -1.8,4.1 -4.1,4.1s-4.0,
- -1.8 -4.0,-4.1c0.0,-1.4 -1.2,-2.6 -2.6,-2.6c-1.4,0.0 -2.6,1.2 -2.6,2.6c0.0,2.3 0.9,
- 4.5 2.4,6.1c1.2,1.3 2.4,2.0 4.2,2.5c0.4,0.1 0.6,0.5 0.5,0.9C20.6,29.7 20.3,29.9 20.0,
- 29.9z" />
+ android:pathData=
+ "M25.5,16.3283C28.47,14.8433 31.9167,14 35.5834,14C39.2501,14 42.6968,
+ 14.8433 45.6668,16.3283
+ M20,28.6669C22.7683,24.3402 28.7084,21.3335 35.5834,21.3335C42.4585,
+ 21.3335 48.3985,24.3402 51.1669,28.6669
+ M22.8607,47.0002C21.834,44.3235 21.834,41.5002 21.834,41.5002C21.834,
+ 34.4051 27.7374,28.6667 35.5841,28.6667C43.4308,28.6667 49.3341,34.4051 49.3341,41.5002
+ M49.3344,41.5003V42.0319C49.3344,44.7636 47.1161,47.0003 44.3661,47.0003C41.9461,
+ 47.0003 39.8744,45.2403 39.471,42.857L38.9577,39.7769C38.591,37.5953 36.7027,
+ 36.0002 34.5027,36.0002C26.5826,36.0002 29.846,49.1087 35.291,50.6487
+ M44.9713,54.6267C42.5513,56.7167 39.2879,58.0001 35.5846,58.0001C32.2296,
+ 58.0001 29.2229,56.9551 26.8945,55.195"
+ android:strokeWidth="3"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"/>
</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
index 7cb44b3..4165830 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
@@ -16,8 +16,5 @@
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
<solid android:color="?android:attr/colorBackgroundFloating"/>
- <corners
- android:topLeftRadius="?android:attr/dialogCornerRadius"
- android:topRightRadius="?android:attr/dialogCornerRadius" />
</shape>
</inset>
diff --git a/packages/SystemUI/res/layout/disabled_udfps_view.xml b/packages/SystemUI/res/layout/disabled_udfps_view.xml
index aab8661..13d3065 100644
--- a/packages/SystemUI/res/layout/disabled_udfps_view.xml
+++ b/packages/SystemUI/res/layout/disabled_udfps_view.xml
@@ -16,9 +16,7 @@
-->
<com.android.keyguard.DisabledUdfpsView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:id="@+id/disabled_udfps_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:background="@drawable/circle_white"
/>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1d82518..bd92299 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -610,6 +610,21 @@
<!-- Determines whether the shell features all run on another thread. -->
<bool name="config_enableShellMainThread">false</bool>
+ <!-- Default udfps icon. Same path as ic_fingerprint.xml -->
+ <string name="config_udfpsIcon" translatable="false">
+ M25.5,16.3283C28.47,14.8433 31.9167,14 35.5834,14C39.2501,14 42.6968,14.8433 45.6668,16.3283
+ M20,28.6669C22.7683,24.3402 28.7084,21.3335 35.5834,21.3335C42.4585,21.3335 48.3985,
+ 24.3402 51.1669,28.6669
+ M22.8607,47.0002C21.834,44.3235 21.834,41.5002 21.834,41.5002C21.834,
+ 34.4051 27.7374,28.6667 35.5841,28.6667C43.4308,28.6667 49.3341,34.4051 49.3341,41.5002
+ M49.3344,41.5003V42.0319C49.3344,44.7636 47.1161,47.0003 44.3661,47.0003C41.9461,
+ 47.0003 39.8744,45.2403 39.471,42.857L38.9577,
+ 39.7769C38.591,37.5953 36.7027,36.0002 34.5027,
+ 36.0002C26.5826,36.0002 29.846,49.1087 35.291,50.6487
+ M44.9713,54.6267C42.5513,56.7167 39.2879,58.0001 35.5846,58.0001C32.2296,
+ 58.0001 29.2229,56.9551 26.8945,55.195
+ </string>
+
<!-- package name of a built-in camera app to use to restrict implicit intent resolution
when the double-press power gesture is used. Ignored if empty. -->
<string translatable="false" name="config_cameraGesturePackage"></string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 91e0466..c1ac5e4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1091,7 +1091,7 @@
<!-- The maximum offset for the under-display fingerprint sensor (UDFPS) icon in either
direction that elements aer moved to prevent burn-in on AOD-->
- <dimen name="udfps_burn_in_offset_x">8dp</dimen>
+ <dimen name="udfps_burn_in_offset_x">2dp</dimen>
<dimen name="udfps_burn_in_offset_y">8dp</dimen>
<dimen name="corner_size">8dp</dimen>
@@ -1407,6 +1407,9 @@
<!-- rounded_slider_track_width / 2 -->
<dimen name="rounded_slider_track_corner_radius">4dp</dimen>
+ <!-- inset for ic_lock_open within a DisabledUdfpsView -->
+ <dimen name="udfps_unlock_icon_inset">16dp</dimen>
+
<!-- Location on the screen of the center of the physical power button. This is a reasonable
default that should be overridden by device-specific overlays. -->
<dimen name="physical_power_button_center_screen_location_y">620px</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
index 118f98d..ed465de0e 100644
--- a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
+++ b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
@@ -18,27 +18,31 @@
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
import android.hardware.biometrics.BiometricSourceType;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
+import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
+import com.android.systemui.R;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
- * Controls when to show the DisabledUdfpsView to unlock the device on the lockscreen.
- * If the device is not authenticated, the bouncer will show.
+ * Controls when to show the DisabledUdfpsView affordance (unlock icon or circle) on lock screen.
*
- * This tap target will only show when:
+ * This view only exists when:
* - User has UDFPS enrolled
* - UDFPS is currently unavailable see {@link KeyguardUpdateMonitor#shouldListenForUdfps}
*/
@@ -47,21 +51,26 @@
@NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@NonNull private final KeyguardViewController mKeyguardViewController;
@NonNull private final StatusBarStateController mStatusBarStateController;
+ @NonNull private final KeyguardStateController mKeyguardStateController;
+ @NonNull private final Drawable mButton;
+ @NonNull private final Drawable mUnlockIcon;
private boolean mIsDozing;
private boolean mIsBouncerShowing;
private boolean mIsKeyguardShowing;
private boolean mRunningFPS;
- private boolean mAuthenticated;
+ private boolean mCanDismissLockScreen;
private boolean mShowButton;
+ private boolean mShowUnlockIcon;
public DisabledUdfpsController(
@NonNull DisabledUdfpsView view,
@NonNull StatusBarStateController statusBarStateController,
@NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
@NonNull AuthController authController,
- @NonNull KeyguardViewController keyguardViewController
+ @NonNull KeyguardViewController keyguardViewController,
+ @NonNull KeyguardStateController keyguardStateController
) {
super(view);
mView.setOnClickListener(mOnClickListener);
@@ -70,25 +79,38 @@
mStatusBarStateController = statusBarStateController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardViewController = keyguardViewController;
+ mKeyguardStateController = keyguardStateController;
+
+ final Context context = view.getContext();
+ mButton = context.getResources().getDrawable(
+ com.android.systemui.R.drawable.circle_white, context.getTheme());
+ mUnlockIcon = new InsetDrawable(context.getResources().getDrawable(
+ com.android.internal.R.drawable.ic_lock_open, context.getTheme()),
+ context.getResources().getDimensionPixelSize(
+ com.android.systemui.R.dimen.udfps_unlock_icon_inset));
}
@Override
protected void onViewAttached() {
mIsBouncerShowing = mKeyguardViewController.isBouncerShowing();
- mIsKeyguardShowing = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
+ mIsKeyguardShowing = mKeyguardStateController.isShowing();
mIsDozing = mStatusBarStateController.isDozing();
mRunningFPS = mKeyguardUpdateMonitor.isFingerprintDetectionRunning();
- mAuthenticated = false;
- updateButtonVisibility();
+ mCanDismissLockScreen = mKeyguardStateController.canDismissLockScreen();
+ mUnlockIcon.setTint(Utils.getColorAttrDefaultColor(mView.getContext(),
+ R.attr.wallpaperTextColorAccent));
+ updateVisibility();
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
mStatusBarStateController.addCallback(mStatusBarStateListener);
+ mKeyguardStateController.addCallback(mKeyguardStateCallback);
}
@Override
protected void onViewDetached() {
mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
mStatusBarStateController.removeCallback(mStatusBarStateListener);
+ mKeyguardStateController.removeCallback(mKeyguardStateCallback);
}
/**
@@ -100,30 +122,41 @@
}
}
- private void updateButtonVisibility() {
- mShowButton = !mAuthenticated && !mIsDozing && mIsKeyguardShowing
- && !mIsBouncerShowing && !mRunningFPS;
+ private void updateVisibility() {
+ mShowButton = !mCanDismissLockScreen && !mRunningFPS && isLockScreen();
+ mShowUnlockIcon = mCanDismissLockScreen && isLockScreen();
+
if (mShowButton) {
+ mView.setImageDrawable(mButton);
+ mView.setVisibility(View.VISIBLE);
+ } else if (mShowUnlockIcon) {
+ mView.setImageDrawable(mUnlockIcon);
mView.setVisibility(View.VISIBLE);
} else {
mView.setVisibility(View.INVISIBLE);
}
}
+ private boolean isLockScreen() {
+ return mIsKeyguardShowing && !mIsDozing && !mIsBouncerShowing;
+ }
+
@Override
public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
pw.println("DisabledUdfpsController state:");
pw.println(" mShowBouncerButton: " + mShowButton);
+ pw.println(" mShowUnlockIcon: " + mShowUnlockIcon);
pw.println(" mIsDozing: " + mIsDozing);
pw.println(" mIsKeyguardShowing: " + mIsKeyguardShowing);
pw.println(" mIsBouncerShowing: " + mIsBouncerShowing);
pw.println(" mRunningFPS: " + mRunningFPS);
- pw.println(" mAuthenticated: " + mAuthenticated);
+ pw.println(" mCanDismissLockScreen: " + mCanDismissLockScreen);
}
private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
+ // if the device is locked, shows bouncer, else goes to launcher
mKeyguardViewController.showBouncer(/* scrim */ true);
}
};
@@ -131,15 +164,9 @@
private StatusBarStateController.StateListener mStatusBarStateListener =
new StatusBarStateController.StateListener() {
@Override
- public void onStateChanged(int newState) {
- mIsKeyguardShowing = newState == StatusBarState.KEYGUARD;
- updateButtonVisibility();
- }
-
- @Override
public void onDozingChanged(boolean isDozing) {
mIsDozing = isDozing;
- updateButtonVisibility();
+ updateVisibility();
}
};
@@ -148,7 +175,7 @@
@Override
public void onKeyguardBouncerChanged(boolean bouncer) {
mIsBouncerShowing = bouncer;
- updateButtonVisibility();
+ updateVisibility();
}
@Override
@@ -157,21 +184,29 @@
if (biometricSourceType == FINGERPRINT) {
mRunningFPS = running;
}
- mAuthenticated &= !mRunningFPS;
- updateButtonVisibility();
- }
- @Override
- public void onBiometricAuthenticated(int userId,
- BiometricSourceType biometricSourceType, boolean isStrongBiometric) {
- mAuthenticated = true;
- updateButtonVisibility();
- }
-
- @Override
- public void onUserUnlocked() {
- mAuthenticated = true;
- updateButtonVisibility();
+ updateVisibility();
}
};
+
+ private final KeyguardStateController.Callback mKeyguardStateCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onKeyguardShowingChanged() {
+ updateIsKeyguardShowing();
+ updateVisibility();
+ }
+
+ @Override
+ public void onUnlockedChanged() {
+ updateIsKeyguardShowing();
+ mCanDismissLockScreen = mKeyguardStateController.canDismissLockScreen();
+ updateVisibility();
+ }
+
+ private void updateIsKeyguardShowing() {
+ mIsKeyguardShowing = mKeyguardStateController.isShowing()
+ && !mKeyguardStateController.isKeyguardGoingAway();
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsView.java b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsView.java
index d8ab780..8ae753e 100644
--- a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsView.java
+++ b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsView.java
@@ -22,14 +22,13 @@
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.util.AttributeSet;
import android.view.Surface;
-import android.widget.Button;
import android.widget.FrameLayout;
+import android.widget.ImageView;
/**
- * A full screen view with an oval target where the UDFPS sensor is.
- * Controlled by {@link DisabledUdfpsController}.
+ * A view positioned in the area of the UDPFS sensor.
*/
-public class DisabledUdfpsView extends Button {
+public class DisabledUdfpsView extends ImageView {
@NonNull private final RectF mSensorRect;
@NonNull private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 27a2ac3..864563e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -427,6 +427,7 @@
public void onTrustChanged(boolean enabled, int userId, int flags) {
Assert.isMainThread();
mUserHasTrust.put(userId, enabled);
+ updateBiometricListeningState();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -627,6 +628,7 @@
}
// Don't send cancel if authentication succeeds
mFingerprintCancelSignal = null;
+ updateBiometricListeningState();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -810,6 +812,7 @@
}
// Don't send cancel if authentication succeeds
mFaceCancelSignal = null;
+ updateBiometricListeningState();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -2109,6 +2112,7 @@
boolean shouldListenForUdfps() {
return shouldListenForFingerprint()
&& !mBouncer
+ && !getUserCanSkipBouncer(getCurrentUser())
&& mStrongAuthTracker.hasUserAuthenticatedSinceBoot();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 078ec9f..29db04b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -45,6 +45,7 @@
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.biometrics.HbmTypes.HbmType;
import com.android.systemui.dagger.SysUISingleton;
@@ -88,6 +89,7 @@
@NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
@NonNull private final DumpManager mDumpManager;
@NonNull private final AuthRippleController mAuthRippleController;
+ @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
@@ -307,7 +309,8 @@
@NonNull StatusBar statusBar,
@NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager,
@NonNull DumpManager dumpManager,
- @NonNull AuthRippleController authRippleController) {
+ @NonNull AuthRippleController authRippleController,
+ @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor) {
mContext = context;
mInflater = inflater;
// The fingerprint manager is queried for UDFPS before this class is constructed, so the
@@ -320,6 +323,7 @@
mKeyguardViewManager = statusBarKeyguardViewManager;
mDumpManager = dumpManager;
mAuthRippleController = authRippleController;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
@@ -486,6 +490,8 @@
mStatusBarStateController,
mStatusBar,
mKeyguardViewManager,
+ mKeyguardUpdateMonitor,
+ mFgExecutor,
mDumpManager
);
case IUdfpsOverlayController.REASON_AUTH_BP:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDrawable.java
index 18f5416..55ed5aa 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDrawable.java
@@ -18,9 +18,13 @@
import android.content.Context;
import android.graphics.ColorFilter;
+import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.PathShape;
+import android.util.PathParser;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -32,15 +36,30 @@
* sensor area.
*/
public abstract class UdfpsDrawable extends Drawable {
- @NonNull protected final Context mContext;
- @NonNull protected final Drawable mFingerprintDrawable;
+ static final float DEFAULT_STROKE_WIDTH = 3f;
+
+ @NonNull final Context mContext;
+ @NonNull final ShapeDrawable mFingerprintDrawable;
+ private final Paint mPaint;
private boolean mIlluminationShowing;
int mAlpha = 255; // 0 - 255
public UdfpsDrawable(@NonNull Context context) {
mContext = context;
- mFingerprintDrawable = context.getResources().getDrawable(R.drawable.ic_fingerprint, null);
+ final String fpPath = context.getResources().getString(R.string.config_udfpsIcon);
+ mFingerprintDrawable = new ShapeDrawable(
+ new PathShape(PathParser.createPathFromPathData(fpPath), 72, 72));
mFingerprintDrawable.mutate();
+
+ mPaint = mFingerprintDrawable.getPaint();
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ setStrokeWidth(DEFAULT_STROKE_WIDTH);
+ }
+
+ void setStrokeWidth(float strokeWidth) {
+ mPaint.setStrokeWidth(strokeWidth);
+ invalidateSelf();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardDrawable.java
index 12c15a0..71ed3f8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardDrawable.java
@@ -18,6 +18,7 @@
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -27,6 +28,7 @@
import com.android.internal.graphics.ColorUtils;
import com.android.settingslib.Utils;
+import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.doze.DozeReceiver;
@@ -37,6 +39,7 @@
private static final String TAG = "UdfpsAnimationKeyguard";
private final int mAmbientDisplayColor;
+ static final float DEFAULT_AOD_STROKE_WIDTH = 1f;
@NonNull private final Context mContext;
private int mLockScreenColor;
@@ -48,22 +51,31 @@
private float mBurnInOffsetX;
private float mBurnInOffsetY;
+ private final ValueAnimator mHintAnimator = ValueAnimator.ofFloat(
+ UdfpsKeyguardDrawable.DEFAULT_STROKE_WIDTH,
+ .5f,
+ UdfpsKeyguardDrawable.DEFAULT_STROKE_WIDTH);
+
UdfpsKeyguardDrawable(@NonNull Context context) {
super(context);
mContext = context;
- // TODO: move burn-in to view
mMaxBurnInOffsetX = context.getResources()
.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
mMaxBurnInOffsetY = context.getResources()
.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
+ mHintAnimator.setDuration(2000);
+ mHintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mHintAnimator.addUpdateListener(anim -> setStrokeWidth((float) anim.getAnimatedValue()));
+
mLockScreenColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor);
mAmbientDisplayColor = Color.WHITE;
- updateAodPositionAndColor();
+
+ updateIcon();
}
- private void updateAodPositionAndColor() {
+ private void updateIcon() {
mBurnInOffsetX = MathUtils.lerp(0f,
getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
- mMaxBurnInOffsetX,
@@ -75,12 +87,14 @@
mFingerprintDrawable.setTint(ColorUtils.blendARGB(mLockScreenColor,
mAmbientDisplayColor, mInterpolatedDarkAmount));
+ setStrokeWidth(MathUtils.lerp(DEFAULT_STROKE_WIDTH, DEFAULT_AOD_STROKE_WIDTH,
+ mInterpolatedDarkAmount));
invalidateSelf();
}
@Override
public void dozeTimeTick() {
- updateAodPositionAndColor();
+ updateIcon();
}
@Override
@@ -88,17 +102,25 @@
if (isIlluminationShowing()) {
return;
}
+ canvas.save();
+ canvas.translate(mBurnInOffsetX, mBurnInOffsetY);
mFingerprintDrawable.draw(canvas);
+ canvas.restore();
+ }
+
+ void animateHint() {
+ mHintAnimator.start();
}
void onDozeAmountChanged(float linear, float eased) {
+ mHintAnimator.cancel();
mInterpolatedDarkAmount = eased;
- updateAodPositionAndColor();
+ updateIcon();
}
void setLockScreenColor(int color) {
if (mLockScreenColor == color) return;
mLockScreenColor = color;
- updateAodPositionAndColor();
+ updateIcon();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index e274843..4590182 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -85,7 +85,6 @@
@Override
public boolean dozeTimeTick() {
- // TODO: burnin
mFingerprintDrawable.dozeTimeTick();
return true;
}
@@ -100,13 +99,16 @@
void onDozeAmountChanged(float linear, float eased) {
mFingerprintDrawable.onDozeAmountChanged(linear, eased);
- invalidate();
+ }
+
+ void animateHint() {
+ mFingerprintDrawable.animateHint();
}
/**
* Animates in the bg protection circle behind the fp icon to highlight the icon.
*/
- void animateHighlightFp() {
+ void animateUdfpsBouncer() {
if (mBgProtection.getVisibility() == View.VISIBLE && mBgProtection.getAlpha() == 1f) {
// already fully highlighted, don't re-animate
return;
@@ -154,7 +156,7 @@
/**
* Animates out the bg protection circle behind the fp icon to unhighlight the icon.
*/
- void animateUnhighlightFp(@Nullable Runnable onEndAnimation) {
+ void animateAwayUdfpsBouncer(@Nullable Runnable onEndAnimation) {
if (mBgProtection.getVisibility() == View.GONE) {
// already hidden
return;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 1f652db..9d846fa 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -17,32 +17,53 @@
package com.android.systemui.biometrics;
import android.annotation.NonNull;
+import android.hardware.biometrics.BiometricSourceType;
+import androidx.annotation.Nullable;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.util.concurrency.DelayableExecutor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Class that coordinates non-HBM animations during keyguard authentication.
+ *
+ * Highlights the udfps icon when:
+ * - Face authentication has failed
+ * - Face authentication has been run for > 2 seconds
*/
public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<UdfpsKeyguardView> {
- @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
+ private static final long AFTER_FACE_AUTH_HINT_DELAY = 2000;
- private boolean mForceShow;
+ @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
+ @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @NonNull private final DelayableExecutor mExecutor;
+
+ @Nullable private Runnable mCancelRunnable;
+ private boolean mShowBouncer;
private boolean mQsExpanded;
+ private boolean mFaceDetectRunning;
+ private boolean mHintShown;
protected UdfpsKeyguardViewController(
@NonNull UdfpsKeyguardView view,
@NonNull StatusBarStateController statusBarStateController,
@NonNull StatusBar statusBar,
@NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
+ @NonNull DelayableExecutor mainDelayableExecutor,
@NonNull DumpManager dumpManager) {
super(view, statusBarStateController, statusBar, dumpManager);
mKeyguardViewManager = statusBarKeyguardViewManager;
+ mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mExecutor = mainDelayableExecutor;
}
@Override
@@ -53,6 +74,9 @@
@Override
protected void onViewAttached() {
super.onViewAttached();
+ mHintShown = false;
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
+ updateFaceDetectRunning(mKeyguardUpdateMonitor.isFaceDetectionRunning());
final float dozeAmount = mStatusBarStateController.getDozeAmount();
mStatusBarStateController.addCallback(mStateListener);
@@ -64,31 +88,40 @@
@Override
protected void onViewDetached() {
super.onViewDetached();
+ mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
+ mFaceDetectRunning = false;
+
mStatusBarStateController.removeCallback(mStateListener);
- mAlternateAuthInterceptor.resetForceShow();
+ mAlternateAuthInterceptor.hideAlternateAuthBouncer();
mKeyguardViewManager.setAlternateAuthInterceptor(null);
+
+ if (mCancelRunnable != null) {
+ mCancelRunnable.run();
+ mCancelRunnable = null;
+ }
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
super.dump(fd, pw, args);
- pw.println("mForceShow=" + mForceShow);
+ pw.println("mShowBouncer=" + mShowBouncer);
+ pw.println("mFaceDetectRunning=" + mFaceDetectRunning);
}
/**
- * Overrides non-force show logic in shouldPauseAuth to still auth.
+ * Overrides non-bouncer show logic in shouldPauseAuth to still auth.
*/
- private void forceShow(boolean forceShow) {
- if (mForceShow == forceShow) {
+ private void showBouncer(boolean forceShow) {
+ if (mShowBouncer == forceShow) {
return;
}
- mForceShow = forceShow;
+ mShowBouncer = forceShow;
updatePauseAuth();
- if (mForceShow) {
- mView.animateHighlightFp();
+ if (mShowBouncer) {
+ mView.animateUdfpsBouncer();
} else {
- mView.animateUnhighlightFp(() -> mKeyguardViewManager.cancelPostAuthActions());
+ mView.animateAwayUdfpsBouncer(() -> mKeyguardViewManager.cancelPostAuthActions());
}
}
@@ -98,7 +131,7 @@
* is expanded, so this can be overridden with the forceShow method.
*/
public boolean shouldPauseAuth() {
- if (mForceShow) {
+ if (mShowBouncer) {
return false;
}
@@ -109,12 +142,42 @@
return super.shouldPauseAuth();
}
+ private void cancelDelayedHint() {
+ if (mCancelRunnable != null) {
+ mCancelRunnable.run();
+ mCancelRunnable = null;
+ }
+ }
+
+ private void updateFaceDetectRunning(boolean running) {
+ if (mFaceDetectRunning == running) {
+ return;
+ }
+
+ // show udfps hint a few seconds after face auth started running
+ if (!mFaceDetectRunning && running && !mHintShown && mCancelRunnable == null) {
+ // Face detect started running, show udfps hint after a delay
+ mCancelRunnable = mExecutor.executeDelayed(() -> showHint(false),
+ AFTER_FACE_AUTH_HINT_DELAY);
+ }
+
+ mFaceDetectRunning = running;
+ }
+
+ private void showHint(boolean forceShow) {
+ cancelDelayedHint();
+ if (!mHintShown || forceShow) {
+ mHintShown = true;
+ mView.animateHint();
+ }
+ }
+
private final StatusBarStateController.StateListener mStateListener =
new StatusBarStateController.StateListener() {
@Override
public void onDozeAmountChanged(float linear, float eased) {
mView.onDozeAmountChanged(linear, eased);
- if (linear != 0) forceShow(false);
+ if (linear != 0) showBouncer(false);
}
@Override
@@ -123,31 +186,56 @@
}
};
+ private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
+ new KeyguardUpdateMonitorCallback() {
+ public void onBiometricRunningStateChanged(boolean running,
+ BiometricSourceType biometricSourceType) {
+ if (biometricSourceType == BiometricSourceType.FACE) {
+ updateFaceDetectRunning(running);
+ }
+ }
+
+ public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) {
+ if (biometricSourceType == BiometricSourceType.FACE) {
+ // show udfps hint when face auth fails
+ showHint(true);
+ }
+ }
+
+ public void onBiometricAuthenticated(int userId,
+ BiometricSourceType biometricSourceType, boolean isStrongBiometric) {
+ if (biometricSourceType == BiometricSourceType.FACE) {
+ // cancel delayed hint if face auth succeeded
+ cancelDelayedHint();
+ }
+ }
+ };
+
private final StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor =
new StatusBarKeyguardViewManager.AlternateAuthInterceptor() {
@Override
- public boolean showAlternativeAuthMethod() {
- if (mForceShow) {
+ public boolean showAlternateAuthBouncer() {
+ if (mShowBouncer) {
return false;
}
- forceShow(true);
+ showBouncer(true);
return true;
}
@Override
- public boolean resetForceShow() {
- if (!mForceShow) {
+ public boolean hideAlternateAuthBouncer() {
+ if (!mShowBouncer) {
return false;
}
- forceShow(false);
+ showBouncer(false);
return true;
}
@Override
- public boolean isShowingAlternateAuth() {
- return mForceShow;
+ public boolean isShowingAlternateAuthBouncer() {
+ return mShowBouncer;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
index 1c5715c..fd80d50 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java
@@ -59,6 +59,7 @@
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.telecom.TelecomManager;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.view.IWindowManager;
import android.view.ViewConfiguration;
@@ -328,6 +329,12 @@
@Provides
@Singleton
+ static SubscriptionManager provideSubcriptionManager(Context context) {
+ return context.getSystemService(SubscriptionManager.class);
+ }
+
+ @Provides
+ @Singleton
@Nullable
static TelecomManager provideTelecomManager(Context context) {
return context.getSystemService(TelecomManager.class);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
index 0d73a5a..5b986b6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
@@ -66,7 +66,7 @@
return getHost().getContext().getPackageManager().hasSystemFeature(FEATURE_CAMERA_TOGGLE)
&& whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
"camera_toggle_enabled",
- false));
+ true));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
index b8d8792..42bd77b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
@@ -67,7 +67,7 @@
.hasSystemFeature(FEATURE_MICROPHONE_TOGGLE)
&& whitelistIpcs(() -> DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY,
"mic_toggle_enabled",
- false));
+ true));
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index a38cf61..555df5c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3543,7 +3543,8 @@
mStatusBarStateController,
mUpdateMonitor,
mAuthController,
- mStatusBarKeyguardViewManager);
+ mStatusBarKeyguardViewManager,
+ mKeyguardStateController);
mDisabledUdfpsController.init();
} else if (mDisabledUdfpsController != null && !udfpsEnrolled) {
mDisabledUdfpsController.destroy();
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 0b6bbcd..ef2444e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -479,7 +479,7 @@
if (mAlternateAuthInterceptor != null) {
mAfterKeyguardGoneAction = r;
mKeyguardGoneCancelAction = cancelAction;
- if (mAlternateAuthInterceptor.showAlternativeAuthMethod()) {
+ if (mAlternateAuthInterceptor.showAlternateAuthBouncer()) {
mStatusBar.updateScrimController();
}
return;
@@ -529,7 +529,8 @@
* Stop showing any alternate auth methods
*/
public void resetAlternateAuth() {
- if (mAlternateAuthInterceptor != null && mAlternateAuthInterceptor.resetForceShow()) {
+ if (mAlternateAuthInterceptor != null
+ && mAlternateAuthInterceptor.hideAlternateAuthBouncer()) {
mStatusBar.updateScrimController();
}
}
@@ -1141,12 +1142,12 @@
public boolean isShowingAlternateAuth() {
return mAlternateAuthInterceptor != null
- && mAlternateAuthInterceptor.isShowingAlternateAuth();
+ && mAlternateAuthInterceptor.isShowingAlternateAuthBouncer();
}
public boolean isShowingAlternateAuthOrAnimating() {
return mAlternateAuthInterceptor != null
- && (mAlternateAuthInterceptor.isShowingAlternateAuth()
+ && (mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()
|| mAlternateAuthInterceptor.isAnimating());
}
@@ -1174,24 +1175,25 @@
/**
* Delegate used to send show/reset events to an alternate authentication method instead of the
- * bouncer.
+ * regular pin/pattern/password bouncer.
*/
public interface AlternateAuthInterceptor {
/**
- * @return whether alternative auth method was newly shown
+ * Show alternate authentication bouncer.
+ * @return whether alternate auth method was newly shown
*/
- boolean showAlternativeAuthMethod();
+ boolean showAlternateAuthBouncer();
/**
- * reset the state to the default (only keyguard showing, no auth methods showing)
- * @return whether alternative auth method was newly hidden
+ * Hide alternate authentication bouncer
+ * @return whether the alternate auth method was newly hidden
*/
- boolean resetForceShow();
+ boolean hideAlternateAuthBouncer();
/**
- * @return true if alternative auth method is showing
+ * @return true if the alternate auth bouncer is showing
*/
- boolean isShowingAlternateAuth();
+ boolean isShowingAlternateAuthBouncer();
/**
* print information for the alternate auth interceptor registered
@@ -1199,12 +1201,12 @@
void dump(PrintWriter pw);
/**
- * @return true if the new auth method is currently animating in or out.
+ * @return true if the new auth method bouncer is currently animating in or out.
*/
boolean isAnimating();
/**
- * Set whether qs is currently expanded
+ * Set whether qs is currently expanded.
*/
void setQsExpanded(boolean expanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
index b96cb5e..7ac6d63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java
@@ -21,6 +21,7 @@
import android.telephony.SubscriptionInfo;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
@@ -32,6 +33,8 @@
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+
/**
* Implements network listeners and forwards the calls along onto other listeners but on
@@ -60,12 +63,9 @@
private int mHistoryIndex;
private String mLastCallback;
- public CallbackHandler() {
- super(Looper.getMainLooper());
- }
-
+ @Inject
@VisibleForTesting
- CallbackHandler(Looper looper) {
+ CallbackHandler(@Main Looper looper) {
super(looper);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index cfaeb0e..f683603 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -85,6 +85,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -171,6 +172,8 @@
private NetworkCapabilities mLastDefaultNetworkCapabilities;
// Handler that all broadcasts are received on.
private final Handler mReceiverHandler;
+ private final Looper mBgLooper;
+ private final Executor mBgExecutor;
// Handler that all callbacks are made on.
private final CallbackHandler mCallbackHandler;
@@ -198,6 +201,9 @@
public NetworkControllerImpl(
Context context,
@Background Looper bgLooper,
+ @Background Executor bgExecutor,
+ SubscriptionManager subscriptionManager,
+ CallbackHandler callbackHandler,
DeviceProvisionedController deviceProvisionedController,
BroadcastDispatcher broadcastDispatcher,
ConnectivityManager connectivityManager,
@@ -212,8 +218,11 @@
telephonyListenerManager,
wifiManager,
networkScoreManager,
- SubscriptionManager.from(context), Config.readConfig(context), bgLooper,
- new CallbackHandler(),
+ subscriptionManager,
+ Config.readConfig(context),
+ bgLooper,
+ bgExecutor,
+ callbackHandler,
accessPointController,
new DataUsageController(context),
new SubscriptionDefaults(),
@@ -230,6 +239,7 @@
WifiManager wifiManager,
NetworkScoreManager networkScoreManager,
SubscriptionManager subManager, Config config, Looper bgLooper,
+ Executor bgExecutor,
CallbackHandler callbackHandler,
AccessPointControllerImpl accessPointController,
DataUsageController dataUsageController,
@@ -241,6 +251,8 @@
mTelephonyListenerManager = telephonyListenerManager;
mConfig = config;
mReceiverHandler = new Handler(bgLooper);
+ mBgLooper = bgLooper;
+ mBgExecutor = bgExecutor;
mCallbackHandler = callbackHandler;
mDataSaverController = new DataSaverControllerImpl(context);
mBroadcastDispatcher = broadcastDispatcher;
@@ -377,21 +389,23 @@
// TODO: Move off of the deprecated CONNECTIVITY_ACTION broadcast and rely on callbacks
// exclusively for status bar icons.
mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler);
- // Register the listener on our bg looper
+ // Run the listener on our bg looper
mPhoneStateListener = subId -> {
- // For data switching from A to B, we assume B is validated for up to 2 seconds iff:
- // 1) A and B are in the same subscription group e.g. CBRS data switch. And
- // 2) A was validated before the switch.
- // This is to provide smooth transition for UI without showing cross during data
- // switch.
- if (keepCellularValidationBitInSwitch(mActiveMobileDataSubscription, subId)) {
- if (DEBUG) Log.d(TAG, ": mForceCellularValidated to true.");
- mForceCellularValidated = true;
- mReceiverHandler.removeCallbacks(mClearForceValidated);
- mReceiverHandler.postDelayed(mClearForceValidated, 2000);
- }
- mActiveMobileDataSubscription = subId;
- doUpdateMobileControllers();
+ mBgExecutor.execute(() -> {
+ // For data switching from A to B, we assume B is validated for up to 2 seconds if:
+ // 1) A and B are in the same subscription group e.g. CBRS data switch. And
+ // 2) A was validated before the switch.
+ // This is to provide smooth transition for UI without showing cross during data
+ // switch.
+ if (keepCellularValidationBitInSwitch(mActiveMobileDataSubscription, subId)) {
+ if (DEBUG) Log.d(TAG, ": mForceCellularValidated to true.");
+ mForceCellularValidated = true;
+ mReceiverHandler.removeCallbacks(mClearForceValidated);
+ mReceiverHandler.postDelayed(mClearForceValidated, 2000);
+ }
+ mActiveMobileDataSubscription = subId;
+ doUpdateMobileControllers();
+ });
};
mDemoModeController.addCallback(this);
@@ -428,7 +442,7 @@
mobileSignalController.registerListener();
}
if (mSubscriptionListener == null) {
- mSubscriptionListener = new SubListener();
+ mSubscriptionListener = new SubListener(mBgLooper);
}
mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener);
@@ -1336,6 +1350,10 @@
}
private class SubListener extends OnSubscriptionsChangedListener {
+ SubListener(Looper looper) {
+ super(looper);
+ }
+
@Override
public void onSubscriptionsChanged() {
updateMobileControllers();
@@ -1346,10 +1364,5 @@
* Used to register listeners from the BG Looper, this way the PhoneStateListeners that
* get created will also run on the BG Looper.
*/
- private final Runnable mRegisterListeners = new Runnable() {
- @Override
- public void run() {
- registerListeners();
- }
- };
+ private final Runnable mRegisterListeners = () -> registerListeners();
}
diff --git a/packages/SystemUI/src/com/android/systemui/telephony/TelephonyCallback.java b/packages/SystemUI/src/com/android/systemui/telephony/TelephonyCallback.java
index 95216c5..728907f 100644
--- a/packages/SystemUI/src/com/android/systemui/telephony/TelephonyCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/telephony/TelephonyCallback.java
@@ -54,9 +54,11 @@
@Override
public void onActiveDataSubscriptionIdChanged(int subId) {
- mActiveDataSubscriptionIdListeners.forEach(listener -> {
- listener.onActiveDataSubscriptionIdChanged(subId);
- });
+ List<ActiveDataSubscriptionIdListener> listeners;
+ synchronized (mActiveDataSubscriptionIdListeners) {
+ listeners = new ArrayList<>(mActiveDataSubscriptionIdListeners);
+ }
+ listeners.forEach(listener -> listener.onActiveDataSubscriptionIdChanged(subId));
}
void addActiveDataSubscriptionIdListener(ActiveDataSubscriptionIdListener listener) {
@@ -69,9 +71,11 @@
@Override
public void onCallStateChanged(int state) {
- mCallStateListeners.forEach(listener -> {
- listener.onCallStateChanged(state);
- });
+ List<CallStateListener> listeners;
+ synchronized (mCallStateListeners) {
+ listeners = new ArrayList<>(mCallStateListeners);
+ }
+ listeners.forEach(listener -> listener.onCallStateChanged(state));
}
void addCallStateListener(CallStateListener listener) {
@@ -84,9 +88,11 @@
@Override
public void onServiceStateChanged(@NonNull ServiceState serviceState) {
- mServiceStateListeners.forEach(listener -> {
- listener.onServiceStateChanged(serviceState);
- });
+ List<ServiceStateListener> listeners;
+ synchronized (mServiceStateListeners) {
+ listeners = new ArrayList<>(mServiceStateListeners);
+ }
+ listeners.forEach(listener -> listener.onServiceStateChanged(serviceState));
}
void addServiceStateListener(ServiceStateListener listener) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 44c3b26..cfcb7bb 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -881,6 +881,36 @@
}
@Test
+ public void testShouldNotListenForUdfps_whenTrustEnabled() {
+ // GIVEN a "we should listen for udfps" state
+ setKeyguardBouncerVisibility(false /* isVisible */);
+ mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
+
+ // WHEN trust is enabled (ie: via smartlock)
+ mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */,
+ KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */);
+
+ // THEN we shouldn't listen for udfps
+ assertThat(mKeyguardUpdateMonitor.shouldListenForUdfps()).isEqualTo(false);
+ }
+
+ @Test
+ public void testShouldNotListenForUdfps_whenFaceAuthenticated() {
+ // GIVEN a "we should listen for udfps" state
+ setKeyguardBouncerVisibility(false /* isVisible */);
+ mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
+ when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
+
+ // WHEN face authenticated
+ mKeyguardUpdateMonitor.onFaceAuthenticated(
+ KeyguardUpdateMonitor.getCurrentUser(), false);
+
+ // THEN we shouldn't listen for udfps
+ assertThat(mKeyguardUpdateMonitor.shouldListenForUdfps()).isEqualTo(false);
+ }
+
+ @Test
public void testRequireUnlockForNfc_Broadcast() {
KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
mKeyguardUpdateMonitor.registerCallback(callback);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index d3694dd..beca965 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -43,6 +43,7 @@
import androidx.test.filters.SmallTest;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
@@ -100,6 +101,8 @@
@Mock
private AuthRippleController mAuthRippleController;
@Mock
+ private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
private IUdfpsOverlayControllerCallback mUdfpsOverlayControllerCallback;
private FakeExecutor mFgExecutor;
@@ -151,7 +154,8 @@
mStatusBar,
mStatusBarKeyguardViewManager,
mDumpManager,
- mAuthRippleController);
+ mAuthRippleController,
+ mKeyguardUpdateMonitor);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 4410992..879cdbfb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -27,12 +27,14 @@
import androidx.test.filters.SmallTest;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.util.concurrency.DelayableExecutor;
import org.junit.Before;
import org.junit.Test;
@@ -59,6 +61,10 @@
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock
private DumpManager mDumpManager;
+ @Mock
+ private DelayableExecutor mExecutor;
+ @Mock
+ private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private UdfpsKeyguardViewController mController;
@@ -82,6 +88,8 @@
mStatusBarStateController,
mStatusBar,
mStatusBarKeyguardViewManager,
+ mKeyguardUpdateMonitor,
+ mExecutor,
mDumpManager);
}
@@ -168,13 +176,13 @@
sendStatusBarStateChanged(StatusBarState.SHADE_LOCKED);
assertTrue(mController.shouldPauseAuth());
- mAltAuthInterceptor.showAlternativeAuthMethod(); // force show
+ mAltAuthInterceptor.showAlternateAuthBouncer(); // force show
assertFalse(mController.shouldPauseAuth());
- assertTrue(mAltAuthInterceptor.isShowingAlternateAuth());
+ assertTrue(mAltAuthInterceptor.isShowingAlternateAuthBouncer());
- mAltAuthInterceptor.resetForceShow(); // stop force show
+ mAltAuthInterceptor.hideAlternateAuthBouncer(); // stop force show
assertTrue(mController.shouldPauseAuth());
- assertFalse(mAltAuthInterceptor.isShowingAlternateAuth());
+ assertFalse(mAltAuthInterceptor.isShowingAlternateAuthBouncer());
}
@Test
@@ -184,13 +192,13 @@
captureStatusBarStateListeners();
captureAltAuthInterceptor();
- mAltAuthInterceptor.showAlternativeAuthMethod(); // alt auth force show
+ mAltAuthInterceptor.showAlternateAuthBouncer(); // alt auth force show
// WHEN view is detached
mController.onViewDetached();
// THEN alt auth state reports not showing
- assertFalse(mAltAuthInterceptor.isShowingAlternateAuth());
+ assertFalse(mAltAuthInterceptor.isShowingAlternateAuthBouncer());
}
private void sendStatusBarStateChanged(int statusBarState) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index ef33172..566c717 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -77,6 +77,8 @@
import com.android.systemui.statusbar.policy.NetworkController.MobileDataIndicators;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import com.android.systemui.telephony.TelephonyListenerManager;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.After;
import org.junit.Before;
@@ -123,6 +125,7 @@
protected DeviceProvisionedListener mUserCallback;
protected Instrumentation mInstrumentation;
protected DemoModeController mDemoModeController;
+ protected FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
protected int mSubId;
@@ -222,6 +225,7 @@
mMockSm,
mConfig,
TestableLooper.get(this).getLooper(),
+ mFakeExecutor,
mCallbackHandler,
mock(AccessPointControllerImpl.class),
mock(DataUsageController.class),
@@ -291,7 +295,8 @@
NetworkControllerImpl networkControllerNoMobile =
new NetworkControllerImpl(mContext, mMockCm, mMockTm, mTelephonyListenerManager,
mMockWm, mMockNsm, mMockSm,
- mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
+ mConfig, TestableLooper.get(this).getLooper(), mFakeExecutor,
+ mCallbackHandler,
mock(AccessPointControllerImpl.class),
mock(DataUsageController.class), mMockSubDefaults,
mock(DeviceProvisionedController.class), mMockBd, mDemoModeController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index f4ad819..6219faf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -108,7 +108,7 @@
mConfig.show4gForLte = true;
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
mTelephonyListenerManager, mMockWm,
- mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
+ mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
mock(AccessPointControllerImpl.class),
mock(DataUsageController.class), mMockSubDefaults,
mock(DeviceProvisionedController.class), mMockBd, mDemoModeController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 3c5cbb6..8d3e403 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -63,7 +63,7 @@
// Create a new NetworkController as this is currently handled in constructor.
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
mTelephonyListenerManager, mMockWm, mMockNsm, mMockSm, mConfig,
- Looper.getMainLooper(), mCallbackHandler,
+ Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
mDemoModeController);
@@ -83,7 +83,7 @@
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
mTelephonyListenerManager, mMockWm, mMockNsm, mMockSm, mConfig,
- Looper.getMainLooper(), mCallbackHandler,
+ Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
mDemoModeController);
@@ -151,7 +151,7 @@
// Create a new NetworkController as this is currently handled in constructor.
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm,
mTelephonyListenerManager, mMockWm, mMockNsm, mMockSm, mConfig,
- Looper.getMainLooper(), mCallbackHandler,
+ Looper.getMainLooper(), mFakeExecutor, mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
mDemoModeController);
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 483f67a..82538b6 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -637,6 +637,8 @@
return association;
}
}));
+
+ restartBleScan();
}
@Override
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index d66d82d1..ed579f2 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -40,7 +40,6 @@
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
-import android.net.vcn.VcnManager;
import android.net.vcn.VcnManager.VcnErrorCode;
import android.net.vcn.VcnManager.VcnStatusCode;
import android.net.vcn.VcnUnderlyingNetworkPolicy;
@@ -531,11 +530,12 @@
if (mVcns.containsKey(subscriptionGroup)) {
final Vcn vcn = mVcns.get(subscriptionGroup);
- final boolean isActive = vcn.isActive();
+ final int status = vcn.getStatus();
vcn.updateConfig(config);
+ // TODO(b/183174340): Remove this once opportunistic-safe-mode is supported
// Only notify VcnStatusCallbacks if this VCN was previously in Safe Mode
- if (!isActive) {
+ if (status == VCN_STATUS_CODE_SAFE_MODE) {
// TODO(b/181789060): invoke asynchronously after Vcn notifies through VcnCallback
notifyAllPermissionedStatusCallbacksLocked(
subscriptionGroup, VCN_STATUS_CODE_ACTIVE);
@@ -768,7 +768,7 @@
synchronized (mLock) {
final Vcn vcn = mVcns.get(subGrp);
if (vcn != null) {
- if (vcn.isActive()) {
+ if (vcn.getStatus() == VCN_STATUS_CODE_ACTIVE) {
isVcnManagedNetwork = true;
}
@@ -879,20 +879,23 @@
// now that callback is registered, send it the VCN's current status
final VcnConfig vcnConfig = mConfigs.get(subGroup);
final Vcn vcn = mVcns.get(subGroup);
- final int vcnStatus;
+ final int vcnStatus =
+ vcn == null ? VCN_STATUS_CODE_NOT_CONFIGURED : vcn.getStatus();
+ final int resultStatus;
if (vcnConfig == null || !isCallbackPermissioned(cbInfo, subGroup)) {
- vcnStatus = VcnManager.VCN_STATUS_CODE_NOT_CONFIGURED;
+ resultStatus = VCN_STATUS_CODE_NOT_CONFIGURED;
} else if (vcn == null) {
- vcnStatus = VcnManager.VCN_STATUS_CODE_INACTIVE;
- } else if (vcn.isActive()) {
- vcnStatus = VcnManager.VCN_STATUS_CODE_ACTIVE;
+ resultStatus = VCN_STATUS_CODE_INACTIVE;
+ } else if (vcnStatus == VCN_STATUS_CODE_ACTIVE
+ || vcnStatus == VCN_STATUS_CODE_SAFE_MODE) {
+ resultStatus = vcnStatus;
} else {
- // TODO(b/181789060): create Vcn.getStatus() and Log.WTF() for unknown status
- vcnStatus = VcnManager.VCN_STATUS_CODE_SAFE_MODE;
+ Slog.wtf(TAG, "Unknown VCN status: " + vcnStatus);
+ resultStatus = VCN_STATUS_CODE_NOT_CONFIGURED;
}
try {
- cbInfo.mCallback.onVcnStatusChanged(vcnStatus);
+ cbInfo.mCallback.onVcnStatusChanged(resultStatus);
} catch (RemoteException e) {
Slog.d(TAG, "VcnStatusCallback threw on VCN status change", e);
}
@@ -930,7 +933,7 @@
/** Called by a Vcn to signal that an error occurred. */
void onGatewayConnectionError(
- @NonNull int[] networkCapabilities,
+ @NonNull String gatewayConnectionName,
@VcnErrorCode int errorCode,
@Nullable String exceptionClass,
@Nullable String exceptionMessage);
@@ -959,7 +962,7 @@
@Override
public void onGatewayConnectionError(
- @NonNull int[] networkCapabilities,
+ @NonNull String gatewayConnectionName,
@VcnErrorCode int errorCode,
@Nullable String exceptionClass,
@Nullable String exceptionMessage) {
@@ -975,7 +978,7 @@
Binder.withCleanCallingIdentity(
() ->
cbInfo.mCallback.onGatewayConnectionError(
- networkCapabilities,
+ gatewayConnectionName,
errorCode,
exceptionClass,
exceptionMessage));
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index c360190..5c2fd26 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -279,7 +279,7 @@
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mHandler = new MessageHandler(injector.getMessageHandlerLooper());
mAuthenticatorCache = mInjector.getAccountAuthenticatorCache();
- mAuthenticatorCache.setListener(this, mHandler);
+ mAuthenticatorCache.setListener(this, null /* Handler */);
sThis.set(this);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index d513ba4..c1ab6cc 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -191,6 +191,15 @@
// calling startForeground() before we ANR + stop it.
static final int SERVICE_START_FOREGROUND_TIMEOUT = 10 * 1000 * Build.HW_TIMEOUT_MULTIPLIER;
+ // Foreground service types that always get immediate notification display,
+ // expressed in the same bitmask format that ServiceRecord.foregroundServiceType
+ // uses.
+ static final int FGS_IMMEDIATE_DISPLAY_MASK =
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
+ | ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL
+ | ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
+ | ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION;
+
final ActivityManagerService mAm;
// Maximum number of services that we allow to start in the background
@@ -2020,15 +2029,12 @@
}
// or is this an type of FGS that always shows immediately?
if (!showNow) {
- switch (r.foregroundServiceType) {
- case ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK:
- case ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL:
- case ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION:
- if (DEBUG_FOREGROUND_SERVICE) {
- Slog.d(TAG_SERVICE, "FGS " + r
- + " type gets immediate display");
- }
- showNow = true;
+ if ((r.foregroundServiceType & FGS_IMMEDIATE_DISPLAY_MASK) != 0) {
+ if (DEBUG_FOREGROUND_SERVICE) {
+ Slog.d(TAG_SERVICE, "FGS " + r
+ + " type gets immediate display");
+ }
+ showNow = true;
}
}
} else {
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 57de708..b103def 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -34,7 +34,7 @@
import android.app.GameManager;
import android.app.GameManager.GameMode;
import android.app.IGameManagerService;
-import android.compat.Compatibility;
+import android.app.compat.PackageOverride;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -61,13 +61,12 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.compat.CompatibilityChangeConfig;
+import com.android.internal.compat.CompatibilityOverrideConfig;
import com.android.internal.compat.IPlatformCompat;
import com.android.server.ServiceThread;
import com.android.server.SystemService;
import java.io.FileDescriptor;
-import java.util.HashSet;
import java.util.List;
/**
@@ -87,6 +86,10 @@
static final int REMOVE_SETTINGS = 2;
static final int POPULATE_GAME_MODE_SETTINGS = 3;
static final int WRITE_SETTINGS_DELAY = 10 * 1000; // 10 seconds
+ static final PackageOverride COMPAT_ENABLED = new PackageOverride.Builder().setEnabled(true)
+ .build();
+ static final PackageOverride COMPAT_DISABLED = new PackageOverride.Builder().setEnabled(false)
+ .build();
private final Context mContext;
private final Object mLock = new Object();
@@ -578,17 +581,14 @@
private void disableCompatScale(String packageName) {
final long uid = Binder.clearCallingIdentity();
try {
- final HashSet<Long> disabledSet = new HashSet<>();
- disabledSet.add(DOWNSCALED);
- final CompatibilityChangeConfig changeConfig = new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(new HashSet<>(), disabledSet));
- // TODO: switch to new API provided by aosp/1599153 once merged
+ final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>();
+ overrides.put(DOWNSCALED, COMPAT_DISABLED);
+ final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
+ overrides);
try {
- mPlatformCompat.setOverridesForTest(changeConfig, packageName);
- } catch (SecurityException e) {
- Slog.e(TAG, "Missing compat override permission", e);
+ mPlatformCompat.setOverridesOnReleaseBuilds(changeConfig, packageName);
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesForTest", e);
+ Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesOnReleaseBuilds", e);
}
} finally {
Binder.restoreCallingIdentity(uid);
@@ -598,25 +598,20 @@
private void enableCompatScale(String packageName, long scaleId) {
final long uid = Binder.clearCallingIdentity();
try {
- final HashSet<Long> disabledSet = new HashSet<>();
- final HashSet<Long> enabledSet = new HashSet<>();
- disabledSet.add(DOWNSCALE_50);
- disabledSet.add(DOWNSCALE_60);
- disabledSet.add(DOWNSCALE_70);
- disabledSet.add(DOWNSCALE_80);
- disabledSet.add(DOWNSCALE_90);
- disabledSet.remove(scaleId);
- enabledSet.add(DOWNSCALED);
- enabledSet.add(scaleId);
- final CompatibilityChangeConfig changeConfig = new CompatibilityChangeConfig(
- new Compatibility.ChangeConfig(enabledSet, disabledSet));
- // TODO: switch to new API provided by aosp/1599153 once merged
+ final ArrayMap<Long, PackageOverride> overrides = new ArrayMap<>();
+ overrides.put(DOWNSCALED, COMPAT_ENABLED);
+ overrides.put(DOWNSCALE_50, COMPAT_DISABLED);
+ overrides.put(DOWNSCALE_60, COMPAT_DISABLED);
+ overrides.put(DOWNSCALE_70, COMPAT_DISABLED);
+ overrides.put(DOWNSCALE_80, COMPAT_DISABLED);
+ overrides.put(DOWNSCALE_90, COMPAT_DISABLED);
+ overrides.put(scaleId, COMPAT_ENABLED);
+ final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
+ overrides);
try {
- mPlatformCompat.setOverridesForTest(changeConfig, packageName);
- } catch (SecurityException e) {
- Slog.e(TAG, "Missing compat override permission", e);
+ mPlatformCompat.setOverridesOnReleaseBuilds(changeConfig, packageName);
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesForTest", e);
+ Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesOnReleaseBuilds", e);
}
} finally {
Binder.restoreCallingIdentity(uid);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 16a9626..2de2fdf 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -128,6 +128,7 @@
import android.os.UserManager;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.os.VibratorManager;
import android.provider.Settings;
import android.provider.Settings.System;
import android.service.notification.ZenModeConfig;
@@ -1092,6 +1093,33 @@
}
}
+ private void updateVibratorInfos() {
+ VibratorManager vibratorManager = mContext.getSystemService(VibratorManager.class);
+ if (vibratorManager == null) {
+ Slog.e(TAG, "Vibrator manager is not found");
+ return;
+ }
+ int[] vibratorIds = vibratorManager.getVibratorIds();
+ if (vibratorIds.length == 0) {
+ Slog.d(TAG, "No vibrator found");
+ return;
+ }
+ List<Vibrator> vibrators = new ArrayList<>(vibratorIds.length);
+ for (int id : vibratorIds) {
+ Vibrator vibrator = vibratorManager.getVibrator(id);
+ if (vibrator != null) {
+ vibrators.add(vibrator);
+ } else {
+ Slog.w(TAG, "Vibrator(" + id + ") is not found");
+ }
+ }
+ if (vibrators.isEmpty()) {
+ Slog.w(TAG, "Cannot find any available vibrator");
+ return;
+ }
+ AudioSystem.setVibratorInfos(vibrators);
+ }
+
public void onSystemReady() {
mSystemReady = true;
scheduleLoadSoundEffects();
@@ -1149,6 +1177,8 @@
setMicMuteFromSwitchInput();
initMinStreamVolumeWithoutModifyAudioSettings();
+
+ updateVibratorInfos();
}
RoleObserver mRoleObserver;
@@ -1231,7 +1261,7 @@
// Restore call state
synchronized (mDeviceBroker.mSetModeLock) {
onUpdateAudioMode(AudioSystem.MODE_CURRENT, android.os.Process.myPid(),
- mContext.getPackageName());
+ mContext.getPackageName(), true /*force*/);
}
final int forSys;
synchronized (mSettingsLock) {
@@ -1341,6 +1371,9 @@
setMicrophoneMuteNoCallerCheck(getCurrentUserId()); // will also update the mic mute cache
setMicMuteFromSwitchInput();
+
+ // Restore vibrator info
+ updateVibratorInfos();
}
private void onReinitVolumes(@NonNull String caller) {
@@ -4614,7 +4647,8 @@
}
@GuardedBy("mDeviceBroker.mSetModeLock")
- void onUpdateAudioMode(int requestedMode, int requesterPid, String requesterPackage) {
+ void onUpdateAudioMode(int requestedMode, int requesterPid, String requesterPackage,
+ boolean force) {
if (requestedMode == AudioSystem.MODE_CURRENT) {
requestedMode = getMode();
}
@@ -4631,7 +4665,7 @@
Log.v(TAG, "onUpdateAudioMode() new mode: " + mode + ", current mode: "
+ mMode.get() + " requested mode: " + requestedMode);
}
- if (mode != mMode.get()) {
+ if (mode != mMode.get() || force) {
final long identity = Binder.clearCallingIdentity();
int status = mAudioSystem.setPhoneState(mode, uid);
Binder.restoreCallingIdentity(identity);
@@ -7402,8 +7436,8 @@
h.setPlaybackActive(mPlaybackMonitor.isPlaybackActiveForUid(h.getUid()));
h.setRecordingActive(mRecordMonitor.isRecordingActiveForUid(h.getUid()));
if (wasActive != h.isActive()) {
- onUpdateAudioMode(AudioSystem.MODE_CURRENT,
- android.os.Process.myPid(), mContext.getPackageName());
+ onUpdateAudioMode(AudioSystem.MODE_CURRENT, android.os.Process.myPid(),
+ mContext.getPackageName(), false /*force*/);
}
}
break;
@@ -7428,7 +7462,7 @@
case MSG_UPDATE_AUDIO_MODE:
synchronized (mDeviceBroker.mSetModeLock) {
- onUpdateAudioMode(msg.arg1, msg.arg2, (String) msg.obj);
+ onUpdateAudioMode(msg.arg1, msg.arg2, (String) msg.obj, false /*force*/);
}
break;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 972071c..24e867a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -52,7 +52,6 @@
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
-import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.InvalidationRequesterClient;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.PerformanceTracker;
@@ -153,7 +152,10 @@
prop.commonProps.maxEnrollmentsPerUser,
componentInfo,
prop.sensorType,
- true /* resetLockoutRequiresHardwareAuthToken */);
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ prop.sensorLocations[0].sensorLocationX,
+ prop.sensorLocations[0].sensorLocationY,
+ prop.sensorLocations[0].sensorRadius);
final Sensor sensor = new Sensor(getTag() + "/" + sensorId, this, mContext, mHandler,
internalProp, gestureAvailabilityDispatcher);
@@ -388,7 +390,7 @@
public void scheduleRemove(int sensorId, @NonNull IBinder token,
@NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,
@NonNull String opPackageName) {
- scheduleRemoveSpecifiedIds(sensorId, token, new int[] {fingerId}, userId, receiver,
+ scheduleRemoveSpecifiedIds(sensorId, token, new int[]{fingerId}, userId, receiver,
opPackageName);
}
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
index 069c5c3..ab9de77 100644
--- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
+++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
@@ -118,7 +118,7 @@
if (!mIsQuitting) {
mRouteSelectionCallback = new RouteSelectionCallback();
mConnectivityManager.requestBackgroundNetwork(
- getBaseNetworkRequestBuilder().build(), mHandler, mRouteSelectionCallback);
+ getRouteSelectionRequest(), mHandler, mRouteSelectionCallback);
mWifiBringupCallback = new NetworkBringupCallback();
mConnectivityManager.requestBackgroundNetwork(
@@ -149,12 +149,48 @@
}
}
- private NetworkRequest getWifiNetworkRequest() {
+ /**
+ * Builds the Route selection request
+ *
+ * <p>This request is guaranteed to select carrier-owned, non-VCN underlying networks by virtue
+ * of a populated set of subIds as expressed in NetworkCapabilities#getSubIds(). Only carrier
+ * owned networks may be selected, as the request specifies only subIds in the VCN's
+ * subscription group, while the VCN networks are excluded by virtue of not having subIds set on
+ * the VCN-exposed networks.
+ */
+ private NetworkRequest getRouteSelectionRequest() {
return getBaseNetworkRequestBuilder()
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
.build();
}
+ /**
+ * Builds the WiFi bringup request
+ *
+ * <p>This request is built specifically to match only carrier-owned WiFi networks, but is also
+ * built to ONLY keep Carrier WiFi Networks alive (but never bring them up). This is a result of
+ * the WifiNetworkFactory not advertising a list of subIds, and therefore not accepting this
+ * request. As such, it will bind to a Carrier WiFi Network that has already been brought up,
+ * but will NEVER bring up a Carrier WiFi network itself.
+ */
+ private NetworkRequest getWifiNetworkRequest() {
+ return getBaseNetworkRequestBuilder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
+ .build();
+ }
+
+ /**
+ * Builds a Cellular bringup request for a given subId
+ *
+ * <p>This request is filed in order to ensure that the Telephony stack always has a
+ * NetworkRequest to bring up a VCN underlying cellular network. It is required in order to
+ * ensure that even when a VCN (appears as Cellular) satisfies the default request, Telephony
+ * will bring up additional underlying Cellular networks.
+ *
+ * <p>Since this request MUST make it to the TelephonyNetworkFactory, subIds are not specified
+ * in the NetworkCapabilities, but rather in the TelephonyNetworkSpecifier.
+ */
private NetworkRequest getCellNetworkRequestForSubId(int subId) {
return getBaseNetworkRequestBuilder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
@@ -164,20 +200,13 @@
/**
* Builds and returns a NetworkRequest builder common to all Underlying Network requests
- *
- * <p>This request is guaranteed to select carrier-owned, non-VCN underlying networks by virtue
- * of a populated set of subIds as expressed in NetworkCapabilities#getSubIds(). Only carrier
- * owned networks may be selected, as the request specifies only subIds in the VCN's
- * subscription group, while the VCN networks are excluded by virtue of not having subIds set on
- * the VCN-exposed networks.
*/
private NetworkRequest.Builder getBaseNetworkRequestBuilder() {
return new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
- .setSubIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup));
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
}
/**
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 89ed956..546893588 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -17,6 +17,9 @@
package com.android.server.vcn;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
import static com.android.server.VcnManagementService.VDBG;
@@ -44,7 +47,6 @@
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
/**
* Represents an single instance of a VCN.
@@ -137,17 +139,14 @@
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
/**
- * Whether this Vcn instance is active and running.
+ * The current status of this Vcn instance
*
- * <p>The value will be {@code true} while running. It will be {@code false} if the VCN has been
- * shut down or has entered safe mode.
- *
- * <p>This AtomicBoolean is required in order to ensure consistency and correctness across
- * multiple threads. Unlike the rest of the Vcn, this is queried synchronously on Binder threads
- * from VcnManagementService, and therefore cannot rely on guarantees of running on the VCN
- * Looper.
+ * <p>The value will be {@link VCN_STATUS_CODE_ACTIVE} while all VcnGatewayConnections are in
+ * good standing, {@link VCN_STATUS_CODE_SAFE_MODE} if any VcnGatewayConnections are in safe
+ * mode, and {@link VCN_STATUS_CODE_INACTIVE} once a teardown has been commanded.
*/
- private final AtomicBoolean mIsActive = new AtomicBoolean(true);
+ // Accessed from different threads, but always under lock in VcnManagementService
+ private volatile int mCurrentStatus = VCN_STATUS_CODE_ACTIVE;
public Vcn(
@NonNull VcnContext vcnContext,
@@ -199,9 +198,15 @@
sendMessageAtFrontOfQueue(obtainMessage(MSG_CMD_TEARDOWN));
}
- /** Synchronously checks whether this Vcn is active. */
- public boolean isActive() {
- return mIsActive.get();
+ /** Synchronously retrieves the current status code. */
+ public int getStatus() {
+ return mCurrentStatus;
+ }
+
+ /** Sets the status of this VCN */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public void setStatus(int status) {
+ mCurrentStatus = status;
}
/** Get current Gateways for testing purposes */
@@ -217,12 +222,6 @@
return Collections.unmodifiableMap(new HashMap<>(mVcnGatewayConnections));
}
- /** Set whether this Vcn is active for testing purposes */
- @VisibleForTesting(visibility = Visibility.PRIVATE)
- public void setIsActive(boolean isActive) {
- mIsActive.set(isActive);
- }
-
private class VcnNetworkRequestListener implements VcnNetworkProvider.NetworkRequestListener {
@Override
public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {
@@ -264,7 +263,8 @@
mConfig = config;
- if (mIsActive.getAndSet(true)) {
+ // TODO(b/183174340): Remove this once opportunistic safe mode is supported.
+ if (mCurrentStatus == VCN_STATUS_CODE_ACTIVE) {
// VCN is already active - teardown any GatewayConnections whose configs have been
// removed and get all current requests
for (final Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry :
@@ -288,11 +288,15 @@
// Trigger a re-evaluation of all NetworkRequests (to make sure any that can be
// satisfied start a new GatewayConnection)
mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
- } else {
+ } else if (mCurrentStatus == VCN_STATUS_CODE_SAFE_MODE) {
// If this VCN was not previously active, it is exiting Safe Mode. Re-register the
// request listener to get NetworkRequests again (and all cached requests).
mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener);
+ } else {
+ // Ignored; VCN was not active; config updates ignored.
+ return;
}
+ mCurrentStatus = VCN_STATUS_CODE_ACTIVE;
}
private void handleTeardown() {
@@ -302,18 +306,20 @@
gatewayConnection.teardownAsynchronously();
}
- mIsActive.set(false);
+ mCurrentStatus = VCN_STATUS_CODE_INACTIVE;
}
private void handleEnterSafeMode() {
+ // TODO(b/183174340): Remove this once opportunistic-safe-mode is supported
handleTeardown();
+ mCurrentStatus = VCN_STATUS_CODE_SAFE_MODE;
mVcnCallback.onEnteredSafeMode();
}
private void handleNetworkRequested(
@NonNull NetworkRequest request, int score, int providerId) {
- if (!isActive()) {
+ if (mCurrentStatus != VCN_STATUS_CODE_ACTIVE) {
Slog.v(getLogTag(), "Received NetworkRequest while inactive. Ignore for now");
return;
}
@@ -370,8 +376,8 @@
mVcnGatewayConnections.remove(config);
// Trigger a re-evaluation of all NetworkRequests (to make sure any that can be satisfied
- // start a new GatewayConnection), but only if the Vcn is still active
- if (isActive()) {
+ // start a new GatewayConnection), but only if the Vcn is still alive
+ if (mCurrentStatus == VCN_STATUS_CODE_ACTIVE) {
mVcnContext.getVcnNetworkProvider().resendAllRequests(mRequestListener);
}
}
@@ -379,7 +385,7 @@
private void handleSubscriptionsChanged(@NonNull TelephonySubscriptionSnapshot snapshot) {
mLastSnapshot = snapshot;
- if (isActive()) {
+ if (mCurrentStatus == VCN_STATUS_CODE_ACTIVE) {
for (VcnGatewayConnection gatewayConnection : mVcnGatewayConnections.values()) {
gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot);
}
@@ -417,7 +423,7 @@
/** Callback by a VcnGatewayConnection to indicate that an error occurred. */
void onGatewayConnectionError(
- @NonNull int[] networkCapabilities,
+ @NonNull String gatewayConnectionName,
@VcnErrorCode int errorCode,
@Nullable String exceptionClass,
@Nullable String exceptionMessage);
@@ -445,12 +451,12 @@
@Override
public void onGatewayConnectionError(
- @NonNull int[] networkCapabilities,
+ @NonNull String gatewayConnectionName,
@VcnErrorCode int errorCode,
@Nullable String exceptionClass,
@Nullable String exceptionMessage) {
mVcnCallback.onGatewayConnectionError(
- networkCapabilities, errorCode, exceptionClass, exceptionMessage);
+ gatewayConnectionName, errorCode, exceptionClass, exceptionMessage);
}
}
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 9589505..2ba8edd 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -980,7 +980,7 @@
// IkeSessionCallback.onClosedExceptionally(), which calls sessionClosed()
if (exception != null) {
mGatewayStatusCallback.onGatewayConnectionError(
- mConnectionConfig.getExposedCapabilities(),
+ mConnectionConfig.getGatewayConnectionName(),
VCN_ERROR_CODE_INTERNAL_ERROR,
RuntimeException.class.getName(),
"Received "
@@ -1017,7 +1017,7 @@
}
mGatewayStatusCallback.onGatewayConnectionError(
- mConnectionConfig.getExposedCapabilities(),
+ mConnectionConfig.getGatewayConnectionName(),
errorCode,
exceptionClass,
exceptionMessage);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index a9d33dc..c9af62b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3750,6 +3750,10 @@
@VisibleForTesting
void setImeInputTarget(WindowState target) {
mImeInputTarget = target;
+ boolean canScreenshot = mImeInputTarget == null || !mImeInputTarget.isSecureLocked();
+ if (mImeWindowsContainer.setCanScreenshot(canScreenshot)) {
+ mWmService.requestTraversal();
+ }
}
@VisibleForTesting
@@ -3867,7 +3871,7 @@
void updateImeInputAndControlTarget(WindowState target) {
if (mImeInputTarget != target) {
ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
- mImeInputTarget = target;
+ setImeInputTarget(target);
updateImeControlTarget();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a5843d4..070a725 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3321,4 +3321,12 @@
@WindowManager.LayoutParams.WindowType int getWindowType() {
return INVALID_WINDOW_TYPE;
}
+
+ boolean setCanScreenshot(boolean canScreenshot) {
+ if (mSurfaceControl == null) {
+ return false;
+ }
+ getPendingTransaction().setSecure(mSurfaceControl, !canScreenshot);
+ return true;
+ }
}
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp
index 9456946..646aabd 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.cpp
+++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp
@@ -302,6 +302,10 @@
SET(Cn0DbHz, measurement.antennaCN0DbHz);
SET(ConstellationType, static_cast<int32_t>(measurement.signalType.constellation));
+ // Half cycle state is reported in the AIDL version of GnssMeasurement
+ SET(AccumulatedDeltaRangeState,
+ (static_cast<int32_t>(measurement.accumulatedDeltaRangeState) |
+ ADR_STATE_HALF_CYCLE_REPORTED));
if (measurement.flags & static_cast<uint32_t>(GnssMeasurement::HAS_CARRIER_FREQUENCY)) {
SET(CarrierFrequencyHz, static_cast<float>(measurement.signalType.carrierFrequencyHz));
@@ -481,7 +485,7 @@
JavaObject& object) {
translateSingleGnssMeasurement(measurement_V1_1.v1_0, object);
- // Set the V1_1 flag, and mark that new field has valid information for Java Layer
+ // Half cycle state is reported in HIDL v1.1 or newer.
SET(AccumulatedDeltaRangeState,
(static_cast<int32_t>(measurement_V1_1.accumulatedDeltaRangeState) |
ADR_STATE_HALF_CYCLE_REPORTED));
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 7c30b45..d1cd7cd 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -92,6 +92,8 @@
<uses-permission android:name="android.permission.CONTROL_DEVICE_STATE"/>
<uses-permission android:name="android.permission.READ_PROJECTION_STATE"/>
<uses-permission android:name="android.permission.KILL_UID"/>
+ <uses-permission
+ android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"/>
<!-- Uses API introduced in O (26) -->
<uses-sdk android:minSdkVersion="1"
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
index 94cc666..35c37ef 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.hardware.biometrics.common.CommonProps;
import android.hardware.biometrics.fingerprint.IFingerprint;
+import android.hardware.biometrics.fingerprint.SensorLocation;
import android.hardware.biometrics.fingerprint.SensorProps;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
@@ -33,7 +34,6 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
-import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
@@ -77,9 +77,11 @@
final SensorProps sensor1 = new SensorProps();
sensor1.commonProps = new CommonProps();
sensor1.commonProps.sensorId = 0;
+ sensor1.sensorLocations = new SensorLocation[] {new SensorLocation()};
final SensorProps sensor2 = new SensorProps();
sensor2.commonProps = new CommonProps();
sensor2.commonProps.sensorId = 1;
+ sensor2.sensorLocations = new SensorLocation[] {new SensorLocation()};
mSensorProps = new SensorProps[] {sensor1, sensor2};
diff --git a/tests/vcn/java/android/net/vcn/VcnConfigTest.java b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
index c1ef350..7ac51b7 100644
--- a/tests/vcn/java/android/net/vcn/VcnConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
@@ -79,6 +79,18 @@
}
@Test
+ public void testBuilderRequiresUniqueGatewayConnectionNames() {
+ final VcnGatewayConnectionConfig config = VcnGatewayConnectionConfigTest.buildTestConfig();
+ try {
+ new VcnConfig.Builder(mContext)
+ .addGatewayConnectionConfig(config)
+ .addGatewayConnectionConfig(config);
+ fail("Expected exception due to duplicate gateway connection name");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
public void testBuilderAndGetters() {
final VcnConfig config = buildTestConfig(mContext);
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index 8a0c923..4ee4d61 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.net.NetworkCapabilities;
@@ -61,13 +62,20 @@
public static final VcnControlPlaneConfig CONTROL_PLANE_CONFIG =
VcnControlPlaneIkeConfigTest.buildTestConfig();
+ public static final String GATEWAY_CONNECTION_NAME_PREFIX = "gatewayConnectionName-";
+ private static int sGatewayConnectionConfigCount = 0;
+
// Public for use in VcnGatewayConnectionTest
public static VcnGatewayConnectionConfig buildTestConfig() {
return buildTestConfigWithExposedCaps(EXPOSED_CAPS);
}
private static VcnGatewayConnectionConfig.Builder newBuilder() {
- return new VcnGatewayConnectionConfig.Builder(CONTROL_PLANE_CONFIG);
+ // Append a unique identifier to the name prefix to guarantee that all created
+ // VcnGatewayConnectionConfigs have a unique name (required by VcnConfig).
+ return new VcnGatewayConnectionConfig.Builder(
+ GATEWAY_CONNECTION_NAME_PREFIX + sGatewayConnectionConfigCount++,
+ CONTROL_PLANE_CONFIG);
}
// Public for use in VcnGatewayConnectionTest
@@ -87,9 +95,23 @@
}
@Test
+ public void testBuilderRequiresNonNullGatewayConnectionName() {
+ try {
+ new VcnGatewayConnectionConfig.Builder(
+ null /* gatewayConnectionName */, CONTROL_PLANE_CONFIG)
+ .build();
+
+ fail("Expected exception due to invalid gateway connection name");
+ } catch (NullPointerException e) {
+ }
+ }
+
+ @Test
public void testBuilderRequiresNonNullControlPlaneConfig() {
try {
- new VcnGatewayConnectionConfig.Builder(null).build();
+ new VcnGatewayConnectionConfig.Builder(
+ GATEWAY_CONNECTION_NAME_PREFIX, null /* ctrlPlaneConfig */)
+ .build();
fail("Expected exception due to invalid control plane config");
} catch (NullPointerException e) {
@@ -139,6 +161,8 @@
public void testBuilderAndGetters() {
final VcnGatewayConnectionConfig config = buildTestConfig();
+ assertTrue(config.getGatewayConnectionName().startsWith(GATEWAY_CONNECTION_NAME_PREFIX));
+
int[] exposedCaps = config.getExposedCapabilities();
Arrays.sort(exposedCaps);
assertArrayEquals(EXPOSED_CAPS, exposedCaps);
diff --git a/tests/vcn/java/android/net/vcn/VcnManagerTest.java b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
index 516c206..8461de6 100644
--- a/tests/vcn/java/android/net/vcn/VcnManagerTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
@@ -50,9 +50,7 @@
public class VcnManagerTest {
private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
- private static final int[] UNDERLYING_NETWORK_CAPABILITIES = {
- NetworkCapabilities.NET_CAPABILITY_IMS, NetworkCapabilities.NET_CAPABILITY_INTERNET
- };
+ private static final String GATEWAY_CONNECTION_NAME = "gatewayConnectionName";
private static final Executor INLINE_EXECUTOR = Runnable::run;
private IVcnManagementService mMockVcnManagementService;
@@ -207,13 +205,13 @@
verify(mMockStatusCallback).onStatusChanged(VCN_STATUS_CODE_ACTIVE);
cbBinder.onGatewayConnectionError(
- UNDERLYING_NETWORK_CAPABILITIES,
+ GATEWAY_CONNECTION_NAME,
VcnManager.VCN_ERROR_CODE_NETWORK_ERROR,
UnknownHostException.class.getName(),
"exception_message");
verify(mMockStatusCallback)
.onGatewayConnectionError(
- eq(UNDERLYING_NETWORK_CAPABILITIES),
+ eq(GATEWAY_CONNECTION_NAME),
eq(VcnManager.VCN_ERROR_CODE_NETWORK_ERROR),
any(UnknownHostException.class));
}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index c88b0c1..4ad7136 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -19,6 +19,8 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
import static android.telephony.TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
@@ -695,7 +697,9 @@
hasCarrierPrivileges);
final Vcn vcn = startAndGetVcnInstance(subGrp);
- doReturn(isVcnActive).when(vcn).isActive();
+ doReturn(isVcnActive ? VCN_STATUS_CODE_ACTIVE : VCN_STATUS_CODE_SAFE_MODE)
+ .when(vcn)
+ .getStatus();
doReturn(true)
.when(mLocationPermissionChecker)
diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
index ed2e4d9..b592000 100644
--- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
@@ -158,7 +158,7 @@
for (final int subId : expectedSubIds) {
verify(mConnectivityManager)
.requestBackgroundNetwork(
- eq(getCellRequestForSubId(subId, expectedSubIds)),
+ eq(getCellRequestForSubId(subId)),
any(),
any(NetworkBringupCallback.class));
}
@@ -189,30 +189,30 @@
}
private NetworkRequest getWifiRequest(Set<Integer> netCapsSubIds) {
- return getExpectedRequestBase(netCapsSubIds)
+ return getExpectedRequestBase()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubIds(netCapsSubIds)
.build();
}
- private NetworkRequest getCellRequestForSubId(int subId, Set<Integer> netCapsSubIds) {
- return getExpectedRequestBase(netCapsSubIds)
+ private NetworkRequest getCellRequestForSubId(int subId) {
+ return getExpectedRequestBase()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.setNetworkSpecifier(new TelephonyNetworkSpecifier(subId))
.build();
}
private NetworkRequest getRouteSelectionRequest(Set<Integer> netCapsSubIds) {
- return getExpectedRequestBase(netCapsSubIds).build();
+ return getExpectedRequestBase().setSubIds(netCapsSubIds).build();
}
- private NetworkRequest.Builder getExpectedRequestBase(Set<Integer> subIds) {
+ private NetworkRequest.Builder getExpectedRequestBase() {
final NetworkRequest.Builder builder =
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
- .setSubIds(subIds);
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
return builder;
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index ca6448c..2fadd44 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -241,7 +241,7 @@
verify(mGatewayStatusCallback)
.onGatewayConnectionError(
- eq(mConfig.getExposedCapabilities()),
+ eq(mConfig.getGatewayConnectionName()),
eq(VCN_ERROR_CODE_INTERNAL_ERROR),
any(),
any());
@@ -275,7 +275,10 @@
verify(mGatewayStatusCallback)
.onGatewayConnectionError(
- eq(mConfig.getExposedCapabilities()), eq(expectedErrorType), any(), any());
+ eq(mConfig.getGatewayConnectionName()),
+ eq(expectedErrorType),
+ any(),
+ any());
}
@Test
diff --git a/tests/vcn/java/com/android/server/vcn/VcnTest.java b/tests/vcn/java/com/android/server/vcn/VcnTest.java
index c853fc5..540be38 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnTest.java
@@ -19,10 +19,12 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_INACTIVE;
+import static android.net.vcn.VcnManager.VCN_STATUS_CODE_SAFE_MODE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
@@ -51,7 +53,9 @@
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Set;
import java.util.UUID;
@@ -140,7 +144,7 @@
mTestLooper.dispatchAll();
}
- private void verifyUpdateSubscriptionSnapshotNotifiesConnectionGateways(boolean isActive) {
+ private void verifyUpdateSubscriptionSnapshotNotifiesGatewayConnections(int status) {
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
startVcnGatewayWithCapabilities(requestListener, TEST_CAPS[0]);
@@ -150,25 +154,25 @@
final TelephonySubscriptionSnapshot updatedSnapshot =
mock(TelephonySubscriptionSnapshot.class);
- mVcn.setIsActive(isActive);
+ mVcn.setStatus(status);
mVcn.updateSubscriptionSnapshot(updatedSnapshot);
mTestLooper.dispatchAll();
for (final VcnGatewayConnection gateway : gatewayConnections) {
- verify(gateway, isActive ? times(1) : never())
+ verify(gateway, status == VCN_STATUS_CODE_ACTIVE ? times(1) : never())
.updateSubscriptionSnapshot(eq(updatedSnapshot));
}
}
@Test
public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() {
- verifyUpdateSubscriptionSnapshotNotifiesConnectionGateways(true /* isActive */);
+ verifyUpdateSubscriptionSnapshotNotifiesGatewayConnections(VCN_STATUS_CODE_ACTIVE);
}
@Test
- public void testSubscriptionSnapshotUpdatesVcnGatewayConnectionsWhileInactive() {
- verifyUpdateSubscriptionSnapshotNotifiesConnectionGateways(false /* isActive */);
+ public void testSubscriptionSnapshotUpdatesVcnGatewayConnectionsInSafeMode() {
+ verifyUpdateSubscriptionSnapshotNotifiesGatewayConnections(VCN_STATUS_CODE_SAFE_MODE);
}
private void triggerVcnRequestListeners(NetworkRequestListener requestListener) {
@@ -199,7 +203,7 @@
private void verifySafeMode(
NetworkRequestListener requestListener,
Set<VcnGatewayConnection> expectedGatewaysTornDown) {
- assertFalse(mVcn.isActive());
+ assertEquals(VCN_STATUS_CODE_SAFE_MODE, mVcn.getStatus());
for (final VcnGatewayConnection gatewayConnection : expectedGatewaysTornDown) {
verify(gatewayConnection).teardownAsynchronously();
}
@@ -274,11 +278,12 @@
assertEquals(2, mVcn.getVcnGatewayConnectionConfigMap().size());
// Create VcnConfig with only one VcnGatewayConnectionConfig so a gateway connection is torn
- // down
- final VcnGatewayConnectionConfig activeConfig =
- VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(TEST_CAPS[0]);
- final VcnGatewayConnectionConfig removedConfig =
- VcnGatewayConnectionConfigTest.buildTestConfigWithExposedCaps(TEST_CAPS[1]);
+ // down. Reuse existing VcnGatewayConnectionConfig so that the gateway connection name
+ // matches.
+ final List<VcnGatewayConnectionConfig> currentConfigs =
+ new ArrayList<>(mVcn.getVcnGatewayConnectionConfigMap().keySet());
+ final VcnGatewayConnectionConfig activeConfig = currentConfigs.get(0);
+ final VcnGatewayConnectionConfig removedConfig = currentConfigs.get(1);
final VcnConfig updatedConfig =
new VcnConfig.Builder(mContext).addGatewayConnectionConfig(activeConfig).build();
@@ -316,7 +321,7 @@
// Registered on start, then re-registered with new configs
verify(mVcnNetworkProvider, times(2)).registerListener(eq(requestListener));
- assertTrue(mVcn.isActive());
+ assertEquals(VCN_STATUS_CODE_ACTIVE, mVcn.getStatus());
for (final int[] caps : TEST_CAPS) {
// Expect each gateway connection created only on initial startup
verify(mDeps)
@@ -331,7 +336,7 @@
@Test
public void testIgnoreNetworkRequestWhileInactive() {
- mVcn.setIsActive(false /* isActive */);
+ mVcn.setStatus(VCN_STATUS_CODE_INACTIVE);
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
triggerVcnRequestListeners(requestListener);
diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp
index dfdac6b..d1e6d39 100644
--- a/tools/aapt2/cmd/Link_test.cpp
+++ b/tools/aapt2/cmd/Link_test.cpp
@@ -466,11 +466,19 @@
const std::string android_r_java = android_java + "/android/R.java";
std::string android_r_contents;
ASSERT_TRUE(android::base::ReadFileToString(android_r_java, &android_r_contents));
- EXPECT_THAT(android_r_contents, HasSubstr(" public static final int finalized_res=0x01010001;"));
- EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_s_res=0x01010050;"));
- EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_s2_res=0x01ff0049;"));
- EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_t_res=0x01fe0063;"));
- EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_t_string=0x01fd0072;"));
+ EXPECT_THAT(android_r_contents, HasSubstr("public static final int finalized_res=0x01010001;"));
+ EXPECT_THAT(
+ android_r_contents,
+ HasSubstr("public static final int staged_s_res; static { staged_s_res=0x01010050; }"));
+ EXPECT_THAT(
+ android_r_contents,
+ HasSubstr("public static final int staged_s2_res; static { staged_s2_res=0x01ff0049; }"));
+ EXPECT_THAT(
+ android_r_contents,
+ HasSubstr("public static final int staged_t_res; static { staged_t_res=0x01fe0063; }"));
+ EXPECT_THAT(
+ android_r_contents,
+ HasSubstr("public static final int staged_t_string; static { staged_t_string=0x01fd0072; }"));
// Build an app that uses the framework attribute in a declare-styleable
const std::string client_res = GetTestPath("app-res");
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index bfb8d58..f1b350f 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -393,8 +393,15 @@
.SetAllowMangled(true);
if (entry->flags & ResTable_entry::FLAG_PUBLIC) {
- res_builder.SetVisibility(Visibility{Visibility::Level::kPublic});
+ Visibility visibility{Visibility::Level::kPublic};
+ auto spec_flags = entry_type_spec_flags_.find(res_id);
+ if (spec_flags != entry_type_spec_flags_.end() &&
+ spec_flags->second & ResTable_typeSpec::SPEC_STAGED_API) {
+ visibility.staged_api = true;
+ }
+
+ res_builder.SetVisibility(visibility);
// Erase the ID from the map once processed, so that we don't mark the same symbol more than
// once.
entry_type_spec_flags_.erase(res_id);
diff --git a/tools/aapt2/java/ClassDefinition.h b/tools/aapt2/java/ClassDefinition.h
index d3648c8..2acdadb 100644
--- a/tools/aapt2/java/ClassDefinition.h
+++ b/tools/aapt2/java/ClassDefinition.h
@@ -78,10 +78,18 @@
ClassMember::Print(final, printer, strip_api_annotations);
printer->Print("public static ");
- if (final && !staged_api_) {
+ if (final) {
printer->Print("final ");
}
- printer->Print("int ").Print(name_).Print("=").Print(to_string(val_)).Print(";");
+ printer->Print("int ").Print(name_);
+ if (staged_api_) {
+ // Prevent references to staged apis from being inline by setting their value out-of-line.
+ printer->Print("; static { ").Print(name_);
+ }
+ printer->Print("=").Print(to_string(val_)).Print(";");
+ if (staged_api_) {
+ printer->Print(" }");
+ }
}
private: