summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/blobstore/framework/java/android/app/blob/BlobInfo.java1
-rw-r--r--apex/jobscheduler/framework/java/android/app/AlarmManager.java1
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobInfo.java1
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java167
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java175
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java70
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java91
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java7
-rw-r--r--apex/media/OWNERS1
-rw-r--r--apex/media/framework/jarjar_rules.txt2
-rw-r--r--apex/media/framework/java/android/media/MediaParser.java6
-rw-r--r--apex/media/framework/java/android/media/Session2CommandGroup.java2
-rw-r--r--apex/media/service/java/com/android/server/media/MediaCommunicationService.java31
-rw-r--r--api/Android.bp13
-rw-r--r--api/api.go224
-rw-r--r--core/api/current.txt322
-rw-r--r--core/api/module-lib-current.txt8
-rw-r--r--core/api/system-current.txt65
-rw-r--r--core/api/test-current.txt22
-rw-r--r--core/java/android/accessibilityservice/AccessibilityGestureEvent.java2
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java4
-rw-r--r--core/java/android/accessibilityservice/GestureDescription.java2
-rw-r--r--core/java/android/app/ActivityManager.java2
-rw-r--r--core/java/android/app/ActivityThread.java13
-rw-r--r--core/java/android/app/AppOpsManager.java6
-rw-r--r--core/java/android/app/AutomaticZenRule.java8
-rw-r--r--core/java/android/app/BroadcastOptions.java8
-rw-r--r--core/java/android/app/ContextImpl.java6
-rw-r--r--core/java/android/app/GrantedUriPermission.java2
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl11
-rw-r--r--core/java/android/app/LoadedApk.java33
-rw-r--r--core/java/android/app/NotificationChannelGroup.java2
-rw-r--r--core/java/android/app/RemoteInputHistoryItem.java2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java32
-rw-r--r--core/java/android/app/assist/AssistStructure.java6
-rw-r--r--core/java/android/app/communal/CommunalManager.java74
-rw-r--r--core/java/android/app/communal/ICommunalManager.aidl5
-rw-r--r--core/java/android/app/people/ConversationChannel.java8
-rw-r--r--core/java/android/app/people/ConversationStatus.java2
-rw-r--r--core/java/android/app/people/PeopleSpaceTile.java12
-rw-r--r--core/java/android/app/prediction/AppTargetEvent.java2
-rw-r--r--core/java/android/app/servertransaction/ClientTransaction.java4
-rw-r--r--core/java/android/app/smartspace/SmartspaceTargetEvent.java2
-rw-r--r--core/java/android/app/time/ExternalTimeSuggestion.java4
-rw-r--r--core/java/android/app/time/TimeCapabilitiesAndConfig.java4
-rw-r--r--core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java4
-rw-r--r--core/java/android/app/timedetector/GnssTimeSuggestion.java4
-rw-r--r--core/java/android/app/timedetector/ManualTimeSuggestion.java4
-rw-r--r--core/java/android/app/timedetector/NetworkTimeSuggestion.java4
-rw-r--r--core/java/android/app/timedetector/TelephonyTimeSuggestion.java4
-rw-r--r--core/java/android/app/timezone/RulesState.java6
-rw-r--r--core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java2
-rw-r--r--core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java2
-rw-r--r--core/java/android/app/trust/TrustManager.java2
-rw-r--r--core/java/android/app/usage/CacheQuotaHint.java2
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java24
-rw-r--r--core/java/android/bluetooth/BluetoothGattCharacteristic.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGattDescriptor.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGattIncludedService.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGattService.java2
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java170
-rw-r--r--core/java/android/bluetooth/BluetoothHeadsetClientCall.java2
-rw-r--r--core/java/android/bluetooth/BluetoothLeCall.java285
-rw-r--r--core/java/android/bluetooth/BluetoothLeCallControl.java899
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java9
-rw-r--r--core/java/android/bluetooth/BluetoothStatusCodes.java99
-rw-r--r--core/java/android/bluetooth/BufferConstraints.java2
-rw-r--r--core/java/android/bluetooth/le/AdvertiseSettings.java48
-rw-r--r--core/java/android/bluetooth/le/AdvertisingSetParameters.java82
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeAdvertiser.java1
-rw-r--r--core/java/android/bluetooth/le/ScanFilter.java10
-rw-r--r--core/java/android/companion/AssociationInfo.java39
-rw-r--r--core/java/android/companion/AssociationRequest.java2
-rw-r--r--core/java/android/companion/BluetoothDeviceFilter.java2
-rw-r--r--core/java/android/companion/BluetoothLeDeviceFilter.java2
-rw-r--r--core/java/android/companion/CompanionDeviceService.java26
-rw-r--r--core/java/android/companion/SystemDataTransferRequest.aidl (renamed from core/java/android/app/communal/ICommunalModeListener.aidl)13
-rw-r--r--core/java/android/companion/SystemDataTransferRequest.java157
-rw-r--r--core/java/android/content/ContentProviderOperation.java2
-rw-r--r--core/java/android/content/Context.java40
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/android/content/Intent.java45
-rw-r--r--core/java/android/content/IntentFilter.java2
-rw-r--r--core/java/android/content/PeriodicSync.java2
-rw-r--r--core/java/android/content/RestrictionEntry.java2
-rw-r--r--core/java/android/content/SyncInfo.java2
-rw-r--r--core/java/android/content/SyncRequest.java2
-rw-r--r--core/java/android/content/UndoManager.java2
-rw-r--r--core/java/android/content/UriPermission.java2
-rw-r--r--core/java/android/content/om/OverlayManagerTransaction.java2
-rw-r--r--core/java/android/content/pm/BaseParceledListSlice.java25
-rw-r--r--core/java/android/content/pm/InstallSourceInfo.java2
-rw-r--r--core/java/android/content/pm/InstantAppInfo.java2
-rw-r--r--core/java/android/content/pm/InstantAppIntentFilter.java2
-rw-r--r--core/java/android/content/pm/InstantAppResolveInfo.java2
-rw-r--r--core/java/android/content/pm/LauncherActivityInfoInternal.java4
-rw-r--r--core/java/android/content/pm/PackageInstaller.java74
-rw-r--r--core/java/android/content/pm/PackageManager.java25
-rw-r--r--core/java/android/content/pm/PackageParser.java44
-rw-r--r--core/java/android/content/pm/RegisteredServicesCache.java2
-rw-r--r--core/java/android/content/pm/SharedLibraryInfo.java10
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java8
-rw-r--r--core/java/android/content/pm/ShortcutManager.java4
-rw-r--r--core/java/android/content/pm/ShortcutQueryWrapper.java2
-rw-r--r--core/java/android/content/pm/TEST_MAPPING6
-rw-r--r--core/java/android/content/pm/VerifierInfo.java2
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageImpl.java2
-rw-r--r--core/java/android/content/pm/parsing/ParsingPackageUtils.java2
-rw-r--r--core/java/android/content/pm/parsing/ParsingUtils.java2
-rw-r--r--core/java/android/content/pm/parsing/component/ParsedPermissionImpl.java2
-rw-r--r--core/java/android/content/res/TEST_MAPPING8
-rw-r--r--core/java/android/debug/AdbManager.java3
-rw-r--r--core/java/android/graphics/fonts/FontUpdateRequest.java6
-rw-r--r--core/java/android/hardware/biometrics/PromptInfo.java2
-rw-r--r--core/java/android/hardware/biometrics/SensorPropertiesInternal.java2
-rw-r--r--core/java/android/hardware/camera2/CaptureRequest.java3
-rw-r--r--core/java/android/hardware/face/FaceAuthenticationFrame.java2
-rw-r--r--core/java/android/hardware/face/FaceEnrollFrame.java4
-rw-r--r--core/java/android/hardware/face/FaceManager.java49
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl9
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java30
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl4
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java2
-rw-r--r--core/java/android/hardware/radio/RadioManager.java3
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java55
-rw-r--r--core/java/android/net/Ikev2VpnProfile.java29
-rw-r--r--core/java/android/net/InterfaceConfiguration.java1
-rw-r--r--core/java/android/net/InternalNetworkUpdateRequest.java15
-rw-r--r--core/java/android/net/NetworkPolicy.java4
-rw-r--r--core/java/android/net/VpnService.java123
-rw-r--r--core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java241
-rw-r--r--core/java/android/net/vcn/VcnConfig.java2
-rw-r--r--core/java/android/net/vcn/VcnGatewayConnectionConfig.java133
-rw-r--r--core/java/android/net/vcn/VcnNetworkPolicyResult.java2
-rw-r--r--core/java/android/net/vcn/VcnTransportInfo.java2
-rw-r--r--core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java2
-rw-r--r--core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java160
-rw-r--r--core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java143
-rw-r--r--core/java/android/nfc/BeamShareData.java4
-rw-r--r--core/java/android/os/Message.java2
-rw-r--r--core/java/android/os/PowerManager.java6
-rw-r--r--core/java/android/os/StrictMode.java2
-rw-r--r--core/java/android/os/UserManager.java64
-rw-r--r--core/java/android/os/VibrationAttributes.java22
-rw-r--r--core/java/android/os/VibrationEffect.java42
-rw-r--r--core/java/android/os/Vibrator.java128
-rw-r--r--core/java/android/os/VibratorInfo.java189
-rw-r--r--core/java/android/os/WorkSource.java2
-rw-r--r--core/java/android/os/storage/StorageVolume.java2
-rw-r--r--core/java/android/os/vibrator/RampSegment.java49
-rw-r--r--core/java/android/os/vibrator/StepSegment.java32
-rw-r--r--core/java/android/os/vibrator/VibrationConfig.java175
-rw-r--r--core/java/android/permission/IPermissionController.aidl2
-rw-r--r--core/java/android/permission/IPermissionManager.aidl4
-rw-r--r--core/java/android/permission/PermissionControllerManager.java36
-rw-r--r--core/java/android/permission/PermissionControllerService.java35
-rw-r--r--core/java/android/permission/PermissionManager.java34
-rw-r--r--core/java/android/print/PrintJobInfo.java10
-rw-r--r--core/java/android/print/PrinterId.java2
-rw-r--r--core/java/android/print/PrinterInfo.java6
-rw-r--r--core/java/android/printservice/PrintServiceInfo.java2
-rw-r--r--core/java/android/provider/Settings.java40
-rw-r--r--core/java/android/service/autofill/BatchUpdates.java2
-rw-r--r--core/java/android/service/autofill/CompositeUserData.java4
-rw-r--r--core/java/android/service/autofill/CustomDescription.java2
-rw-r--r--core/java/android/service/autofill/Dataset.java12
-rw-r--r--core/java/android/service/autofill/DateTransformation.java4
-rw-r--r--core/java/android/service/autofill/DateValueSanitizer.java2
-rw-r--r--core/java/android/service/autofill/FillRequest.java2
-rw-r--r--core/java/android/service/autofill/FillResponse.java20
-rw-r--r--core/java/android/service/autofill/ImageTransformation.java2
-rw-r--r--core/java/android/service/autofill/NegationValidator.java2
-rw-r--r--core/java/android/service/autofill/RegexValidator.java4
-rw-r--r--core/java/android/service/autofill/SaveInfo.java8
-rw-r--r--core/java/android/service/autofill/TextValueSanitizer.java2
-rw-r--r--core/java/android/service/contentcapture/ActivityEvent.java2
-rw-r--r--core/java/android/service/contentcapture/SnapshotData.java4
-rw-r--r--core/java/android/service/dreams/DreamOverlayService.java10
-rw-r--r--core/java/android/service/dreams/DreamService.java13
-rw-r--r--core/java/android/service/games/GameService.java17
-rw-r--r--core/java/android/service/games/GameSessionService.java2
-rw-r--r--core/java/android/service/notification/Condition.java2
-rw-r--r--core/java/android/service/notification/ConversationChannelWrapper.java4
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java4
-rw-r--r--core/java/android/service/notification/NotificationRankingUpdate.java2
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java12
-rw-r--r--core/java/android/service/notification/ZenPolicy.java4
-rw-r--r--core/java/android/service/quickaccesswallet/GetWalletCardsResponse.java2
-rw-r--r--core/java/android/service/settings/suggestions/Suggestion.java4
-rw-r--r--core/java/android/service/timezone/TimeZoneProviderEvent.java2
-rw-r--r--core/java/android/service/timezone/TimeZoneProviderSuggestion.java2
-rw-r--r--core/java/android/speech/tts/Voice.java2
-rw-r--r--core/java/android/telephony/SubscriptionPlan.java2
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java41
-rw-r--r--core/java/android/text/BoringLayout.java29
-rw-r--r--core/java/android/text/FontConfig.java6
-rw-r--r--core/java/android/text/TextLine.java9
-rw-r--r--core/java/android/text/style/EasyEditSpan.java2
-rw-r--r--core/java/android/text/style/TextAppearanceSpan.java2
-rw-r--r--core/java/android/util/MemoryIntArray.java2
-rw-r--r--core/java/android/view/DisplayInfo.java6
-rw-r--r--core/java/android/view/KeyboardShortcutInfo.java2
-rw-r--r--core/java/android/view/OWNERS7
-rw-r--r--core/java/android/view/View.java4
-rw-r--r--core/java/android/view/ViewDebug.java6
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityWindowInfo.java11
-rw-r--r--core/java/android/view/autofill/ParcelableMap.java4
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureCondition.java2
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureContext.java4
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureEvent.java8
-rw-r--r--core/java/android/view/contentcapture/ViewNode.java8
-rw-r--r--core/java/android/view/inputmethod/CursorAnchorInfo.java2
-rw-r--r--core/java/android/view/inputmethod/EditorInfo.java2
-rw-r--r--core/java/android/view/inputmethod/InlineSuggestionsRequest.java2
-rw-r--r--core/java/android/view/inputmethod/InlineSuggestionsResponse.java2
-rw-r--r--core/java/android/view/textclassifier/ConversationAction.java2
-rw-r--r--core/java/android/view/textclassifier/ConversationActions.java8
-rw-r--r--core/java/android/view/textclassifier/SelectionEvent.java2
-rw-r--r--core/java/android/view/textclassifier/TextClassification.java4
-rw-r--r--core/java/android/view/textclassifier/TextClassificationContext.java2
-rw-r--r--core/java/android/view/textclassifier/TextClassifierEvent.java2
-rw-r--r--core/java/android/view/textclassifier/TextLanguage.java2
-rw-r--r--core/java/android/view/textclassifier/TextLinks.java6
-rw-r--r--core/java/android/view/textclassifier/TextSelection.java6
-rw-r--r--core/java/android/view/translation/TranslationRequest.java4
-rw-r--r--core/java/android/view/translation/TranslationSpec.java2
-rw-r--r--core/java/android/widget/ExpandableListView.java2
-rw-r--r--core/java/android/widget/RemoteViews.java3
-rw-r--r--core/java/android/widget/TextView.java13
-rw-r--r--core/java/android/window/DisplayAreaOrganizer.java10
-rw-r--r--core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java2
-rw-r--r--core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java6
-rw-r--r--core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java2
-rw-r--r--core/java/com/android/ims/internal/uce/presence/PresCapInfo.java2
-rw-r--r--core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java4
-rw-r--r--core/java/com/android/ims/internal/uce/presence/PresResInfo.java2
-rw-r--r--core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java2
-rw-r--r--core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java2
-rw-r--r--core/java/com/android/ims/internal/uce/presence/PresSipResponse.java2
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java4
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java4
-rw-r--r--core/java/com/android/internal/app/chooser/DisplayResolveInfo.java7
-rw-r--r--core/java/com/android/internal/infra/AndroidFuture.java2
-rw-r--r--core/java/com/android/internal/net/LegacyVpnInfo.java2
-rw-r--r--core/java/com/android/internal/net/VpnConfig.java44
-rw-r--r--core/java/com/android/internal/net/VpnProfile.java4
-rw-r--r--core/java/com/android/internal/os/AppFuseMount.java2
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java34
-rw-r--r--core/java/com/android/internal/statusbar/StatusBarIcon.java4
-rw-r--r--core/java/com/android/internal/util/ScreenshotHelper.java6
-rw-r--r--core/java/com/android/internal/widget/PointerLocationView.java27
-rw-r--r--core/jni/android_text_Hyphenator.cpp1
-rw-r--r--core/proto/android/providers/settings/system.proto6
-rw-r--r--core/proto/android/server/vibrator/OWNERS1
-rw-r--r--core/proto/android/server/vibrator/vibratormanagerservice.proto8
-rw-r--r--core/res/AndroidManifest.xml27
-rw-r--r--core/res/res/values/attrs.xml3
-rw-r--r--core/res/res/values/config.xml10
-rw-r--r--core/res/res/values/public.xml3
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java2
-rw-r--r--core/tests/coretests/src/android/content/res/FontResourcesParserTest.java2
-rw-r--r--core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java2
-rw-r--r--core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java2
-rw-r--r--core/tests/coretests/src/android/content/res/ResourcesManagerTest.java2
-rw-r--r--core/tests/coretests/src/android/content/res/TEST_MAPPING43
-rw-r--r--core/tests/coretests/src/android/os/OWNERS6
-rw-r--r--core/tests/coretests/src/android/os/VibrationEffectTest.java18
-rw-r--r--core/tests/coretests/src/android/os/VibratorInfoTest.java176
-rw-r--r--core/tests/coretests/src/android/os/VibratorTest.java18
-rw-r--r--core/tests/coretests/src/android/os/vibrator/OWNERS1
-rw-r--r--core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java20
-rw-r--r--core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java14
-rw-r--r--core/tests/coretests/src/com/android/internal/content/res/TEST_MAPPING21
-rw-r--r--core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java19
-rw-r--r--core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java5
-rw-r--r--core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java16
-rw-r--r--data/etc/privapp-permissions-platform.xml8
-rw-r--r--graphics/java/android/graphics/BaseCanvas.java117
-rw-r--r--graphics/java/android/graphics/Outline.java5
-rw-r--r--graphics/java/android/graphics/Picture.java15
-rw-r--r--graphics/java/android/graphics/RuntimeShader.java30
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java12
-rw-r--r--graphics/java/android/graphics/drawable/RippleShader.java61
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java19
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java60
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java32
-rw-r--r--libs/WindowManager/Shell/res/layout/background_panel.xml (renamed from packages/SystemUI/res-keyguard/values-sw720dp/bools.xml)24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java121
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java18
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java90
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java246
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java272
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java37
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java39
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/util/CounterRotator.java21
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt28
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt15
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt9
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/BackgroundWindowManagerTest.java61
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java131
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java7
-rw-r--r--libs/hwui/Android.bp30
-rw-r--r--libs/hwui/jni/NinePatch.cpp2
-rw-r--r--libs/hwui/jni/android_util_PathParser.cpp2
-rw-r--r--location/java/android/location/GnssMeasurement.java2
-rw-r--r--location/java/android/location/GnssMeasurementsEvent.java2
-rw-r--r--location/java/android/location/GpsMeasurementsEvent.java2
-rw-r--r--location/java/android/location/GpsNavigationMessageEvent.java2
-rw-r--r--location/java/android/location/SatellitePvt.java6
-rw-r--r--location/java/android/location/provider/LocationProviderBase.java40
-rw-r--r--media/OWNERS1
-rw-r--r--media/java/android/media/AudioSystem.java2
-rw-r--r--media/java/android/media/ImageReader.java314
-rw-r--r--media/java/android/media/ImageUtils.java29
-rw-r--r--media/java/android/media/MediaDescription.java6
-rw-r--r--media/java/android/media/MediaRoute2Info.java2
-rw-r--r--media/java/android/media/PublicFormatUtils.java34
-rw-r--r--media/java/android/media/midi/MidiDeviceStatus.java2
-rw-r--r--media/java/android/media/musicrecognition/RecognitionRequest.java4
-rw-r--r--media/java/android/media/session/MediaController.java2
-rw-r--r--media/java/android/media/tv/ITvInputManager.aidl1
-rw-r--r--media/java/android/media/tv/TvContentRatingSystemInfo.java4
-rw-r--r--media/java/android/media/tv/TvInputInfo.java10
-rw-r--r--media/java/android/media/tv/TvInputManager.java43
-rwxr-xr-xmedia/java/android/media/tv/TvInputService.java18
-rw-r--r--media/java/android/media/tv/interactive/ITvIAppManager.aidl4
-rw-r--r--media/java/android/media/tv/interactive/ITvIAppSession.aidl4
-rw-r--r--media/java/android/media/tv/interactive/TvIAppInfo.java1
-rw-r--r--media/java/android/media/tv/interactive/TvIAppManager.java61
-rw-r--r--media/java/android/media/tv/interactive/TvIAppService.java89
-rw-r--r--media/java/android/media/tv/interactive/TvIAppView.java94
-rw-r--r--media/java/android/media/tv/tuner/Lnb.java95
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java375
-rw-r--r--media/java/android/media/tv/tuner/filter/Filter.java12
-rw-r--r--media/java/android/media/tv/tuner/filter/SectionSettings.java39
-rw-r--r--media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java9
-rw-r--r--media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java8
-rw-r--r--media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java65
-rw-r--r--media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl39
-rw-r--r--media/jni/Android.bp1
-rw-r--r--media/jni/android_media_ImageReader.cpp24
-rw-r--r--media/jni/android_media_MediaPlayer.cpp6
-rw-r--r--media/jni/android_media_PublicFormatUtils.cpp59
-rw-r--r--media/jni/android_media_tv_Tuner.cpp53
-rw-r--r--media/jni/android_media_tv_Tuner.h2
-rw-r--r--media/jni/soundpool/Stream.cpp198
-rw-r--r--media/jni/tuner/FilterClient.cpp16
-rw-r--r--media/jni/tuner/FilterClient.h3
-rw-r--r--native/android/libandroid_net.map.txt4
-rw-r--r--native/android/net.c12
-rw-r--r--packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java26
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java2
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java8
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java2
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java6
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java2
-rw-r--r--packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java110
-rw-r--r--packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java34
-rw-r--r--packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml4
-rw-r--r--packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml4
-rw-r--r--packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml5
-rw-r--r--packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml8
-rw-r--r--packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml4
-rw-r--r--packages/SettingsLib/SettingsTheme/res/values/config.xml19
-rw-r--r--packages/SettingsLib/SettingsTheme/res/values/dimens.xml7
-rw-r--r--packages/SettingsLib/SettingsTheme/res/values/styles.xml29
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-am/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-as/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-az/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-be/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-bs/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-cs/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-da/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-el/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rAU/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rCA/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rGB/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rIN/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rXC/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-et/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-gl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hy/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-is/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ka/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-kk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-km/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ko/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ky/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-lo/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ml/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-mn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ms/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-my/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-nl/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-or/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pa/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-si/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sq/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sw/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ta/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-tl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ur/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-uz/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-vi/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zu/strings.xml2
-rw-r--r--packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java7
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractConnectivityPreferenceController.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java13
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java15
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java16
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java9
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java25
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java7
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java26
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java2
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java2
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java12
-rw-r--r--packages/Shell/AndroidManifest.xml12
-rw-r--r--packages/Shell/res/values-watch/strings.xml20
-rw-r--r--packages/Shell/src/com/android/shell/BugreportProgressService.java54
-rw-r--r--packages/SystemUI/Android.bp7
-rw-r--r--packages/SystemUI/animation/Android.bp2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt38
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml1
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml1
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/bools.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values/config.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/dimens.xml1
-rw-r--r--packages/SystemUI/res-product/values-zu/strings.xml6
-rw-r--r--packages/SystemUI/res/values-af/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-am/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ar/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-as/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-az/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-be/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-bg/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-bn/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-bs/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ca/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-cs/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-da/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-de/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-el/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-es/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-et/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-eu/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-fa/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-fi/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-fr/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-gl/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-gu/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-hi/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-hr/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-hu/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-hy/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-in/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-is/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-it/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-iw/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ja/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ka/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-kk/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-km/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-kn/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ko/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ky/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-lo/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-lt/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-lv/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-mk/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ml/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-mn/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-mr/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ms/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-my/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-nb/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ne/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-nl/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-or/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-pa/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-pl/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-ro/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ru/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-si/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-sk/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-sl/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-sq/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-sr/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-sv/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-sw/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-sw720dp-land/config.xml2
-rw-r--r--packages/SystemUI/res/values-ta/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-te/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-th/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-tl/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-tr/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-uk/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-ur/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-uz/tiles_states_strings.xml5
-rw-r--r--packages/SystemUI/res/values-vi/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values-zu/tiles_states_strings.xml3
-rw-r--r--packages/SystemUI/res/values/config.xml1
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/navigationbar/RegionSamplingHelper.java46
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java8
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt176
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt16
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java10
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java13
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java133
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt36
-rw-r--r--packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java48
-rw-r--r--packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt194
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt50
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogTest.kt33
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt102
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt44
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java20
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java26
-rw-r--r--services/companion/java/com/android/server/companion/AssociationCleanUpService.java77
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java46
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerServiceInternal.java29
-rw-r--r--services/companion/java/com/android/server/companion/PersistentDataStore.java14
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java9
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java8
-rw-r--r--services/core/java/com/android/server/SystemServiceManager.java44
-rw-r--r--services/core/java/com/android/server/adb/AdbDebuggingManager.java21
-rw-r--r--services/core/java/com/android/server/adb/AdbService.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java9
-rw-r--r--services/core/java/com/android/server/am/AppNotRespondingDialog.java4
-rw-r--r--services/core/java/com/android/server/am/BatteryExternalStatsWorker.java11
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java10
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java33
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java13
-rw-r--r--services/core/java/com/android/server/am/ServiceRecord.java6
-rw-r--r--services/core/java/com/android/server/apphibernation/AppHibernationService.java26
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java6
-rw-r--r--services/core/java/com/android/server/audio/AudioSystemAdapter.java21
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java421
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java419
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/Interruptable.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/LockoutResetDispatcher.java14
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java35
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java15
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java3
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java23
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java3
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java3
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java30
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java33
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java3
-rw-r--r--services/core/java/com/android/server/communal/CommunalManagerService.java60
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java7
-rw-r--r--services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java27
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java19
-rw-r--r--services/core/java/com/android/server/media/OWNERS10
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java2
-rw-r--r--services/core/java/com/android/server/notification/CountdownConditionProvider.java3
-rw-r--r--services/core/java/com/android/server/notification/EventConditionProvider.java3
-rw-r--r--services/core/java/com/android/server/notification/NotificationHistoryDatabase.java3
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerInternal.java6
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java119
-rw-r--r--services/core/java/com/android/server/notification/PermissionHelper.java32
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java3
-rw-r--r--services/core/java/com/android/server/notification/ScheduleConditionProvider.java3
-rw-r--r--services/core/java/com/android/server/notification/SnoozeHelper.java3
-rw-r--r--services/core/java/com/android/server/notification/VibratorHelper.java8
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java4
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java13
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java12
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageSessionVerifier.java30
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java22
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java9
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java4
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java45
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java163
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java29
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyInternal.java20
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java185
-rw-r--r--services/core/java/com/android/server/power/Notifier.java22
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java30
-rw-r--r--services/core/java/com/android/server/power/ScreenUndimDetector.java10
-rw-r--r--services/core/java/com/android/server/powerstats/PowerStatsLogger.java5
-rw-r--r--services/core/java/com/android/server/powerstats/PowerStatsService.java35
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java53
-rw-r--r--services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java15
-rwxr-xr-xservices/core/java/com/android/server/tv/TvInputManagerService.java30
-rw-r--r--services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java88
-rw-r--r--services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java115
-rw-r--r--services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java38
-rw-r--r--services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java12
-rw-r--r--services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java40
-rw-r--r--services/core/java/com/android/server/vibrator/RampDownAdapter.java12
-rw-r--r--services/core/java/com/android/server/vibrator/RampToStepAdapter.java22
-rw-r--r--services/core/java/com/android/server/vibrator/StepToRampAdapter.java55
-rw-r--r--services/core/java/com/android/server/vibrator/Vibration.java6
-rw-r--r--services/core/java/com/android/server/vibrator/VibrationSettings.java268
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorController.java15
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorManagerService.java16
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java307
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java625
-rw-r--r--services/core/java/com/android/server/wm/ActivityInterceptorCallback.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java13
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java93
-rw-r--r--services/core/java/com/android/server/wm/AppTransitionController.java13
-rw-r--r--services/core/java/com/android/server/wm/DisplayAreaPolicy.java7
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java21
-rw-r--r--services/core/java/com/android/server/wm/FadeRotationAnimationController.java4
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java61
-rw-r--r--services/core/java/com/android/server/wm/ShellRoot.java52
-rw-r--r--services/core/java/com/android/server/wm/StartingSurfaceController.java87
-rw-r--r--services/core/java/com/android/server/wm/Task.java4
-rw-r--r--services/core/java/com/android/server/wm/WallpaperWindowToken.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java33
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java16
-rw-r--r--services/core/jni/com_android_server_am_CachedAppOptimizer.cpp22
-rw-r--r--services/core/jni/com_android_server_vibrator_VibratorController.cpp24
-rw-r--r--services/incremental/TEST_MAPPING6
-rw-r--r--services/java/com/android/server/SystemServer.java64
-rw-r--r--services/midi/OWNERS1
-rw-r--r--services/tests/mockingservicestests/Android.bp26
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java97
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java5
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java37
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java23
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java26
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java303
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java125
-rw-r--r--services/tests/servicestests/src/com/android/server/SystemServiceManagerTest.java84
-rw-r--r--services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java110
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java326
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java266
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/LockoutResetDispatcherTest.java105
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java1
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java67
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/FakeVibrator.java34
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java192
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java67
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java147
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java351
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java66
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java93
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java2
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java123
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java6
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java29
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java20
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java19
-rw-r--r--telecomm/java/android/telecom/Call.java12
-rw-r--r--telecomm/java/android/telecom/CallAudioState.java23
-rw-r--r--telecomm/java/android/telecom/Connection.java13
-rw-r--r--telecomm/java/android/telecom/ConnectionRequest.java12
-rw-r--r--telecomm/java/android/telecom/DisconnectCause.java2
-rw-r--r--telecomm/java/android/telecom/ParcelableCall.java16
-rw-r--r--telecomm/java/android/telecom/ParcelableConference.java10
-rw-r--r--telecomm/java/android/telecom/ParcelableConnection.java8
-rw-r--r--telecomm/java/android/telecom/ParcelableRttCall.java4
-rw-r--r--telecomm/java/android/telecom/PhoneAccountSuggestion.java2
-rw-r--r--telecomm/java/android/telecom/StatusHints.java4
-rw-r--r--telephony/java/android/telephony/AvailableNetworkInfo.java4
-rw-r--r--telephony/java/android/telephony/BarringInfo.java4
-rw-r--r--telephony/java/android/telephony/CallAttributes.java4
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java2555
-rw-r--r--telephony/java/android/telephony/CellIdentityLte.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityTdscdma.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityWcdma.java2
-rw-r--r--telephony/java/android/telephony/CellSignalStrengthNr.java2
-rw-r--r--telephony/java/android/telephony/DataSpecificRegistrationInfo.java2
-rw-r--r--telephony/java/android/telephony/NetworkRegistrationInfo.java8
-rw-r--r--telephony/java/android/telephony/NetworkScanRequest.java3
-rw-r--r--telephony/java/android/telephony/PhoneCapability.java2
-rw-r--r--telephony/java/android/telephony/PreciseDataConnectionState.java4
-rw-r--r--telephony/java/android/telephony/ServiceState.java2
-rw-r--r--telephony/java/android/telephony/SignalStrength.java12
-rw-r--r--telephony/java/android/telephony/ThermalMitigationRequest.java2
-rw-r--r--telephony/java/android/telephony/UiccCardInfo.java8
-rw-r--r--telephony/java/android/telephony/UiccSlotInfo.java16
-rw-r--r--telephony/java/android/telephony/VisualVoicemailSms.java2
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java2
-rw-r--r--telephony/java/android/telephony/data/DataCallResponse.java16
-rw-r--r--telephony/java/android/telephony/data/DataProfile.java4
-rw-r--r--telephony/java/android/telephony/data/Qos.java4
-rw-r--r--telephony/java/android/telephony/data/QosBearerFilter.java45
-rw-r--r--telephony/java/android/telephony/data/QosBearerSession.java4
-rw-r--r--telephony/java/android/telephony/gba/GbaAuthRequest.java2
-rw-r--r--telephony/java/android/telephony/ims/DelegateRequest.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java5
-rw-r--r--telephony/java/android/telephony/ims/ImsConferenceState.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsExternalCallState.java4
-rw-r--r--telephony/java/android/telephony/ims/ImsRegistrationAttributes.java2
-rw-r--r--telephony/java/android/telephony/ims/ImsSsData.java4
-rw-r--r--telephony/java/android/telephony/ims/RcsContactPresenceTuple.java4
-rw-r--r--telephony/java/android/telephony/ims/RcsContactTerminatedReason.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsContactUceCapability.java4
-rw-r--r--telephony/java/android/telephony/ims/RtpHeaderExtensionType.java2
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateConfiguration.java2
-rw-r--r--telephony/java/android/telephony/ims/SipMessage.java4
-rw-r--r--telephony/java/android/telephony/mbms/DownloadRequest.java4
-rw-r--r--telephony/java/android/telephony/mbms/FileInfo.java2
-rw-r--r--telephony/java/android/telephony/mbms/FileServiceInfo.java2
-rw-r--r--telephony/java/android/telephony/mbms/ServiceInfo.java8
-rw-r--r--telephony/java/android/telephony/mbms/UriPathPair.java4
-rw-r--r--telephony/java/com/android/internal/telephony/NetworkScanResult.java2
-rw-r--r--telephony/java/com/android/internal/telephony/OperatorInfo.java2
-rw-r--r--tests/AppLaunchWear/Android.bp22
-rw-r--r--tests/AppLaunchWear/AndroidManifest.xml21
-rw-r--r--tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java864
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java4
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java2
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java24
-rw-r--r--tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java41
-rw-r--r--tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java66
-rw-r--r--tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java24
-rw-r--r--tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java25
-rw-r--r--tools/aapt2/cmd/Compile_test.cpp64
-rw-r--r--tools/aapt2/test/Fixture.cpp5
-rwxr-xr-xtools/fonts/fontchain_linter.py1
866 files changed, 16799 insertions, 7389 deletions
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobInfo.java b/apex/blobstore/framework/java/android/app/blob/BlobInfo.java
index 73ef310c7b40..ba92d95b483e 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobInfo.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobInfo.java
@@ -48,7 +48,6 @@ public final class BlobInfo implements Parcelable {
mLeaseInfos = leaseInfos;
}
- @SuppressWarnings("UnsafeParcelApi")
private BlobInfo(Parcel in) {
mId = in.readLong();
mExpiryTimeMs = in.readLong();
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
index 66767e21a2e7..9c0c3657bff3 100644
--- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java
+++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
@@ -1408,7 +1408,6 @@ public class AlarmManager {
* Use the {@link #CREATOR}
* @hide
*/
- @SuppressWarnings("UnsafeParcelApi")
AlarmClockInfo(Parcel in) {
mTriggerTime = in.readLong();
mShowIntent = in.readParcelable(PendingIntent.class.getClassLoader());
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index b9673f25d680..0e6006a62397 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -881,7 +881,6 @@ public class JobInfo implements Parcelable {
return hashCode;
}
- @SuppressWarnings("UnsafeParcelApi")
private JobInfo(Parcel in) {
jobId = in.readInt();
extras = in.readPersistableBundle();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 86d7a5a5a62e..3fb1fadba062 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -54,6 +54,8 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.ServiceInfo;
import android.net.Uri;
+import android.os.BatteryManager;
+import android.os.BatteryManagerInternal;
import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
import android.os.Binder;
@@ -250,8 +252,6 @@ public class JobSchedulerService extends com.android.server.SystemService
*/
private final List<RestrictingController> mRestrictiveControllers;
/** Need direct access to this for testing. */
- private final BatteryController mBatteryController;
- /** Need direct access to this for testing. */
private final StorageController mStorageController;
/** Need directly for sending uid state changes */
private final DeviceIdleJobsController mDeviceIdleJobsController;
@@ -268,6 +268,9 @@ public class JobSchedulerService extends com.android.server.SystemService
*/
private final List<JobRestriction> mJobRestrictions;
+ @GuardedBy("mLock")
+ private final BatteryStateTracker mBatteryStateTracker;
+
@NonNull
private final String mSystemGalleryPackage;
@@ -1697,6 +1700,9 @@ public class JobSchedulerService extends com.android.server.SystemService
// Initialize the job store and set up any persisted jobs
mJobs = JobStore.initAndGet(this);
+ mBatteryStateTracker = new BatteryStateTracker();
+ mBatteryStateTracker.startTracking();
+
// Create the controllers.
mControllers = new ArrayList<StateController>();
final ConnectivityController connectivityController = new ConnectivityController(this);
@@ -1704,8 +1710,8 @@ public class JobSchedulerService extends com.android.server.SystemService
mControllers.add(new TimeController(this));
final IdleController idleController = new IdleController(this);
mControllers.add(idleController);
- mBatteryController = new BatteryController(this);
- mControllers.add(mBatteryController);
+ final BatteryController batteryController = new BatteryController(this);
+ mControllers.add(batteryController);
mStorageController = new StorageController(this);
mControllers.add(mStorageController);
final BackgroundJobsController backgroundJobsController =
@@ -1725,7 +1731,7 @@ public class JobSchedulerService extends com.android.server.SystemService
mControllers.add(mTareController);
mRestrictiveControllers = new ArrayList<>();
- mRestrictiveControllers.add(mBatteryController);
+ mRestrictiveControllers.add(batteryController);
mRestrictiveControllers.add(connectivityController);
mRestrictiveControllers.add(idleController);
@@ -2818,6 +2824,129 @@ public class JobSchedulerService extends com.android.server.SystemService
return adjustJobBias(bias, job);
}
+ private final class BatteryStateTracker extends BroadcastReceiver {
+ /**
+ * Track whether we're "charging", where charging means that we're ready to commit to
+ * doing work.
+ */
+ private boolean mCharging;
+ /** Keep track of whether the battery is charged enough that we want to do work. */
+ private boolean mBatteryNotLow;
+ /** Sequence number of last broadcast. */
+ private int mLastBatterySeq = -1;
+
+ private BroadcastReceiver mMonitor;
+
+ BatteryStateTracker() {
+ }
+
+ public void startTracking() {
+ IntentFilter filter = new IntentFilter();
+
+ // Battery health.
+ filter.addAction(Intent.ACTION_BATTERY_LOW);
+ filter.addAction(Intent.ACTION_BATTERY_OKAY);
+ // Charging/not charging.
+ filter.addAction(BatteryManager.ACTION_CHARGING);
+ filter.addAction(BatteryManager.ACTION_DISCHARGING);
+ getTestableContext().registerReceiver(this, filter);
+
+ // Initialise tracker state.
+ BatteryManagerInternal batteryManagerInternal =
+ LocalServices.getService(BatteryManagerInternal.class);
+ mBatteryNotLow = !batteryManagerInternal.getBatteryLevelLow();
+ mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
+ }
+
+ public void setMonitorBatteryLocked(boolean enabled) {
+ if (enabled) {
+ if (mMonitor == null) {
+ mMonitor = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ onReceiveInternal(intent);
+ }
+ };
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ getTestableContext().registerReceiver(mMonitor, filter);
+ }
+ } else if (mMonitor != null) {
+ getTestableContext().unregisterReceiver(mMonitor);
+ mMonitor = null;
+ }
+ }
+
+ public boolean isCharging() {
+ return mCharging;
+ }
+
+ public boolean isBatteryNotLow() {
+ return mBatteryNotLow;
+ }
+
+ public boolean isMonitoring() {
+ return mMonitor != null;
+ }
+
+ public int getSeq() {
+ return mLastBatterySeq;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ onReceiveInternal(intent);
+ }
+
+ @VisibleForTesting
+ public void onReceiveInternal(Intent intent) {
+ synchronized (mLock) {
+ final String action = intent.getAction();
+ boolean changed = false;
+ if (Intent.ACTION_BATTERY_LOW.equals(action)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Battery life too low @ " + sElapsedRealtimeClock.millis());
+ }
+ if (mBatteryNotLow) {
+ mBatteryNotLow = false;
+ changed = true;
+ }
+ } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Battery high enough @ " + sElapsedRealtimeClock.millis());
+ }
+ if (!mBatteryNotLow) {
+ mBatteryNotLow = true;
+ changed = true;
+ }
+ } else if (BatteryManager.ACTION_CHARGING.equals(action)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Battery charging @ " + sElapsedRealtimeClock.millis());
+ }
+ if (!mCharging) {
+ mCharging = true;
+ changed = true;
+ }
+ } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Disconnected from power @ " + sElapsedRealtimeClock.millis());
+ }
+ if (mCharging) {
+ mCharging = false;
+ changed = true;
+ }
+ }
+ mLastBatterySeq =
+ intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq);
+ if (changed) {
+ for (int c = mControllers.size() - 1; c >= 0; --c) {
+ mControllers.get(c).onBatteryStateChangedLocked();
+ }
+ }
+ }
+ }
+ }
+
final class LocalService implements JobSchedulerInternal {
/**
@@ -3417,29 +3546,27 @@ public class JobSchedulerService extends com.android.server.SystemService
void setMonitorBattery(boolean enabled) {
synchronized (mLock) {
- if (mBatteryController != null) {
- mBatteryController.getTracker().setMonitorBatteryLocked(enabled);
- }
+ mBatteryStateTracker.setMonitorBatteryLocked(enabled);
}
}
int getBatterySeq() {
synchronized (mLock) {
- return mBatteryController != null ? mBatteryController.getTracker().getSeq() : -1;
+ return mBatteryStateTracker.getSeq();
}
}
- boolean getBatteryCharging() {
+ /** Return {@code true} if the device is currently charging. */
+ public boolean isBatteryCharging() {
synchronized (mLock) {
- return mBatteryController != null
- ? mBatteryController.getTracker().isOnStablePower() : false;
+ return mBatteryStateTracker.isCharging();
}
}
- boolean getBatteryNotLow() {
+ /** Return {@code true} if the battery is not low. */
+ public boolean isBatteryNotLow() {
synchronized (mLock) {
- return mBatteryController != null
- ? mBatteryController.getTracker().isBatteryNotLow() : false;
+ return mBatteryStateTracker.isBatteryNotLow();
}
}
@@ -3614,6 +3741,16 @@ public class JobSchedulerService extends com.android.server.SystemService
mQuotaTracker.dump(pw);
pw.println();
+ pw.print("Battery charging: ");
+ pw.println(mBatteryStateTracker.isCharging());
+ pw.print("Battery not low: ");
+ pw.println(mBatteryStateTracker.isBatteryNotLow());
+ if (mBatteryStateTracker.isMonitoring()) {
+ pw.print("MONITORING: seq=");
+ pw.println(mBatteryStateTracker.getSeq());
+ }
+ pw.println();
+
pw.println("Started users: " + Arrays.toString(mStartedUsers));
pw.print("Registered ");
pw.print(mJobs.size());
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index cc202130ab07..27268d267001 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -293,13 +293,13 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
}
private int getBatteryCharging(PrintWriter pw) {
- boolean val = mInternal.getBatteryCharging();
+ boolean val = mInternal.isBatteryCharging();
pw.println(val);
return 0;
}
private int getBatteryNotLow(PrintWriter pw) {
- boolean val = mInternal.getBatteryNotLow();
+ boolean val = mInternal.isBatteryNotLow();
pw.println(val);
return 0;
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
index 657f4700bd5c..f7338494384d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
@@ -18,12 +18,6 @@ package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.BatteryManager;
-import android.os.BatteryManagerInternal;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
@@ -31,8 +25,8 @@ import android.util.Log;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.LocalServices;
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
@@ -49,17 +43,9 @@ public final class BatteryController extends RestrictingController {
|| Log.isLoggable(TAG, Log.DEBUG);
private final ArraySet<JobStatus> mTrackedTasks = new ArraySet<>();
- private ChargingTracker mChargeTracker;
-
- @VisibleForTesting
- public ChargingTracker getTracker() {
- return mChargeTracker;
- }
public BatteryController(JobSchedulerService service) {
super(service);
- mChargeTracker = new ChargingTracker();
- mChargeTracker.startTracking();
}
@Override
@@ -68,9 +54,9 @@ public final class BatteryController extends RestrictingController {
final long nowElapsed = sElapsedRealtimeClock.millis();
mTrackedTasks.add(taskStatus);
taskStatus.setTrackingController(JobStatus.TRACKING_BATTERY);
- taskStatus.setChargingConstraintSatisfied(nowElapsed, mChargeTracker.isOnStablePower());
- taskStatus.setBatteryNotLowConstraintSatisfied(
- nowElapsed, mChargeTracker.isBatteryNotLow());
+ taskStatus.setChargingConstraintSatisfied(nowElapsed,
+ mService.isBatteryCharging() && mService.isBatteryNotLow());
+ taskStatus.setBatteryNotLowConstraintSatisfied(nowElapsed, mService.isBatteryNotLow());
}
}
@@ -93,9 +79,21 @@ public final class BatteryController extends RestrictingController {
}
}
+ @Override
+ @GuardedBy("mLock")
+ public void onBatteryStateChangedLocked() {
+ // Update job bookkeeping out of band.
+ JobSchedulerBackgroundThread.getHandler().post(() -> {
+ synchronized (mLock) {
+ maybeReportNewChargingStateLocked();
+ }
+ });
+ }
+
+ @GuardedBy("mLock")
private void maybeReportNewChargingStateLocked() {
- final boolean stablePower = mChargeTracker.isOnStablePower();
- final boolean batteryNotLow = mChargeTracker.isBatteryNotLow();
+ final boolean stablePower = mService.isBatteryCharging() && mService.isBatteryNotLow();
+ final boolean batteryNotLow = mService.isBatteryNotLow();
if (DEBUG) {
Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower);
}
@@ -116,133 +114,11 @@ public final class BatteryController extends RestrictingController {
}
}
- public final class ChargingTracker extends BroadcastReceiver {
- /**
- * Track whether we're "charging", where charging means that we're ready to commit to
- * doing work.
- */
- private boolean mCharging;
- /** Keep track of whether the battery is charged enough that we want to do work. */
- private boolean mBatteryHealthy;
- /** Sequence number of last broadcast. */
- private int mLastBatterySeq = -1;
-
- private BroadcastReceiver mMonitor;
-
- public ChargingTracker() {
- }
-
- public void startTracking() {
- IntentFilter filter = new IntentFilter();
-
- // Battery health.
- filter.addAction(Intent.ACTION_BATTERY_LOW);
- filter.addAction(Intent.ACTION_BATTERY_OKAY);
- // Charging/not charging.
- filter.addAction(BatteryManager.ACTION_CHARGING);
- filter.addAction(BatteryManager.ACTION_DISCHARGING);
- mContext.registerReceiver(this, filter);
-
- // Initialise tracker state.
- BatteryManagerInternal batteryManagerInternal =
- LocalServices.getService(BatteryManagerInternal.class);
- mBatteryHealthy = !batteryManagerInternal.getBatteryLevelLow();
- mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
- }
-
- public void setMonitorBatteryLocked(boolean enabled) {
- if (enabled) {
- if (mMonitor == null) {
- mMonitor = new BroadcastReceiver() {
- @Override public void onReceive(Context context, Intent intent) {
- ChargingTracker.this.onReceive(context, intent);
- }
- };
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- mContext.registerReceiver(mMonitor, filter);
- }
- } else {
- if (mMonitor != null) {
- mContext.unregisterReceiver(mMonitor);
- mMonitor = null;
- }
- }
- }
-
- public boolean isOnStablePower() {
- return mCharging && mBatteryHealthy;
- }
-
- public boolean isBatteryNotLow() {
- return mBatteryHealthy;
- }
-
- public boolean isMonitoring() {
- return mMonitor != null;
- }
-
- public int getSeq() {
- return mLastBatterySeq;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- onReceiveInternal(intent);
- }
-
- @VisibleForTesting
- public void onReceiveInternal(Intent intent) {
- synchronized (mLock) {
- final String action = intent.getAction();
- if (Intent.ACTION_BATTERY_LOW.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Battery life too low to do work. @ "
- + sElapsedRealtimeClock.millis());
- }
- // If we get this action, the battery is discharging => it isn't plugged in so
- // there's no work to cancel. We track this variable for the case where it is
- // charging, but hasn't been for long enough to be healthy.
- mBatteryHealthy = false;
- maybeReportNewChargingStateLocked();
- } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Battery life healthy enough to do work. @ "
- + sElapsedRealtimeClock.millis());
- }
- mBatteryHealthy = true;
- maybeReportNewChargingStateLocked();
- } else if (BatteryManager.ACTION_CHARGING.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Received charging intent, fired @ "
- + sElapsedRealtimeClock.millis());
- }
- mCharging = true;
- maybeReportNewChargingStateLocked();
- } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Disconnected from power.");
- }
- mCharging = false;
- maybeReportNewChargingStateLocked();
- }
- mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE,
- mLastBatterySeq);
- }
- }
- }
-
@Override
public void dumpControllerStateLocked(IndentingPrintWriter pw,
Predicate<JobStatus> predicate) {
- pw.println("Stable power: " + mChargeTracker.isOnStablePower());
- pw.println("Not low: " + mChargeTracker.isBatteryNotLow());
-
- if (mChargeTracker.isMonitoring()) {
- pw.print("MONITORING: seq=");
- pw.println(mChargeTracker.getSeq());
- }
- pw.println();
+ pw.println("Stable power: " + (mService.isBatteryCharging() && mService.isBatteryNotLow()));
+ pw.println("Not low: " + mService.isBatteryNotLow());
for (int i = 0; i < mTrackedTasks.size(); i++) {
final JobStatus js = mTrackedTasks.valueAt(i);
@@ -264,14 +140,9 @@ public final class BatteryController extends RestrictingController {
final long mToken = proto.start(StateControllerProto.BATTERY);
proto.write(StateControllerProto.BatteryController.IS_ON_STABLE_POWER,
- mChargeTracker.isOnStablePower());
+ mService.isBatteryCharging() && mService.isBatteryNotLow());
proto.write(StateControllerProto.BatteryController.IS_BATTERY_NOT_LOW,
- mChargeTracker.isBatteryNotLow());
-
- proto.write(StateControllerProto.BatteryController.IS_MONITORING,
- mChargeTracker.isMonitoring());
- proto.write(StateControllerProto.BatteryController.LAST_BROADCAST_SEQUENCE_NUMBER,
- mChargeTracker.getSeq());
+ mService.isBatteryNotLow());
for (int i = 0; i < mTrackedTasks.size(); i++) {
final JobStatus js = mTrackedTasks.valueAt(i);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index 524d68fb72e7..9fb7ab594607 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -25,18 +25,12 @@ import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.job.JobInfo;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
-import android.os.BatteryManager;
-import android.os.BatteryManagerInternal;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -55,6 +49,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobSchedulerService.Constants;
@@ -107,8 +102,6 @@ public final class ConnectivityController extends RestrictingController implemen
private final ConnectivityManager mConnManager;
private final NetworkPolicyManagerInternal mNetPolicyManagerInternal;
- private final ChargingTracker mChargingTracker;
-
/** List of tracked jobs keyed by source UID. */
@GuardedBy("mLock")
private final SparseArray<ArraySet<JobStatus>> mTrackedJobs = new SparseArray<>();
@@ -237,9 +230,6 @@ public final class ConnectivityController extends RestrictingController implemen
// network changes against the active network for each UID with jobs.
final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
mConnManager.registerNetworkCallback(request, mNetworkCallback);
-
- mChargingTracker = new ChargingTracker();
- mChargingTracker.startTracking();
}
@GuardedBy("mLock")
@@ -535,6 +525,17 @@ public final class ConnectivityController extends RestrictingController implemen
}
}
+ @Override
+ @GuardedBy("mLock")
+ public void onBatteryStateChangedLocked() {
+ // Update job bookkeeping out of band to avoid blocking broadcast progress.
+ JobSchedulerBackgroundThread.getHandler().post(() -> {
+ synchronized (mLock) {
+ updateTrackedJobsLocked(-1, null);
+ }
+ });
+ }
+
private boolean isUsable(NetworkCapabilities capabilities) {
return capabilities != null
&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
@@ -591,7 +592,7 @@ public final class ConnectivityController extends RestrictingController implemen
// Minimum chunk size isn't defined. Check using the estimated upload/download sizes.
if (capabilities.hasCapability(NET_CAPABILITY_NOT_METERED)
- && mChargingTracker.isCharging()) {
+ && mService.isBatteryCharging()) {
// We're charging and on an unmetered network. We don't have to be as conservative about
// making sure the job will run within its max execution time. Let's just hope the app
// supports interruptible work.
@@ -1072,51 +1073,6 @@ public final class ConnectivityController extends RestrictingController implemen
}
}
- private final class ChargingTracker extends BroadcastReceiver {
- /**
- * Track whether we're "charging", where charging means that we're ready to commit to
- * doing work.
- */
- private boolean mCharging;
-
- ChargingTracker() {}
-
- public void startTracking() {
- IntentFilter filter = new IntentFilter();
- filter.addAction(BatteryManager.ACTION_CHARGING);
- filter.addAction(BatteryManager.ACTION_DISCHARGING);
- mContext.registerReceiver(this, filter);
-
- // Initialise tracker state.
- final BatteryManagerInternal batteryManagerInternal =
- LocalServices.getService(BatteryManagerInternal.class);
- mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
- }
-
- public boolean isCharging() {
- return mCharging;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- synchronized (mLock) {
- final String action = intent.getAction();
- if (BatteryManager.ACTION_CHARGING.equals(action)) {
- if (mCharging) {
- return;
- }
- mCharging = true;
- } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
- if (!mCharging) {
- return;
- }
- mCharging = false;
- }
- updateTrackedJobsLocked(-1, null);
- }
- }
- }
-
private final NetworkCallback mNetworkCallback = new NetworkCallback() {
@Override
public void onAvailable(Network network) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index c147ef83dcf0..65e1d49d1510 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -39,15 +39,11 @@ import android.app.IUidObserver;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.UsageEventListener;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.BatteryManager;
-import android.os.BatteryManagerInternal;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -319,7 +315,6 @@ public final class QuotaController extends StateController {
private final SparseLongArray mTopAppGraceCache = new SparseLongArray();
private final AlarmManager mAlarmManager;
- private final ChargingTracker mChargeTracker;
private final QcHandler mHandler;
private final QcConstants mQcConstants;
@@ -542,8 +537,6 @@ public final class QuotaController extends StateController {
@NonNull ConnectivityController connectivityController) {
super(service);
mHandler = new QcHandler(mContext.getMainLooper());
- mChargeTracker = new ChargingTracker();
- mChargeTracker.startTracking();
mAlarmManager = mContext.getSystemService(AlarmManager.class);
mQcConstants = new QcConstants();
mBackgroundJobsController = backgroundJobsController;
@@ -705,6 +698,11 @@ public final class QuotaController extends StateController {
mTopAppTrackers.delete(userId);
}
+ @Override
+ public void onBatteryStateChangedLocked() {
+ handleNewChargingStateLocked();
+ }
+
/** Drop all historical stats and stop tracking any active sessions for the specified app. */
public void clearAppStatsLocked(int userId, @NonNull String packageName) {
mTrackedJobs.delete(userId, packageName);
@@ -766,7 +764,7 @@ public final class QuotaController extends StateController {
if (!jobStatus.shouldTreatAsExpeditedJob()) {
// If quota is currently "free", then the job can run for the full amount of time,
// regardless of bucket (hence using charging instead of isQuotaFreeLocked()).
- if (mChargeTracker.isChargingLocked()
+ if (mService.isBatteryCharging()
|| mTopAppCache.get(jobStatus.getSourceUid())
|| isTopStartedJobLocked(jobStatus)
|| isUidInForeground(jobStatus.getSourceUid())) {
@@ -777,7 +775,7 @@ public final class QuotaController extends StateController {
}
// Expedited job.
- if (mChargeTracker.isChargingLocked()) {
+ if (mService.isBatteryCharging()) {
return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
}
if (mTopAppCache.get(jobStatus.getSourceUid()) || isTopStartedJobLocked(jobStatus)) {
@@ -864,7 +862,7 @@ public final class QuotaController extends StateController {
@GuardedBy("mLock")
private boolean isQuotaFreeLocked(final int standbyBucket) {
// Quota constraint is not enforced while charging.
- if (mChargeTracker.isChargingLocked()) {
+ if (mService.isBatteryCharging()) {
// Restricted jobs require additional constraints when charging, so don't immediately
// mark quota as free when charging.
return standbyBucket != RESTRICTED_INDEX;
@@ -1538,15 +1536,19 @@ public final class QuotaController extends StateController {
private void handleNewChargingStateLocked() {
mTimerChargingUpdateFunctor.setStatus(sElapsedRealtimeClock.millis(),
- mChargeTracker.isChargingLocked());
+ mService.isBatteryCharging());
if (DEBUG) {
- Slog.d(TAG, "handleNewChargingStateLocked: " + mChargeTracker.isChargingLocked());
+ Slog.d(TAG, "handleNewChargingStateLocked: " + mService.isBatteryCharging());
}
// Deal with Timers first.
mEJPkgTimers.forEach(mTimerChargingUpdateFunctor);
mPkgTimers.forEach(mTimerChargingUpdateFunctor);
- // Now update jobs.
- maybeUpdateAllConstraintsLocked();
+ // Now update jobs out of band so broadcast processing can proceed.
+ JobSchedulerBackgroundThread.getHandler().post(() -> {
+ synchronized (mLock) {
+ maybeUpdateAllConstraintsLocked();
+ }
+ });
}
private void maybeUpdateAllConstraintsLocked() {
@@ -1811,58 +1813,6 @@ public final class QuotaController extends StateController {
return false;
}
- private final class ChargingTracker extends BroadcastReceiver {
- /**
- * Track whether we're charging. This has a slightly different definition than that of
- * BatteryController.
- */
- @GuardedBy("mLock")
- private boolean mCharging;
-
- ChargingTracker() {
- }
-
- public void startTracking() {
- IntentFilter filter = new IntentFilter();
-
- // Charging/not charging.
- filter.addAction(BatteryManager.ACTION_CHARGING);
- filter.addAction(BatteryManager.ACTION_DISCHARGING);
- mContext.registerReceiver(this, filter);
-
- // Initialise tracker state.
- BatteryManagerInternal batteryManagerInternal =
- LocalServices.getService(BatteryManagerInternal.class);
- mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
- }
-
- @GuardedBy("mLock")
- public boolean isChargingLocked() {
- return mCharging;
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- synchronized (mLock) {
- final String action = intent.getAction();
- if (BatteryManager.ACTION_CHARGING.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Received charging intent, fired @ "
- + sElapsedRealtimeClock.millis());
- }
- mCharging = true;
- handleNewChargingStateLocked();
- } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
- if (DEBUG) {
- Slog.d(TAG, "Disconnected from power.");
- }
- mCharging = false;
- handleNewChargingStateLocked();
- }
- }
- }
- }
-
@VisibleForTesting
static final class TimingSession {
// Start timestamp in elapsed realtime timebase.
@@ -2127,6 +2077,12 @@ public final class QuotaController extends StateController {
final long topAppGracePeriodEndElapsed = mTopAppGraceCache.get(mUid);
final boolean hasTopAppExemption = !mRegularJobTimer
&& (mTopAppCache.get(mUid) || nowElapsed < topAppGracePeriodEndElapsed);
+ if (DEBUG) {
+ Slog.d(TAG, "quotaFree=" + isQuotaFreeLocked(standbyBucket)
+ + " isFG=" + mForegroundUids.get(mUid)
+ + " tempEx=" + hasTempAllowlistExemption
+ + " topEx=" + hasTopAppExemption);
+ }
return !isQuotaFreeLocked(standbyBucket)
&& !mForegroundUids.get(mUid) && !hasTempAllowlistExemption
&& !hasTopAppExemption;
@@ -3938,7 +3894,6 @@ public final class QuotaController extends StateController {
public void dumpControllerStateLocked(final IndentingPrintWriter pw,
final Predicate<JobStatus> predicate) {
pw.println("Is enabled: " + mIsEnabled);
- pw.println("Is charging: " + mChargeTracker.isChargingLocked());
pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis());
pw.println();
@@ -4116,7 +4071,7 @@ public final class QuotaController extends StateController {
final long mToken = proto.start(StateControllerProto.QUOTA);
proto.write(StateControllerProto.QuotaController.IS_CHARGING,
- mChargeTracker.isChargingLocked());
+ mService.isBatteryCharging());
proto.write(StateControllerProto.QuotaController.ELAPSED_REALTIME,
sElapsedRealtimeClock.millis());
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
index 5e73f42ff1cb..509fb6963a3c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StateController.java
@@ -133,6 +133,13 @@ public abstract class StateController {
}
/**
+ * Called when the battery status changes.
+ */
+ @GuardedBy("mLock")
+ public void onBatteryStateChangedLocked() {
+ }
+
+ /**
* Called when a UID's base bias has changed. The more positive the bias, the more
* important the UID is.
*/
diff --git a/apex/media/OWNERS b/apex/media/OWNERS
index bed38954a70c..2c5965c300e3 100644
--- a/apex/media/OWNERS
+++ b/apex/media/OWNERS
@@ -1,6 +1,5 @@
# Bug component: 1344
hdmoon@google.com
-hkuang@google.com
jinpark@google.com
klhyun@google.com
lnilsson@google.com
diff --git a/apex/media/framework/jarjar_rules.txt b/apex/media/framework/jarjar_rules.txt
index 1bd5b3616693..91489dcee0a1 100644
--- a/apex/media/framework/jarjar_rules.txt
+++ b/apex/media/framework/jarjar_rules.txt
@@ -1,4 +1,2 @@
rule com.android.modules.** android.media.internal.@1
rule com.google.android.exoplayer2.** android.media.internal.exo.@1
-rule com.google.common.** android.media.internal.guava_common.@1
-rule com.google.thirdparty.** android.media.internal.guava_thirdparty.@1
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index 7daebd0155a1..b6f85c7eac6f 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -62,8 +62,8 @@ import com.google.android.exoplayer2.extractor.wav.WavExtractor;
import com.google.android.exoplayer2.upstream.DataReader;
import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.TimestampAdjuster;
+import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.ColorInfo;
-import com.google.common.base.Ascii;
import java.io.EOFException;
import java.io.IOException;
@@ -978,7 +978,7 @@ public final class MediaParser {
@ParserName
public static List<String> getParserNames(@NonNull MediaFormat mediaFormat) {
String mimeType = mediaFormat.getString(MediaFormat.KEY_MIME);
- mimeType = mimeType == null ? null : Ascii.toLowerCase(mimeType);
+ mimeType = mimeType == null ? null : Util.toLowerInvariant(mimeType.trim());
if (TextUtils.isEmpty(mimeType)) {
// No MIME type provided. Return all.
return Collections.unmodifiableList(
@@ -1420,7 +1420,7 @@ public final class MediaParser {
int flags = 0;
TimestampAdjuster timestampAdjuster = null;
if (mIgnoreTimestampOffset) {
- timestampAdjuster = new TimestampAdjuster(TimestampAdjuster.MODE_NO_OFFSET);
+ timestampAdjuster = new TimestampAdjuster(TimestampAdjuster.DO_NOT_OFFSET);
}
switch (parserName) {
case PARSER_NAME_MATROSKA:
diff --git a/apex/media/framework/java/android/media/Session2CommandGroup.java b/apex/media/framework/java/android/media/Session2CommandGroup.java
index 13aabfc45ab7..af8184a27f0d 100644
--- a/apex/media/framework/java/android/media/Session2CommandGroup.java
+++ b/apex/media/framework/java/android/media/Session2CommandGroup.java
@@ -68,7 +68,7 @@ public final class Session2CommandGroup implements Parcelable {
/**
* Used by parcelable creator.
*/
- @SuppressWarnings("WeakerAccess") /* synthetic access */
+ @SuppressWarnings({"WeakerAccess", "UnsafeParcelApi"}) /* synthetic access */
Session2CommandGroup(Parcel in) {
Parcelable[] commands = in.readParcelableArray(Session2Command.class.getClassLoader());
if (commands != null) {
diff --git a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
index e48f234c5569..7d47e250f99d 100644
--- a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
+++ b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
@@ -79,7 +79,7 @@ public class MediaCommunicationService extends SystemService {
final Executor mRecordExecutor = Executors.newSingleThreadExecutor();
@GuardedBy("mLock")
- final List<CallbackRecord> mCallbackRecords = new ArrayList<>();
+ final ArrayList<CallbackRecord> mCallbackRecords = new ArrayList<>();
final NotificationManager mNotificationManager;
MediaSessionManager mSessionManager;
@@ -150,8 +150,8 @@ public class MediaCommunicationService extends SystemService {
return null;
}
- List<Session2Token> getSession2TokensLocked(int userId) {
- List<Session2Token> list = new ArrayList<>();
+ ArrayList<Session2Token> getSession2TokensLocked(int userId) {
+ ArrayList<Session2Token> list = new ArrayList<>();
if (userId == ALL.getIdentifier()) {
int size = mUserRecords.size();
for (int i = 0; i < size; i++) {
@@ -237,28 +237,29 @@ public class MediaCommunicationService extends SystemService {
}
void dispatchSession2Changed(int userId) {
- MediaParceledListSlice<Session2Token> allSession2Tokens;
- MediaParceledListSlice<Session2Token> userSession2Tokens;
+ ArrayList<Session2Token> allSession2Tokens;
+ ArrayList<Session2Token> userSession2Tokens;
synchronized (mLock) {
- allSession2Tokens =
- new MediaParceledListSlice<>(getSession2TokensLocked(ALL.getIdentifier()));
- userSession2Tokens = new MediaParceledListSlice<>(getSession2TokensLocked(userId));
- }
- allSession2Tokens.setInlineCountLimit(1);
- userSession2Tokens.setInlineCountLimit(1);
+ allSession2Tokens = getSession2TokensLocked(ALL.getIdentifier());
+ userSession2Tokens = getSession2TokensLocked(userId);
- synchronized (mLock) {
for (CallbackRecord record : mCallbackRecords) {
if (record.mUserId == ALL.getIdentifier()) {
try {
- record.mCallback.onSession2Changed(allSession2Tokens);
+ MediaParceledListSlice<Session2Token> toSend =
+ new MediaParceledListSlice<>(allSession2Tokens);
+ toSend.setInlineCountLimit(0);
+ record.mCallback.onSession2Changed(toSend);
} catch (RemoteException e) {
Log.w(TAG, "Failed to notify session2 tokens changed " + record);
}
} else if (record.mUserId == userId) {
try {
- record.mCallback.onSession2Changed(userSession2Tokens);
+ MediaParceledListSlice<Session2Token> toSend =
+ new MediaParceledListSlice<>(userSession2Tokens);
+ toSend.setInlineCountLimit(0);
+ record.mCallback.onSession2Changed(toSend);
} catch (RemoteException e) {
Log.w(TAG, "Failed to notify session2 tokens changed " + record);
}
@@ -382,7 +383,7 @@ public class MediaCommunicationService extends SystemService {
try {
// Check that they can make calls on behalf of the user and get the final user id
int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
- List<Session2Token> result;
+ ArrayList<Session2Token> result;
synchronized (mLock) {
result = getSession2TokensLocked(resolvedUserId);
}
diff --git a/api/Android.bp b/api/Android.bp
index 2e49a0c56778..70f995a44c86 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -24,6 +24,19 @@ package {
default_applicable_licenses: ["frameworks_base_license"],
}
+bootstrap_go_package {
+ name: "soong-api",
+ pkgPath: "android/soong/api",
+ deps: [
+ "blueprint",
+ "soong",
+ "soong-android",
+ "soong-genrule",
+ ],
+ srcs: ["api.go"],
+ pluginFor: ["soong_build"],
+}
+
python_defaults {
name: "python3_version_defaults",
version: {
diff --git a/api/api.go b/api/api.go
new file mode 100644
index 000000000000..976b140f407f
--- /dev/null
+++ b/api/api.go
@@ -0,0 +1,224 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package api
+
+import (
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+ "android/soong/genrule"
+)
+
+// The intention behind this soong plugin is to generate a number of "merged"
+// API-related modules that would otherwise require a large amount of very
+// similar Android.bp boilerplate to define. For example, the merged current.txt
+// API definitions (created by merging the non-updatable current.txt with all
+// the module current.txts). This simplifies the addition of new android
+// modules, by reducing the number of genrules etc a new module must be added to.
+
+// The properties of the combined_apis module type.
+type CombinedApisProperties struct {
+ // Module libraries that have public APIs
+ Public []string
+ // Module libraries that have system APIs
+ System []string
+ // Module libraries that have module_library APIs
+ Module_lib []string
+ // Module libraries that have system_server APIs
+ System_server []string
+ // ART module library. The only API library not removed from the filtered api database, because
+ // 1) ART apis are available by default to all modules, while other module-to-module deps are
+ // explicit and probably receive more scrutiny anyway
+ // 2) The number of ART/libcore APIs is large, so not linting them would create a large gap
+ // 3) It's a compromise. Ideally we wouldn't be filtering out any module APIs, and have
+ // per-module lint databases that excludes just that module's APIs. Alas, that's more
+ // difficult to achieve.
+ Art_module string
+}
+
+type CombinedApis struct {
+ android.ModuleBase
+
+ properties CombinedApisProperties
+}
+
+func init() {
+ registerBuildComponents(android.InitRegistrationContext)
+}
+
+func registerBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("combined_apis", combinedApisModuleFactory)
+}
+
+var PrepareForCombinedApisTest = android.FixtureRegisterWithContext(registerBuildComponents)
+
+func (a *CombinedApis) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+}
+
+type genruleProps struct {
+ Name *string
+ Cmd *string
+ Dists []android.Dist
+ Out []string
+ Srcs []string
+ Tools []string
+ Visibility []string
+}
+
+// Struct to pass parameters for the various merged [current|removed].txt file modules we create.
+type MergedTxtDefinition struct {
+ // "current.txt" or "removed.txt"
+ TxtFilename string
+ // The module for the non-updatable / non-module part of the api.
+ BaseTxt string
+ // The list of modules that are relevant for this merged txt.
+ Modules []string
+ // The output tag for each module to use.e.g. {.public.api.txt} for current.txt
+ ModuleTag string
+ // public, system, module-lib or system-server
+ Scope string
+}
+
+func createMergedTxt(ctx android.LoadHookContext, txt MergedTxtDefinition) {
+ metalavaCmd := "$(location metalava)"
+ // Silence reflection warnings. See b/168689341
+ metalavaCmd += " -J--add-opens=java.base/java.util=ALL-UNNAMED "
+ metalavaCmd += " --quiet --no-banner --format=v2 "
+
+ filename := txt.TxtFilename
+ if txt.Scope != "public" {
+ filename = txt.Scope + "-" + filename
+ }
+
+ props := genruleProps{}
+ props.Name = proptools.StringPtr(ctx.ModuleName() + "-" + filename)
+ props.Tools = []string{"metalava"}
+ props.Out = []string{txt.TxtFilename}
+ props.Cmd = proptools.StringPtr(metalavaCmd + "$(in) --api $(out)")
+ props.Srcs = createSrcs(txt.BaseTxt, txt.Modules, txt.ModuleTag)
+ props.Dists = []android.Dist{
+ {
+ Targets: []string{"droidcore"},
+ Dir: proptools.StringPtr("api"),
+ Dest: proptools.StringPtr(filename),
+ },
+ {
+ Targets: []string{"sdk"},
+ Dir: proptools.StringPtr("apistubs/android/" + txt.Scope + "/api"),
+ Dest: proptools.StringPtr(txt.TxtFilename),
+ },
+ }
+ props.Visibility = []string{"//visibility:public"}
+ ctx.CreateModule(genrule.GenRuleFactory, &props)
+}
+
+func createMergedStubsSrcjar(ctx android.LoadHookContext, modules []string) {
+ props := genruleProps{}
+ props.Name = proptools.StringPtr(ctx.ModuleName() + "-current.srcjar")
+ props.Tools = []string{"merge_zips"}
+ props.Out = []string{"current.srcjar"}
+ props.Cmd = proptools.StringPtr("$(location merge_zips) $(out) $(in)")
+ props.Srcs = createSrcs(":api-stubs-docs-non-updatable", modules, "{.public.stubs.source}")
+ props.Visibility = []string{"//visibility:private"} // Used by make module in //development, mind
+ ctx.CreateModule(genrule.GenRuleFactory, &props)
+}
+
+func createFilteredApiVersions(ctx android.LoadHookContext, modules []string) {
+ props := genruleProps{}
+ props.Name = proptools.StringPtr("api-versions-xml-public-filtered")
+ props.Tools = []string{"api_versions_trimmer"}
+ props.Out = []string{"api-versions-public-filtered.xml"}
+ props.Cmd = proptools.StringPtr("$(location api_versions_trimmer) $(out) $(in)")
+ // Note: order matters: first parameter is the full api-versions.xml
+ // after that the stubs files in any order
+ // stubs files are all modules that export API surfaces EXCEPT ART
+ props.Srcs = createSrcs(":framework-doc-stubs{.api_versions.xml}", modules, ".stubs{.jar}")
+ props.Dists = []android.Dist{{Targets: []string{"sdk"}}}
+ ctx.CreateModule(genrule.GenRuleFactory, &props)
+}
+
+func createSrcs(base string, modules []string, tag string) []string {
+ a := make([]string, 0, len(modules)+1)
+ a = append(a, base)
+ for _, module := range modules {
+ a = append(a, ":"+module+tag)
+ }
+ return a
+}
+
+func remove(s []string, v string) []string {
+ s2 := make([]string, 0, len(s))
+ for _, sv := range s {
+ if sv != v {
+ s2 = append(s2, sv)
+ }
+ }
+ return s2
+}
+
+func createMergedTxts(ctx android.LoadHookContext, props CombinedApisProperties) {
+ var textFiles []MergedTxtDefinition
+ tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
+ for i, f := range []string{"current.txt", "removed.txt"} {
+ textFiles = append(textFiles, MergedTxtDefinition{
+ TxtFilename: f,
+ BaseTxt: ":non-updatable-" + f,
+ Modules: props.Public,
+ ModuleTag: "{.public" + tagSuffix[i],
+ Scope: "public",
+ })
+ textFiles = append(textFiles, MergedTxtDefinition{
+ TxtFilename: f,
+ BaseTxt: ":non-updatable-system-" + f,
+ Modules: props.System,
+ ModuleTag: "{.system" + tagSuffix[i],
+ Scope: "system",
+ })
+ textFiles = append(textFiles, MergedTxtDefinition{
+ TxtFilename: f,
+ BaseTxt: ":non-updatable-module-lib-" + f,
+ Modules: props.Module_lib,
+ ModuleTag: "{.module-lib" + tagSuffix[i],
+ Scope: "module-lib",
+ })
+ textFiles = append(textFiles, MergedTxtDefinition{
+ TxtFilename: f,
+ BaseTxt: ":non-updatable-system-server-" + f,
+ Modules: props.System_server,
+ ModuleTag: "{.system-server" + tagSuffix[i],
+ Scope: "system-server",
+ })
+ }
+ for _, txt := range textFiles {
+ createMergedTxt(ctx, txt)
+ }
+}
+
+func (a *CombinedApis) createInternalModules(ctx android.LoadHookContext) {
+ createMergedTxts(ctx, a.properties)
+
+ createMergedStubsSrcjar(ctx, a.properties.Public)
+
+ // For the filtered api versions, we prune all APIs except art module's APIs.
+ createFilteredApiVersions(ctx, remove(a.properties.Public, a.properties.Art_module))
+}
+
+func combinedApisModuleFactory() android.Module {
+ module := &CombinedApis{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidModule(module)
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.createInternalModules(ctx) })
+ return module
+}
diff --git a/core/api/current.txt b/core/api/current.txt
index edf69449f4e9..8557e90d6328 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1312,6 +1312,7 @@ package android {
field public static final int shouldDisableView = 16843246; // 0x10101ee
field public static final int shouldUseDefaultUnfoldTransition = 16844364; // 0x101064c
field public static final int showAsAction = 16843481; // 0x10102d9
+ field public static final int showClockAndComplications;
field public static final int showDefault = 16843258; // 0x10101fa
field public static final int showDividers = 16843561; // 0x1010329
field public static final int showForAllUsers = 16844015; // 0x10104ef
@@ -9742,13 +9743,14 @@ package android.bluetooth {
field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
- field public static final int ERROR_FEATURE_NOT_SUPPORTED = 10; // 0xa
- field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101; // 0x65
- field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102; // 0x66
+ field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 200; // 0xc8
+ field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 201; // 0xc9
field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
field public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; // 0x8
field public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; // 0x9
field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff
+ field public static final int FEATURE_NOT_SUPPORTED = 11; // 0xb
+ field public static final int FEATURE_SUPPORTED = 10; // 0xa
field public static final int SUCCESS = 0; // 0x0
}
@@ -10875,6 +10877,8 @@ package android.content {
method @Deprecated @RequiresPermission(allOf={"android.permission.INTERACT_ACROSS_USERS", android.Manifest.permission.BROADCAST_STICKY}) public abstract void removeStickyBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle);
method public abstract void revokeUriPermission(android.net.Uri, int);
method public abstract void revokeUriPermission(String, android.net.Uri, int);
+ method public void selfRevokePermission(@NonNull String);
+ method public void selfRevokePermissions(@NonNull java.util.Collection<java.lang.String>);
method public abstract void sendBroadcast(@RequiresPermission android.content.Intent);
method public abstract void sendBroadcast(@RequiresPermission android.content.Intent, @Nullable String);
method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle);
@@ -12761,11 +12765,16 @@ package android.content.pm {
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
field public static final int INVALID_ID = -1; // 0xffffffff
- field public static final int STAGED_SESSION_ACTIVATION_FAILED = 2; // 0x2
- field public static final int STAGED_SESSION_CONFLICT = 4; // 0x4
- field public static final int STAGED_SESSION_NO_ERROR = 0; // 0x0
- field public static final int STAGED_SESSION_UNKNOWN = 3; // 0x3
- field public static final int STAGED_SESSION_VERIFICATION_FAILED = 1; // 0x1
+ field public static final int SESSION_ACTIVATION_FAILED = 2; // 0x2
+ field public static final int SESSION_CONFLICT = 4; // 0x4
+ field public static final int SESSION_NO_ERROR = 0; // 0x0
+ field public static final int SESSION_UNKNOWN_ERROR = 3; // 0x3
+ field public static final int SESSION_VERIFICATION_FAILED = 1; // 0x1
+ field @Deprecated public static final int STAGED_SESSION_ACTIVATION_FAILED = 2; // 0x2
+ field @Deprecated public static final int STAGED_SESSION_CONFLICT = 4; // 0x4
+ field @Deprecated public static final int STAGED_SESSION_NO_ERROR = 0; // 0x0
+ field @Deprecated public static final int STAGED_SESSION_UNKNOWN = 3; // 0x3
+ field @Deprecated public static final int STAGED_SESSION_VERIFICATION_FAILED = 1; // 0x1
}
public static class PackageInstaller.SessionParams implements android.os.Parcelable {
@@ -21893,16 +21902,29 @@ package android.media {
method public android.media.Image acquireNextImage();
method public void close();
method public void discardFreeBuffers();
+ method public long getDataSpace();
+ method public int getHardwareBufferFormat();
method public int getHeight();
method public int getImageFormat();
method public int getMaxImages();
method public android.view.Surface getSurface();
+ method public long getUsage();
method public int getWidth();
method @NonNull public static android.media.ImageReader newInstance(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int);
method @NonNull public static android.media.ImageReader newInstance(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int, long);
method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);
}
+ public static final class ImageReader.Builder {
+ ctor public ImageReader.Builder(@IntRange(from=1) int, @IntRange(from=1) int);
+ method @NonNull public android.media.ImageReader build();
+ method @NonNull public android.media.ImageReader.Builder setDefaultDataSpace(long);
+ method @NonNull public android.media.ImageReader.Builder setDefaultHardwareBufferFormat(int);
+ method @NonNull public android.media.ImageReader.Builder setImageFormat(int);
+ method @NonNull public android.media.ImageReader.Builder setMaxImages(int);
+ method @NonNull public android.media.ImageReader.Builder setUsage(long);
+ }
+
public static interface ImageReader.OnImageAvailableListener {
method public void onImageAvailable(android.media.ImageReader);
}
@@ -27363,11 +27385,13 @@ package android.net {
method @NonNull public android.net.VpnService.Builder addDnsServer(@NonNull java.net.InetAddress);
method @NonNull public android.net.VpnService.Builder addDnsServer(@NonNull String);
method @NonNull public android.net.VpnService.Builder addRoute(@NonNull java.net.InetAddress, int);
+ method @NonNull public android.net.VpnService.Builder addRoute(@NonNull android.net.IpPrefix);
method @NonNull public android.net.VpnService.Builder addRoute(@NonNull String, int);
method @NonNull public android.net.VpnService.Builder addSearchDomain(@NonNull String);
method @NonNull public android.net.VpnService.Builder allowBypass();
method @NonNull public android.net.VpnService.Builder allowFamily(int);
method @Nullable public android.os.ParcelFileDescriptor establish();
+ method @NonNull public android.net.VpnService.Builder excludeRoute(@NonNull android.net.IpPrefix);
method @NonNull public android.net.VpnService.Builder setBlocking(boolean);
method @NonNull public android.net.VpnService.Builder setConfigureIntent(@NonNull android.app.PendingIntent);
method @NonNull public android.net.VpnService.Builder setHttpProxy(@NonNull android.net.ProxyInfo);
@@ -27685,6 +27709,23 @@ package android.net.sip {
package android.net.vcn {
+ public final class VcnCellUnderlyingNetworkTemplate extends android.net.vcn.VcnUnderlyingNetworkTemplate {
+ method @NonNull public java.util.Set<java.lang.String> getOperatorPlmnIds();
+ method public int getOpportunistic();
+ method public int getRoaming();
+ method @NonNull public java.util.Set<java.lang.Integer> getSimSpecificCarrierIds();
+ }
+
+ public static final class VcnCellUnderlyingNetworkTemplate.Builder {
+ ctor public VcnCellUnderlyingNetworkTemplate.Builder();
+ method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate build();
+ method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setMetered(int);
+ method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setOperatorPlmnIds(@NonNull java.util.Set<java.lang.String>);
+ method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setOpportunistic(int);
+ method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setRoaming(int);
+ method @NonNull public android.net.vcn.VcnCellUnderlyingNetworkTemplate.Builder setSimSpecificCarrierIds(@NonNull java.util.Set<java.lang.Integer>);
+ }
+
public final class VcnConfig implements android.os.Parcelable {
method public int describeContents();
method @NonNull public java.util.Set<android.net.vcn.VcnGatewayConnectionConfig> getGatewayConnectionConfigs();
@@ -27703,6 +27744,7 @@ package android.net.vcn {
method @NonNull public String getGatewayConnectionName();
method @IntRange(from=0x500) public int getMaxMtu();
method @NonNull public long[] getRetryIntervalsMillis();
+ method @NonNull public java.util.List<android.net.vcn.VcnUnderlyingNetworkTemplate> getVcnUnderlyingNetworkPriorities();
}
public static final class VcnGatewayConnectionConfig.Builder {
@@ -27712,6 +27754,7 @@ package android.net.vcn {
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int);
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=0x500) int);
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setRetryIntervalsMillis(@NonNull long[]);
+ method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setVcnUnderlyingNetworkPriorities(@NonNull java.util.List<android.net.vcn.VcnUnderlyingNetworkTemplate>);
}
public class VcnManager {
@@ -27735,6 +27778,24 @@ package android.net.vcn {
method public abstract void onStatusChanged(int);
}
+ public abstract class VcnUnderlyingNetworkTemplate {
+ method public int getMetered();
+ field public static final int MATCH_ANY = 0; // 0x0
+ field public static final int MATCH_FORBIDDEN = 2; // 0x2
+ field public static final int MATCH_REQUIRED = 1; // 0x1
+ }
+
+ public final class VcnWifiUnderlyingNetworkTemplate extends android.net.vcn.VcnUnderlyingNetworkTemplate {
+ method @NonNull public java.util.Set<java.lang.String> getSsids();
+ }
+
+ public static final class VcnWifiUnderlyingNetworkTemplate.Builder {
+ ctor public VcnWifiUnderlyingNetworkTemplate.Builder();
+ method @NonNull public android.net.vcn.VcnWifiUnderlyingNetworkTemplate build();
+ method @NonNull public android.net.vcn.VcnWifiUnderlyingNetworkTemplate.Builder setMetered(int);
+ method @NonNull public android.net.vcn.VcnWifiUnderlyingNetworkTemplate.Builder setSsids(@NonNull java.util.Set<java.lang.String>);
+ }
+
}
package android.nfc {
@@ -40267,6 +40328,7 @@ package android.telecom {
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 2048; // 0x800
field public static final int PROPERTY_RTT = 1024; // 0x400
field public static final int PROPERTY_SELF_MANAGED = 256; // 0x100
+ field public static final int PROPERTY_TETHERED_CALL = 32768; // 0x8000
field public static final int PROPERTY_VOIP_AUDIO_MODE = 4096; // 0x1000
field public static final int PROPERTY_WIFI = 8; // 0x8
}
@@ -40295,6 +40357,7 @@ package android.telecom {
field @NonNull public static final android.os.Parcelable.Creator<android.telecom.CallAudioState> CREATOR;
field public static final int ROUTE_BLUETOOTH = 2; // 0x2
field public static final int ROUTE_EARPIECE = 1; // 0x1
+ field public static final int ROUTE_EXTERNAL = 16; // 0x10
field public static final int ROUTE_SPEAKER = 8; // 0x8
field public static final int ROUTE_WIRED_HEADSET = 4; // 0x4
field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
@@ -40569,6 +40632,7 @@ package android.telecom {
field public static final int PROPERTY_IS_RTT = 256; // 0x100
field public static final int PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL = 1024; // 0x400
field public static final int PROPERTY_SELF_MANAGED = 128; // 0x80
+ field public static final int PROPERTY_TETHERED_CALL = 16384; // 0x4000
field public static final int PROPERTY_WIFI = 8; // 0x8
field public static final int STATE_ACTIVE = 4; // 0x4
field public static final int STATE_DIALING = 3; // 0x3
@@ -41662,21 +41726,101 @@ package android.telephony {
field public static final String PROTOCOL_IPV6 = "IPV6";
}
+ public static final class CarrierConfigManager.Bsf {
+ field public static final String KEY_BSF_SERVER_FQDN_STRING = "bsf.bsf_server_fqdn_string";
+ field public static final String KEY_BSF_SERVER_PORT_INT = "bsf.bsf_server_port_int";
+ field public static final String KEY_BSF_TRANSPORT_TYPE_INT = "bsf.bsf_transport type_int";
+ field public static final String KEY_PREFIX = "bsf.";
+ }
+
public static final class CarrierConfigManager.Gps {
field public static final String KEY_PERSIST_LPP_MODE_BOOL = "gps.persist_lpp_mode_bool";
field public static final String KEY_PREFIX = "gps.";
}
public static final class CarrierConfigManager.Ims {
+ field public static final int E911_RTCP_INACTIVITY_ON_CONNECTED = 3; // 0x3
+ field public static final int E911_RTP_INACTIVITY_ON_CONNECTED = 4; // 0x4
+ field public static final int GEOLOCATION_PIDF_FOR_EMERGENCY_ON_CELLULAR = 4; // 0x4
+ field public static final int GEOLOCATION_PIDF_FOR_EMERGENCY_ON_WIFI = 2; // 0x2
+ field public static final int GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_CELLULAR = 3; // 0x3
+ field public static final int GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_WIFI = 1; // 0x1
+ field public static final int IPSEC_AUTHENTICATION_ALGORITHM_HMAC_MD5 = 0; // 0x0
+ field public static final int IPSEC_AUTHENTICATION_ALGORITHM_HMAC_SHA1 = 1; // 0x1
+ field public static final int IPSEC_ENCRYPTION_ALGORITHM_AES_CBC = 2; // 0x2
+ field public static final int IPSEC_ENCRYPTION_ALGORITHM_DES_EDE3_CBC = 1; // 0x1
+ field public static final int IPSEC_ENCRYPTION_ALGORITHM_NULL = 0; // 0x0
field public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL = "ims.enable_presence_capability_exchange_bool";
field public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL = "ims.enable_presence_group_subscribe_bool";
field public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL = "ims.enable_presence_publish_bool";
+ field public static final String KEY_GEOLOCATION_PIDF_IN_SIP_INVITE_SUPPORT_INT_ARRAY = "ims.geolocation_pidf_in_sip_invite_support_int_array";
+ field public static final String KEY_GEOLOCATION_PIDF_IN_SIP_REGISTER_SUPPORT_INT_ARRAY = "ims.geolocation_pidf_in_sip_register_support_int_array";
+ field public static final String KEY_GRUU_ENABLED_BOOL = "ims.gruu_enabled_bool";
+ field public static final String KEY_IMS_PDN_ENABLED_IN_NO_VOPS_SUPPORT_INT_ARRAY = "ims.ims_pdn_enabled_in_no_vops_support_int_array";
field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
+ field public static final String KEY_IMS_USER_AGENT_STRING = "ims.ims_user_agent_string";
+ field public static final String KEY_IPSEC_AUTHENTICATION_ALGORITHMS_INT_ARRAY = "ims.ipsec_authentication_algorithms_int_array";
+ field public static final String KEY_IPSEC_ENCRYPTION_ALGORITHMS_INT_ARRAY = "ims.ipsec_encryption_algorithms_int_array";
+ field public static final String KEY_IPV4_SIP_MTU_SIZE_CELLULAR_INT = "ims.ipv4_sip_mtu_size_cellular_int";
+ field public static final String KEY_IPV6_SIP_MTU_SIZE_CELLULAR_INT = "ims.ipv6_sip_mtu_size_cellular_int";
+ field public static final String KEY_KEEP_PDN_UP_IN_NO_VOPS_BOOL = "ims.keep_pdn_up_in_no_vops_bool";
field public static final String KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT = "ims.non_rcs_capabilities_cache_expiration_sec_int";
+ field public static final String KEY_PHONE_CONTEXT_DOMAIN_NAME_STRING = "ims.phone_context_domain_name_string";
field public static final String KEY_PREFIX = "ims.";
field public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL = "ims.rcs_bulk_capability_exchange_bool";
field public static final String KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY = "ims.rcs_feature_tag_allowed_string_array";
+ field public static final String KEY_REGISTRATION_EVENT_PACKAGE_SUPPORTED_BOOL = "ims.registration_event_package_supported_bool";
+ field public static final String KEY_REGISTRATION_EXPIRY_TIMER_SEC_INT = "ims.registration_expiry_timer_sec_int";
+ field public static final String KEY_REGISTRATION_RETRY_BASE_TIMER_MILLIS_INT = "ims.registration_retry_base_timer_millis_int";
+ field public static final String KEY_REGISTRATION_RETRY_MAX_TIMER_MILLIS_INT = "ims.registration_retry_max_timer_millis_int";
+ field public static final String KEY_REGISTRATION_SUBSCRIBE_EXPIRY_TIMER_SEC_INT = "ims.registration_subscribe_expiry_timer_sec_int";
+ field public static final String KEY_REQUEST_URI_TYPE_INT = "ims.request_uri_type_int";
+ field public static final String KEY_SIP_OVER_IPSEC_ENABLED_BOOL = "ims.sip_over_ipsec_enabled_bool";
+ field public static final String KEY_SIP_PREFERRED_TRANSPORT_INT = "ims.sip_preferred_transport_int";
+ field public static final String KEY_SIP_SERVER_PORT_NUMBER_INT = "ims.sip_server_port_number_int";
+ field public static final String KEY_SIP_TIMER_B_MILLIS_INT = "ims.sip_timer_b_millis_int";
+ field public static final String KEY_SIP_TIMER_C_MILLIS_INT = "ims.sip_timer_c_millis_int";
+ field public static final String KEY_SIP_TIMER_D_MILLIS_INT = "ims.sip_timer_d_millis_int";
+ field public static final String KEY_SIP_TIMER_F_MILLIS_INT = "ims.sip_timer_f_millis_int";
+ field public static final String KEY_SIP_TIMER_H_MILLIS_INT = "ims.sip_timer_h_millis_int";
+ field public static final String KEY_SIP_TIMER_J_MILLIS_INT = "ims.sip_timer_j_millis_int";
+ field public static final String KEY_SIP_TIMER_T1_MILLIS_INT = "ims.sip_timer_t1_millis_int";
+ field public static final String KEY_SIP_TIMER_T2_MILLIS_INT = "ims.sip_timer_t2_millis_int";
+ field public static final String KEY_SIP_TIMER_T4_MILLIS_INT = "ims.sip_timer_t4_millis_int";
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
+ field public static final int NETWORK_TYPE_HOME = 0; // 0x0
+ field public static final int NETWORK_TYPE_ROAMING = 1; // 0x1
+ field public static final int PREFERRED_TRANSPORT_DYNAMIC_UDP_TCP = 2; // 0x2
+ field public static final int PREFERRED_TRANSPORT_TCP = 1; // 0x1
+ field public static final int PREFERRED_TRANSPORT_TLS = 3; // 0x3
+ field public static final int PREFERRED_TRANSPORT_UDP = 0; // 0x0
+ field public static final int REQUEST_URI_FORMAT_SIP = 1; // 0x1
+ field public static final int REQUEST_URI_FORMAT_TEL = 0; // 0x0
+ field public static final int RTCP_INACTIVITY_ON_CONNECTED = 1; // 0x1
+ field public static final int RTCP_INACTIVITY_ON_HOLD = 0; // 0x0
+ field public static final int RTP_INACTIVITY_ON_CONNECTED = 2; // 0x2
+ }
+
+ public static final class CarrierConfigManager.ImsEmergency {
+ field public static final String KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL = "imsemergency.emergency_callback_mode_supported_bool";
+ field public static final String KEY_EMERGENCY_OVER_IMS_SUPPORTED_RATS_INT_ARRAY = "imsemergency.emergency_over_ims_supported_rats_int_array";
+ field public static final String KEY_EMERGENCY_QOS_PRECONDITION_SUPPORTED_BOOL = "imsemergency.emergency_qos_precondition_supported_bool";
+ field public static final String KEY_EMERGENCY_REGISTRATION_TIMER_MILLIS_INT = "imsemergency.emergency_registration_timer_millis_int";
+ field public static final String KEY_PREFIX = "imsemergency.";
+ field public static final String KEY_RETRY_EMERGENCY_ON_IMS_PDN_BOOL = "imsemergency.retry_emergency_on_ims_pdn_bool";
+ }
+
+ public static final class CarrierConfigManager.ImsRtt {
+ field public static final String KEY_PREFIX = "imsrtt.";
+ field public static final String KEY_RED_PAYLOAD_TYPE_INT = "imsrtt.red_payload_type_int";
+ field public static final String KEY_T140_PAYLOAD_TYPE_INT = "imsrtt.t140_payload_type_int";
+ field public static final String KEY_TEXT_AS_BANDWIDTH_KBPS_INT = "imsrtt.text_as_bandwidth_kbps_int";
+ field public static final String KEY_TEXT_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE = "imsrtt.text_codec_capability_payload_types_bundle";
+ field public static final String KEY_TEXT_INACTIVITY_CALL_END_REASONS_INT_ARRAY = "imsrtt.text_inactivity_call_end_reasons_int_array";
+ field public static final String KEY_TEXT_ON_DEFAULT_BEARER_SUPPORTED_BOOL = "imsrtt.text_on_default_bearer_supported_bool";
+ field public static final String KEY_TEXT_QOS_PRECONDITION_SUPPORTED_BOOL = "imsrtt.text_qos_precondition_supported_bool";
+ field public static final String KEY_TEXT_RR_BANDWIDTH_BPS_INT = "imsrtt.text_rr_bandwidth_bps_int";
+ field public static final String KEY_TEXT_RS_BANDWIDTH_BPS_INT = "imsrtt.text_rs_bandwidth_bps_int";
}
public static final class CarrierConfigManager.ImsServiceEntitlement {
@@ -41687,6 +41831,167 @@ package android.telephony {
field public static final String KEY_SHOW_VOWIFI_WEBVIEW_BOOL = "imsserviceentitlement.show_vowifi_webview_bool";
}
+ public static final class CarrierConfigManager.ImsSms {
+ field public static final String KEY_PREFIX = "imssms.";
+ field public static final String KEY_SMS_CSFB_RETRY_ON_FAILURE_BOOL = "imssms.sms_csfb_retry_on_failure_bool";
+ field public static final String KEY_SMS_OVER_IMS_FORMAT_INT = "imssms.sms_over_ims_format_int";
+ field public static final String KEY_SMS_OVER_IMS_SUPPORTED_BOOL = "imssms.sms_over_ims_supported_bool";
+ field public static final String KEY_SMS_OVER_IMS_SUPPORTED_RATS_INT_ARRAY = "imssms.sms_over_ims_supported_rats_int_array";
+ field public static final int SMS_FORMAT_3GPP = 0; // 0x0
+ field public static final int SMS_FORMAT_3GPP2 = 1; // 0x1
+ }
+
+ public static final class CarrierConfigManager.ImsSs {
+ field public static final String KEY_NETWORK_INITIATED_USSD_OVER_IMS_SUPPORTED_BOOL = "imsss.network_initiated_ussd_over_ims_supported_bool";
+ field public static final String KEY_PREFIX = "imsss.";
+ field public static final String KEY_USE_CSFB_ON_XCAP_OVER_UT_FAILURE_BOOL = "imsss.use_csfb_on_xcap_over_ut_failure_bool";
+ field public static final String KEY_UT_AS_SERVER_FQDN_STRING = "imsss.ut_as_server_fqdn_string";
+ field public static final String KEY_UT_AS_SERVER_PORT_INT = "imsss.ut_as_server_port_int";
+ field public static final String KEY_UT_IPTYPE_HOME_INT = "imsss.ut_iptype_home_int";
+ field public static final String KEY_UT_IPTYPE_ROAMING_INT = "imsss.ut_iptype_roaming_int";
+ field public static final String KEY_UT_REQUIRES_IMS_REGISTRATION_BOOL = "imsss.ut_requires_ims_registration_bool";
+ field public static final String KEY_UT_SERVER_BASED_SERVICES_INT_ARRAY = "imsss.ut_server_based_services_int_array";
+ field public static final String KEY_UT_SUPPORTED_WHEN_PS_DATA_OFF_BOOL = "imsss.ut_supported_when_ps_data_off_bool";
+ field public static final String KEY_UT_TERMINAL_BASED_SERVICES_INT_ARRAY = "imsss.ut_terminal_based_services_int_array";
+ field public static final String KEY_UT_TRANSPORT_TYPE_INT = "imsss.ut_transport_type_int";
+ field public static final String KEY_XCAP_OVER_UT_SUPPORTED_RATS_INT_ARRAY = "imsss.xcap_over_ut_supported_rats_int_array";
+ field public static final int SUPPLEMENTARY_SERVICE_CB_ACR = 20; // 0x14
+ field public static final int SUPPLEMENTARY_SERVICE_CB_ALL = 12; // 0xc
+ field public static final int SUPPLEMENTARY_SERVICE_CB_BAIC = 18; // 0x12
+ field public static final int SUPPLEMENTARY_SERVICE_CB_BAOC = 14; // 0xe
+ field public static final int SUPPLEMENTARY_SERVICE_CB_BIC_ROAM = 19; // 0x13
+ field public static final int SUPPLEMENTARY_SERVICE_CB_BIL = 21; // 0x15
+ field public static final int SUPPLEMENTARY_SERVICE_CB_BOIC = 15; // 0xf
+ field public static final int SUPPLEMENTARY_SERVICE_CB_BOIC_EXHC = 16; // 0x10
+ field public static final int SUPPLEMENTARY_SERVICE_CB_IBS = 17; // 0x11
+ field public static final int SUPPLEMENTARY_SERVICE_CB_OBS = 13; // 0xd
+ field public static final int SUPPLEMENTARY_SERVICE_CF_ALL = 1; // 0x1
+ field public static final int SUPPLEMENTARY_SERVICE_CF_ALL_CONDITONAL_FORWARDING = 3; // 0x3
+ field public static final int SUPPLEMENTARY_SERVICE_CF_CFB = 4; // 0x4
+ field public static final int SUPPLEMENTARY_SERVICE_CF_CFNL = 7; // 0x7
+ field public static final int SUPPLEMENTARY_SERVICE_CF_CFNRC = 6; // 0x6
+ field public static final int SUPPLEMENTARY_SERVICE_CF_CFNRY = 5; // 0x5
+ field public static final int SUPPLEMENTARY_SERVICE_CF_CFU = 2; // 0x2
+ field public static final int SUPPLEMENTARY_SERVICE_CW = 0; // 0x0
+ field public static final int SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIP = 8; // 0x8
+ field public static final int SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIR = 10; // 0xa
+ field public static final int SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIP = 9; // 0x9
+ field public static final int SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIR = 11; // 0xb
+ }
+
+ public static final class CarrierConfigManager.ImsVoice {
+ field public static final int ALERTING_SRVCC_SUPPORT = 1; // 0x1
+ field public static final int BANDWIDTH_EFFICIENT = 0; // 0x0
+ field public static final int BASIC_SRVCC_SUPPORT = 0; // 0x0
+ field public static final int CONFERENCE_SUBSCRIBE_TYPE_IN_DIALOG = 0; // 0x0
+ field public static final int CONFERENCE_SUBSCRIBE_TYPE_OUT_OF_DIALOG = 1; // 0x1
+ field public static final int EVS_ENCODED_BW_TYPE_FB = 3; // 0x3
+ field public static final int EVS_ENCODED_BW_TYPE_NB = 0; // 0x0
+ field public static final int EVS_ENCODED_BW_TYPE_NB_WB = 4; // 0x4
+ field public static final int EVS_ENCODED_BW_TYPE_NB_WB_SWB = 5; // 0x5
+ field public static final int EVS_ENCODED_BW_TYPE_NB_WB_SWB_FB = 6; // 0x6
+ field public static final int EVS_ENCODED_BW_TYPE_SWB = 2; // 0x2
+ field public static final int EVS_ENCODED_BW_TYPE_WB = 1; // 0x1
+ field public static final int EVS_ENCODED_BW_TYPE_WB_SWB = 7; // 0x7
+ field public static final int EVS_ENCODED_BW_TYPE_WB_SWB_FB = 8; // 0x8
+ field public static final int EVS_OPERATIONAL_MODE_AMRWB_IO = 1; // 0x1
+ field public static final int EVS_OPERATIONAL_MODE_PRIMARY = 0; // 0x0
+ field public static final int EVS_PRIMARY_MODE_BITRATE_128_0_KBPS = 11; // 0xb
+ field public static final int EVS_PRIMARY_MODE_BITRATE_13_2_KBPS = 4; // 0x4
+ field public static final int EVS_PRIMARY_MODE_BITRATE_16_4_KBPS = 5; // 0x5
+ field public static final int EVS_PRIMARY_MODE_BITRATE_24_4_KBPS = 6; // 0x6
+ field public static final int EVS_PRIMARY_MODE_BITRATE_32_0_KBPS = 7; // 0x7
+ field public static final int EVS_PRIMARY_MODE_BITRATE_48_0_KBPS = 8; // 0x8
+ field public static final int EVS_PRIMARY_MODE_BITRATE_5_9_KBPS = 0; // 0x0
+ field public static final int EVS_PRIMARY_MODE_BITRATE_64_0_KBPS = 9; // 0x9
+ field public static final int EVS_PRIMARY_MODE_BITRATE_7_2_KBPS = 1; // 0x1
+ field public static final int EVS_PRIMARY_MODE_BITRATE_8_0_KBPS = 2; // 0x2
+ field public static final int EVS_PRIMARY_MODE_BITRATE_96_0_KBPS = 10; // 0xa
+ field public static final int EVS_PRIMARY_MODE_BITRATE_9_6_KBPS = 3; // 0x3
+ field public static final String KEY_AMRNB_PAYLOAD_DESCRIPTION_BUNDLE = "imsvoice.amrnb_payload_description_bundle";
+ field public static final String KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY = "imsvoice.amrnb_payload_type_int_array";
+ field public static final String KEY_AMRWB_PAYLOAD_DESCRIPTION_BUNDLE = "imsvoice.amrwb_payload_description_bundle";
+ field public static final String KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY = "imsvoice.amrwb_payload_type_int_array";
+ field public static final String KEY_AMR_CODEC_ATTRIBUTE_MODESET_INT_ARRAY = "imsvoice.amr_codec_attribute_modeset_int_array";
+ field public static final String KEY_AMR_CODEC_ATTRIBUTE_PAYLOAD_FORMAT_INT = "imsvoice.amr_codec_attribute_payload_format_int";
+ field public static final String KEY_AUDIO_AS_BANDWIDTH_KBPS_INT = "imsvoice.audio_as_bandwidth_kbps_int";
+ field public static final String KEY_AUDIO_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE = "imsvoice.audio_codec_capability_payload_types_bundle";
+ field public static final String KEY_AUDIO_INACTIVITY_CALL_END_REASONS_INT_ARRAY = "imsvoice.audio_inactivity_call_end_reasons_int_array";
+ field public static final String KEY_AUDIO_RR_BANDWIDTH_BPS_INT = "imsvoice.audio_rr_bandwidth_bps_int";
+ field public static final String KEY_AUDIO_RS_BANDWIDTH_BPS_INT = "imsvoice.audio_rs_bandwidth_bps_int";
+ field public static final String KEY_AUDIO_RTCP_INACTIVITY_TIMER_MILLIS_INT = "imsvoice.audio_rtcp_inactivity_timer_millis_int";
+ field public static final String KEY_AUDIO_RTP_INACTIVITY_TIMER_MILLIS_INT = "imsvoice.audio_rtp_inactivity_timer_millis_int";
+ field public static final String KEY_CARRIER_VOLTE_ROAMING_AVAILABLE_BOOL = "imsvoice.carrier_volte_roaming_available_bool";
+ field public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_CAPABILITY_INT = "imsvoice.codec_attribute_mode_change_capability_int";
+ field public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_NEIGHBOR_INT = "imsvoice.codec_attribute_mode_change_neighbor_int";
+ field public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_PERIOD_INT = "imsvoice.codec_attribute_mode_change_period_int";
+ field public static final String KEY_CONFERENCE_FACTORY_URI_STRING = "imsvoice.conference_factory_uri_string";
+ field public static final String KEY_CONFERENCE_SUBSCRIBE_TYPE_INT = "imsvoice.conference_subscribe_type_int";
+ field public static final String KEY_DEDICATED_BEARER_WAIT_TIMER_MILLIS_INT = "imsvoice.dedicated_bearer_wait_timer_millis_int";
+ field public static final String KEY_DTMFNB_PAYLOAD_TYPE_INT_ARRAY = "imsvoice.dtmfnb_payload_type_int_array";
+ field public static final String KEY_DTMFWB_PAYLOAD_TYPE_INT_ARRAY = "imsvoice.dtmfwb_payload_type_int_array";
+ field public static final String KEY_EVS_CODEC_ATTRIBUTE_BANDWIDTH_INT = "imsvoice.evs_codec_attribute_bandwidth_int";
+ field public static final String KEY_EVS_CODEC_ATTRIBUTE_BITRATE_INT_ARRAY = "imsvoice.evs_codec_attribute_bitrate_int_array";
+ field public static final String KEY_EVS_CODEC_ATTRIBUTE_CHANNELS_INT = "imsvoice.evs_codec_attribute_channels_int";
+ field public static final String KEY_EVS_CODEC_ATTRIBUTE_CH_AW_RECV_INT = "imsvoice.evs_codec_attribute_ch_aw_recv_int";
+ field public static final String KEY_EVS_CODEC_ATTRIBUTE_CMR_INT = "imsvoice.codec_attribute_cmr_int";
+ field public static final String KEY_EVS_CODEC_ATTRIBUTE_DTX_BOOL = "imsvoice.evs_codec_attribute_dtx_bool";
+ field public static final String KEY_EVS_CODEC_ATTRIBUTE_DTX_RECV_BOOL = "imsvoice.evs_codec_attribute_dtx_recv_bool";
+ field public static final String KEY_EVS_CODEC_ATTRIBUTE_HF_ONLY_INT = "imsvoice.evs_codec_attribute_hf_only_int";
+ field public static final String KEY_EVS_CODEC_ATTRIBUTE_MODE_SWITCH_INT = "imsvoice.evs_codec_attribute_mode_switch_int";
+ field public static final String KEY_EVS_PAYLOAD_DESCRIPTION_BUNDLE = "imsvoice.evs_payload_description_bundle";
+ field public static final String KEY_EVS_PAYLOAD_TYPE_INT_ARRAY = "imsvoice.evs_payload_type_int_array";
+ field public static final String KEY_INCLUDE_CALLER_ID_SERVICE_CODES_IN_SIP_INVITE_BOOL = "imsvoice.include_caller_id_service_codes_in_sip_invite_bool";
+ field public static final String KEY_MINIMUM_SESSION_EXPIRES_TIMER_SEC_INT = "imsvoice.minimum_session_expires_timer_sec_int";
+ field public static final String KEY_MO_CALL_REQUEST_TIMEOUT_MILLIS_INT = "imsvoice.mo_call_request_timeout_millis_int";
+ field public static final String KEY_MULTIENDPOINT_SUPPORTED_BOOL = "imsvoice.multiendpoint_supported_bool";
+ field public static final String KEY_OIP_SOURCE_FROM_HEADER_BOOL = "imsvoice.oip_source_from_header_bool";
+ field public static final String KEY_PRACK_SUPPORTED_FOR_18X_BOOL = "imsvoice.prack_supported_for_18x_bool";
+ field public static final String KEY_PREFIX = "imsvoice.";
+ field public static final String KEY_RINGBACK_TIMER_MILLIS_INT = "imsvoice.ringback_timer_millis_int";
+ field public static final String KEY_RINGING_TIMER_MILLIS_INT = "imsvoice.ringing_timer_millis_int";
+ field public static final String KEY_SESSION_EXPIRES_TIMER_SEC_INT = "imsvoice.session_expires_timer_sec_int";
+ field public static final String KEY_SESSION_REFRESHER_TYPE_INT = "imsvoice.session_refresher_type_int";
+ field public static final String KEY_SESSION_REFRESH_METHOD_INT = "imsvoice.session_refresh_method_int";
+ field public static final String KEY_SESSION_TIMER_SUPPORTED_BOOL = "imsvoice.session_timer_supported_bool";
+ field public static final String KEY_SRVCC_TYPE_INT_ARRAY = "imsvoice.srvcc_type_int_array";
+ field public static final String KEY_VOICE_ON_DEFAULT_BEARER_SUPPORTED_BOOL = "imsvoice.voice_on_default_bearer_supported_bool";
+ field public static final String KEY_VOICE_QOS_PRECONDITION_SUPPORTED_BOOL = "imsvoice.voice_qos_precondition_supported_bool";
+ field public static final int MIDCALL_SRVCC_SUPPORT = 3; // 0x3
+ field public static final int OCTET_ALIGNED = 1; // 0x1
+ field public static final int PREALERTING_SRVCC_SUPPORT = 2; // 0x2
+ field public static final int SESSION_REFRESHER_TYPE_UAC = 1; // 0x1
+ field public static final int SESSION_REFRESHER_TYPE_UAS = 2; // 0x2
+ field public static final int SESSION_REFRESHER_TYPE_UNKNOWN = 0; // 0x0
+ field public static final int SESSION_REFRESH_METHOD_INVITE = 0; // 0x0
+ field public static final int SESSION_REFRESH_METHOD_UPDATE_PREFERRED = 1; // 0x1
+ }
+
+ public static final class CarrierConfigManager.ImsVt {
+ field public static final String KEY_H264_PAYLOAD_DESCRIPTION_BUNDLE = "imsvt.h264_payload_description_bundle";
+ field public static final String KEY_H264_PAYLOAD_TYPE_INT_ARRAY = "imsvt.h264_payload_type_int_array";
+ field public static final String KEY_H264_VIDEO_CODEC_ATTRIBUTE_PROFILE_LEVEL_ID_STRING = "imsvt.h264_video_codec_attribute_profile_level_id_string";
+ field public static final String KEY_PREFIX = "imsvt.";
+ field public static final String KEY_VIDEO_AS_BANDWIDTH_KBPS_INT = "imsvt.video_as_bandwidth_kbps_int";
+ field public static final String KEY_VIDEO_CODEC_ATTRIBUTE_FRAME_RATE_INT = "imsvt.video_codec_attribute_frame_rate_int";
+ field public static final String KEY_VIDEO_CODEC_ATTRIBUTE_PACKETIZATION_MODE_INT = "imsvt.video_codec_attribute_packetization_mode_int";
+ field public static final String KEY_VIDEO_CODEC_ATTRIBUTE_RESOLUTION_INT_ARRAY = "imsvt.video_codec_attribute_resolution_int_array";
+ field public static final String KEY_VIDEO_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE = "imsvt.video_codec_capability_payload_types_bundle";
+ field public static final String KEY_VIDEO_ON_DEFAULT_BEARER_SUPPORTED_BOOL = "imsvt.video_on_default_bearer_supported_bool";
+ field public static final String KEY_VIDEO_QOS_PRECONDITION_SUPPORTED_BOOL = "imsvt.video_qos_precondition_supported_bool";
+ field public static final String KEY_VIDEO_RR_BANDWIDTH_BPS_INT = "imsvt.video_rr_bandwidth_bps_int";
+ field public static final String KEY_VIDEO_RS_BANDWIDTH_BPS_INT = "imsvt.video_rs_bandwidth_bps_int";
+ field public static final String KEY_VIDEO_RTCP_INACTIVITY_TIMER_MILLIS_INT = "imsvt.video_rtcp_inactivity_timer_millis_int";
+ field public static final String KEY_VIDEO_RTP_DSCP_INT = "imsvt.video_rtp_dscp_int";
+ field public static final String KEY_VIDEO_RTP_INACTIVITY_TIMER_MILLIS_INT = "imsvt.video_rtp_inactivity_timer_millis_int";
+ }
+
+ public static final class CarrierConfigManager.ImsWfc {
+ field public static final String KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL = "imswfc.emergency_call_over_emergency_pdn_bool";
+ field public static final String KEY_PIDF_SHORT_CODE_STRING_ARRAY = "imswfc.pidf_short_code_string_array";
+ field public static final String KEY_PREFIX = "imswfc.";
+ }
+
public static final class CarrierConfigManager.Iwlan {
field public static final int AUTHENTICATION_METHOD_CERT = 1; // 0x1
field public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0; // 0x0
@@ -51947,6 +52252,7 @@ package android.view.accessibility {
field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
field public static final int TYPE_APPLICATION = 1; // 0x1
field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+ field public static final int TYPE_MAGNIFICATION_OVERLAY = 6; // 0x6
field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
field public static final int TYPE_SYSTEM = 3; // 0x3
}
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 53bc8a6e0323..4d8453725205 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -88,6 +88,14 @@ package android.content {
field public static final String TEST_NETWORK_SERVICE = "test_network";
}
+ public class Intent implements java.lang.Cloneable android.os.Parcelable {
+ field public static final String ACTION_SETTING_RESTORED = "android.os.action.SETTING_RESTORED";
+ field public static final String EXTRA_SETTING_NAME = "setting_name";
+ field public static final String EXTRA_SETTING_NEW_VALUE = "new_value";
+ field public static final String EXTRA_SETTING_PREVIOUS_VALUE = "previous_value";
+ field public static final String EXTRA_SETTING_RESTORED_FROM_SDK_INT = "restored_from_sdk_int";
+ }
+
}
package android.content.pm {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e26d3c419039..3a7077dde0a5 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -165,6 +165,7 @@ package android {
field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
field public static final String MANAGE_ROTATION_RESOLVER = "android.permission.MANAGE_ROTATION_RESOLVER";
+ field public static final String MANAGE_SAFETY_CENTER = "android.permission.MANAGE_SAFETY_CENTER";
field public static final String MANAGE_SEARCH_UI = "android.permission.MANAGE_SEARCH_UI";
field public static final String MANAGE_SENSOR_PRIVACY = "android.permission.MANAGE_SENSOR_PRIVACY";
field public static final String MANAGE_SMARTSPACE = "android.permission.MANAGE_SMARTSPACE";
@@ -226,7 +227,6 @@ package android {
field public static final String READ_APP_SPECIFIC_LOCALES = "android.permission.READ_APP_SPECIFIC_LOCALES";
field public static final String READ_CARRIER_APP_INFO = "android.permission.READ_CARRIER_APP_INFO";
field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
- field public static final String READ_COMMUNAL_STATE = "android.permission.READ_COMMUNAL_STATE";
field public static final String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS";
field public static final String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG";
field public static final String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE";
@@ -404,6 +404,7 @@ package android {
field public static final int config_systemAmbientAudioIntelligence = 17039411; // 0x1040033
field public static final int config_systemAppProtectionService;
field public static final int config_systemAudioIntelligence = 17039412; // 0x1040034
+ field public static final int config_systemAutomotiveCalendarSyncManager;
field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
field public static final int config_systemCompanionDeviceProvider = 17039417; // 0x1040039
@@ -1046,6 +1047,7 @@ package android.app.admin {
field @Deprecated public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_LABEL";
field public static final String EXTRA_PROVISIONING_ORGANIZATION_NAME = "android.app.extra.PROVISIONING_ORGANIZATION_NAME";
field public static final String EXTRA_PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE = "android.app.extra.PROVISIONING_RETURN_BEFORE_POLICY_COMPLIANCE";
+ field public static final String EXTRA_PROVISIONING_ROLE_HOLDER_CUSTOM_USER_CONSENT_INTENT = "android.app.extra.PROVISIONING_ROLE_HOLDER_CUSTOM_USER_CONSENT_INTENT";
field public static final String EXTRA_PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER = "android.app.extra.PROVISIONING_SKIP_OWNERSHIP_DISCLAIMER";
field public static final String EXTRA_PROVISIONING_SUPPORTED_MODES = "android.app.extra.PROVISIONING_SUPPORTED_MODES";
field public static final String EXTRA_PROVISIONING_SUPPORT_URL = "android.app.extra.PROVISIONING_SUPPORT_URL";
@@ -1391,13 +1393,6 @@ package android.app.backup {
package android.app.communal {
public final class CommunalManager {
- method @RequiresPermission(android.Manifest.permission.READ_COMMUNAL_STATE) public void addCommunalModeListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.communal.CommunalManager.CommunalModeListener);
- method @RequiresPermission(android.Manifest.permission.READ_COMMUNAL_STATE) public boolean isCommunalMode();
- method @RequiresPermission(android.Manifest.permission.READ_COMMUNAL_STATE) public void removeCommunalModeListener(@NonNull android.app.communal.CommunalManager.CommunalModeListener);
- }
-
- @java.lang.FunctionalInterface public static interface CommunalManager.CommunalModeListener {
- method public void onCommunalModeChanged(boolean);
}
}
@@ -2226,9 +2221,12 @@ package android.bluetooth {
public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean connect(android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int connectAudio();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice);
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnectAudio();
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getAudioState(@NonNull android.bluetooth.BluetoothDevice);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInbandRingingEnabled();
+ method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isInbandRingingEnabled();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startScoUsingVirtualVoiceCall();
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean stopScoUsingVirtualVoiceCall();
@@ -2307,6 +2305,14 @@ package android.bluetooth {
public final class BluetoothStatusCodes {
field public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000; // 0x3e8
+ field public static final int ERROR_AUDIO_DEVICE_ALREADY_CONNECTED = 1116; // 0x45c
+ field public static final int ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED = 1117; // 0x45d
+ field public static final int ERROR_AUDIO_ROUTE_BLOCKED = 1118; // 0x45e
+ field public static final int ERROR_CALL_ACTIVE = 1119; // 0x45f
+ field public static final int ERROR_NOT_ACTIVE_DEVICE = 12; // 0xc
+ field public static final int ERROR_NO_ACTIVE_DEVICES = 13; // 0xd
+ field public static final int ERROR_PROFILE_NOT_CONNECTED = 14; // 0xe
+ field public static final int ERROR_TIMEOUT = 15; // 0xf
}
public final class BluetoothUuid {
@@ -2436,6 +2442,25 @@ package android.bluetooth {
package android.bluetooth.le {
+ public final class AdvertiseSettings implements android.os.Parcelable {
+ method public int getOwnAddressType();
+ }
+
+ public static final class AdvertiseSettings.Builder {
+ method @NonNull public android.bluetooth.le.AdvertiseSettings.Builder setOwnAddressType(int);
+ }
+
+ public final class AdvertisingSetParameters implements android.os.Parcelable {
+ method public int getOwnAddressType();
+ field public static final int ADDRESS_TYPE_DEFAULT = -1; // 0xffffffff
+ field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
+ field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
+ }
+
+ public static final class AdvertisingSetParameters.Builder {
+ method @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setOwnAddressType(int);
+ }
+
public final class BluetoothLeScanner {
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
@@ -3031,6 +3056,7 @@ package android.content.pm {
method @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS}) public abstract void updatePermissionFlags(@NonNull String, @NonNull String, @android.content.pm.PackageManager.PermissionFlags int, @android.content.pm.PackageManager.PermissionFlags int, @NonNull android.os.UserHandle);
method @Deprecated @RequiresPermission(android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT) public abstract void verifyIntentFilter(int, int, @NonNull java.util.List<java.lang.String>);
field public static final String ACTION_REQUEST_PERMISSIONS = "android.content.pm.action.REQUEST_PERMISSIONS";
+ field public static final String ACTION_REQUEST_PERMISSIONS_FOR_OTHER = "android.content.pm.action.REQUEST_PERMISSIONS_FOR_OTHER";
field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";
@@ -6323,6 +6349,7 @@ package android.media.tv {
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig);
method @NonNull public java.util.List<java.lang.String> getAvailableExtensionInterfaceNames(@NonNull String);
method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String);
+ method public int getClientPriority(int, @Nullable String);
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_TUNED_INFO) public java.util.List<android.media.tv.TunedInfo> getCurrentTunedInfos();
method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList();
method @Nullable public android.os.IBinder getExtensionInterface(@NonNull String, @NonNull String);
@@ -6442,7 +6469,9 @@ package android.media.tv.tuner {
}
public class Lnb implements java.lang.AutoCloseable {
+ method public void addCallback(@NonNull android.media.tv.tuner.LnbCallback, @NonNull java.util.concurrent.Executor);
method public void close();
+ method public boolean removeCallback(@NonNull android.media.tv.tuner.LnbCallback);
method public int sendDiseqcMessage(@NonNull byte[]);
method public int setSatellitePosition(int);
method public int setTone(int);
@@ -6479,6 +6508,7 @@ package android.media.tv.tuner {
method public void clearOnTuneEventListener();
method public void clearResourceLostListener();
method public void close();
+ method public void closeFrontend();
method public int connectCiCam(int);
method public int connectFrontendToCiCam(int);
method public int disconnectCiCam();
@@ -6507,6 +6537,7 @@ package android.media.tv.tuner {
method public void setOnTuneEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.OnTuneEventListener);
method public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener);
method public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner);
+ method public int transferOwner(@NonNull android.media.tv.tuner.Tuner);
method public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings);
method @RequiresPermission("android.permission.TUNER_RESOURCE_ACCESS") public void updateResourcePriority(int, int);
field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff
@@ -6720,8 +6751,8 @@ package android.media.tv.tuner.filter {
method @Nullable public String acquireSharedFilterToken();
method public void close();
method public int configure(@NonNull android.media.tv.tuner.filter.FilterConfiguration);
- method public int delayCallbackUntilBufferFilled(int);
- method public int delayCallbackUntilTimeMillis(long);
+ method public int delayCallbackUntilBytesAccumulated(int);
+ method public int delayCallbackUntilMillisElapsed(long);
method public int flush();
method public void freeSharedFilterToken(@NonNull String);
method @Deprecated public int getId();
@@ -6940,12 +6971,14 @@ package android.media.tv.tuner.filter {
}
public abstract class SectionSettings extends android.media.tv.tuner.filter.Settings {
+ method public int getBitWidthOfLengthField();
method public boolean isCrcEnabled();
method public boolean isRaw();
method public boolean isRepeat();
}
public abstract static class SectionSettings.Builder<T extends android.media.tv.tuner.filter.SectionSettings.Builder<T>> {
+ method @NonNull public T setBitWidthOfLengthField(@IntRange(from=0) int);
method @NonNull public T setCrcEnabled(boolean);
method @NonNull public T setRaw(boolean);
method @NonNull public T setRepeat(boolean);
@@ -9346,6 +9379,7 @@ package android.os {
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUserOfType(@NonNull String);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean isUserUnlockingOrUnlocked(@NonNull android.os.UserHandle);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean removeUser(@NonNull android.os.UserHandle);
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public int removeUserWhenPossible(@NonNull android.os.UserHandle, boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap) throws android.os.UserManager.UserOperationException;
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(@Nullable String);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean someUserHasAccount(@NonNull String, @NonNull String);
@@ -9353,6 +9387,10 @@ package android.os {
field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
field @Deprecated public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
+ field public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2; // 0x2
+ field public static final int REMOVE_RESULT_DEFERRED = 1; // 0x1
+ field public static final int REMOVE_RESULT_ERROR = 3; // 0x3
+ field public static final int REMOVE_RESULT_REMOVED = 0; // 0x0
field public static final int RESTRICTION_NOT_SET = 0; // 0x0
field public static final int RESTRICTION_SOURCE_DEVICE_OWNER = 2; // 0x2
field public static final int RESTRICTION_SOURCE_PROFILE_OWNER = 4; // 0x4
@@ -9582,6 +9620,7 @@ package android.permission {
method @Deprecated @BinderThread public void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
method @BinderThread public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String, @NonNull Runnable);
method @BinderThread public abstract void onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.util.List<java.lang.String>>>);
+ method @BinderThread public void onSelfRevokePermissions(@NonNull String, @NonNull java.util.List<java.lang.String>, @NonNull Runnable);
method @Deprecated @BinderThread public abstract void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @BinderThread public void onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull android.permission.AdminPermissionControlParams, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method @BinderThread public void onStageAndApplyRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream, @NonNull Runnable);
@@ -10797,7 +10836,7 @@ package android.service.games {
public class GameService extends android.app.Service {
ctor public GameService();
- method @Nullable public android.os.IBinder onBind(@Nullable android.content.Intent);
+ method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
method public void onConnected();
method public void onDisconnected();
field public static final String ACTION_GAME_SERVICE = "android.service.games.action.GAME_SERVICE";
@@ -10812,7 +10851,7 @@ package android.service.games {
public abstract class GameSessionService extends android.app.Service {
ctor public GameSessionService();
- method @Nullable public android.os.IBinder onBind(@Nullable android.content.Intent);
+ method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
method @NonNull public abstract android.service.games.GameSession onNewSession(@NonNull android.service.games.CreateGameSessionRequest);
field public static final String ACTION_GAME_SESSION_SERVICE = "android.service.games.action.GAME_SESSION_SERVICE";
}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 0710781a3155..66250fcebe92 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -36,6 +36,7 @@ package android {
field public static final String RECORD_BACKGROUND_AUDIO = "android.permission.RECORD_BACKGROUND_AUDIO";
field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
field public static final String RESET_APP_ERRORS = "android.permission.RESET_APP_ERRORS";
+ field public static final String REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL = "android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL";
field public static final String SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS = "android.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS";
field public static final String START_TASKS_FROM_RECENTS = "android.permission.START_TASKS_FROM_RECENTS";
field public static final String SUSPEND_APPS = "android.permission.SUSPEND_APPS";
@@ -66,6 +67,7 @@ package android {
public static final class R.string {
field public static final int config_defaultAssistant = 17039393; // 0x1040021
field public static final int config_defaultDialer = 17039395; // 0x1040023
+ field public static final int config_systemAutomotiveCalendarSyncManager;
field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
field public static final int config_systemAutomotiveProjection = 17039401; // 0x1040029
field public static final int config_systemGallery = 17039399; // 0x1040027
@@ -1822,13 +1824,21 @@ package android.os {
public static final class VibrationEffect.WaveformBuilder {
method @NonNull public android.os.VibrationEffect.WaveformBuilder addRamp(@FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int);
- method @NonNull public android.os.VibrationEffect.WaveformBuilder addRamp(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=-1.0F, to=1.0f) float, @IntRange(from=0) int);
+ method @NonNull public android.os.VibrationEffect.WaveformBuilder addRamp(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=1.0f) float, @IntRange(from=0) int);
method @NonNull public android.os.VibrationEffect.WaveformBuilder addStep(@FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int);
- method @NonNull public android.os.VibrationEffect.WaveformBuilder addStep(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=-1.0F, to=1.0f) float, @IntRange(from=0) int);
+ method @NonNull public android.os.VibrationEffect.WaveformBuilder addStep(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=1.0f) float, @IntRange(from=0) int);
method @NonNull public android.os.VibrationEffect build();
method @NonNull public android.os.VibrationEffect build(int);
}
+ public abstract class Vibrator {
+ method public int getDefaultVibrationIntensity(int);
+ field public static final int VIBRATION_INTENSITY_HIGH = 3; // 0x3
+ field public static final int VIBRATION_INTENSITY_LOW = 1; // 0x1
+ field public static final int VIBRATION_INTENSITY_MEDIUM = 2; // 0x2
+ field public static final int VIBRATION_INTENSITY_OFF = 0; // 0x0
+ }
+
public class VintfObject {
method public static String[] getHalNamesAndVersions();
method @NonNull public static String getPlatformSepolicyVersion();
@@ -1982,9 +1992,9 @@ package android.os.vibrator {
method public int describeContents();
method public long getDuration();
method public float getEndAmplitude();
- method public float getEndFrequency();
+ method public float getEndFrequencyHz();
method public float getStartAmplitude();
- method public float getStartFrequency();
+ method public float getStartFrequencyHz();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.RampSegment> CREATOR;
}
@@ -1993,7 +2003,7 @@ package android.os.vibrator {
method public int describeContents();
method public float getAmplitude();
method public long getDuration();
- method public float getFrequency();
+ method public float getFrequencyHz();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.StepSegment> CREATOR;
}
@@ -2036,6 +2046,7 @@ package android.permission {
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData();
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(boolean);
method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource);
+ method public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String, int);
}
}
@@ -2309,6 +2320,7 @@ package android.service.dreams {
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onStartDream(@NonNull android.view.WindowManager.LayoutParams);
method public final void requestExit();
+ method public final boolean shouldShowComplications();
}
}
diff --git a/core/java/android/accessibilityservice/AccessibilityGestureEvent.java b/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
index 8e01779c6fac..3c9b23251191 100644
--- a/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
+++ b/core/java/android/accessibilityservice/AccessibilityGestureEvent.java
@@ -172,7 +172,7 @@ public final class AccessibilityGestureEvent implements Parcelable {
private AccessibilityGestureEvent(@NonNull Parcel parcel) {
mGestureId = parcel.readInt();
mDisplayId = parcel.readInt();
- ParceledListSlice<MotionEvent> slice = parcel.readParcelable(getClass().getClassLoader(), android.content.pm.ParceledListSlice.class);
+ ParceledListSlice<MotionEvent> slice = parcel.readParcelable(getClass().getClassLoader());
mMotionEvents = slice.getList();
}
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 1167d0b1034f..04c784ea1c17 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -1094,8 +1094,8 @@ public class AccessibilityServiceInfo implements Parcelable {
mInteractiveUiTimeout = parcel.readInt();
flags = parcel.readInt();
crashed = parcel.readInt() != 0;
- mComponentName = parcel.readParcelable(this.getClass().getClassLoader(), android.content.ComponentName.class);
- mResolveInfo = parcel.readParcelable(null, android.content.pm.ResolveInfo.class);
+ mComponentName = parcel.readParcelable(this.getClass().getClassLoader());
+ mResolveInfo = parcel.readParcelable(null);
mSettingsActivityName = parcel.readString();
mCapabilities = parcel.readInt();
mSummaryResId = parcel.readInt();
diff --git a/core/java/android/accessibilityservice/GestureDescription.java b/core/java/android/accessibilityservice/GestureDescription.java
index a821dadf4948..857c5416b3bc 100644
--- a/core/java/android/accessibilityservice/GestureDescription.java
+++ b/core/java/android/accessibilityservice/GestureDescription.java
@@ -525,7 +525,7 @@ public final class GestureDescription {
public GestureStep(Parcel parcel) {
timeSinceGestureStart = parcel.readLong();
Parcelable[] parcelables =
- parcel.readParcelableArray(TouchPoint.class.getClassLoader());
+ parcel.readParcelableArray(TouchPoint.class.getClassLoader(), TouchPoint.class);
numTouchPoints = (parcelables == null) ? 0 : parcelables.length;
touchPoints = new TouchPoint[numTouchPoints];
for (int i = 0; i < numTouchPoints; i++) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a1409839ff63..9f8d24662c8d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1903,7 +1903,7 @@ public class ActivityManager {
public void readFromParcel(Parcel source) {
id = source.readInt();
persistentId = source.readInt();
- childrenTaskInfos = source.readArrayList(RecentTaskInfo.class.getClassLoader(), android.app.ActivityManager.RecentTaskInfo.class);
+ childrenTaskInfos = source.readArrayList(RecentTaskInfo.class.getClassLoader());
lastSnapshotData.taskSize = source.readTypedObject(Point.CREATOR);
lastSnapshotData.contentInsets = source.readTypedObject(Rect.CREATOR);
lastSnapshotData.bufferSize = source.readTypedObject(Point.CREATOR);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b2c9439d5760..7ac4bddbed57 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4178,15 +4178,20 @@ public final class ActivityThread extends ClientTransactionHandler
view.requestLayout();
view.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
+ private boolean mHandled = false;
@Override
public void onDraw() {
+ if (mHandled) {
+ return;
+ }
+ mHandled = true;
// Transfer the splash screen view from shell to client.
// Call syncTransferSplashscreenViewTransaction at the first onDraw so we can ensure
// the client view is ready to show and we can use applyTransactionOnDraw to make
// all transitions happen at the same frame.
syncTransferSplashscreenViewTransaction(
view, r.token, decorView, startingWindowLeash);
- view.postOnAnimation(() -> view.getViewTreeObserver().removeOnDrawListener(this));
+ view.post(() -> view.getViewTreeObserver().removeOnDrawListener(this));
}
});
}
@@ -4530,6 +4535,12 @@ public final class ActivityThread extends ClientTransactionHandler
// we are back active so skip it.
unscheduleGcIdler();
+ // To investigate "duplciate Application objects" bug (b/185177290)
+ if (UserHandle.myUserId() != UserHandle.getUserId(data.info.applicationInfo.uid)) {
+ Slog.wtf(TAG, "handleCreateService called with wrong appinfo UID: myUserId="
+ + UserHandle.myUserId() + " appinfo.uid=" + data.info.applicationInfo.uid);
+ }
+
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 68c69e555bda..565f69090c6b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -4058,7 +4058,7 @@ public class AppOpsManager {
LongSparseArray<NoteOpEvent> array = new LongSparseArray<>(numEntries);
for (int i = 0; i < numEntries; i++) {
- array.put(source.readLong(), source.readParcelable(null, android.app.AppOpsManager.NoteOpEvent.class));
+ array.put(source.readLong(), source.readParcelable(null));
}
return array;
@@ -5178,7 +5178,7 @@ public class AppOpsManager {
final int[] uids = parcel.createIntArray();
if (!ArrayUtils.isEmpty(uids)) {
final ParceledListSlice<HistoricalUidOps> listSlice = parcel.readParcelable(
- HistoricalOps.class.getClassLoader(), android.content.pm.ParceledListSlice.class);
+ HistoricalOps.class.getClassLoader());
final List<HistoricalUidOps> uidOps = (listSlice != null)
? listSlice.getList() : null;
if (uidOps == null) {
@@ -10000,7 +10000,7 @@ public class AppOpsManager {
private static @Nullable List<AttributedOpEntry> readDiscreteAccessArrayFromParcel(
@NonNull Parcel parcel) {
- final ParceledListSlice<AttributedOpEntry> listSlice = parcel.readParcelable(null, android.content.pm.ParceledListSlice.class);
+ final ParceledListSlice<AttributedOpEntry> listSlice = parcel.readParcelable(null);
return listSlice == null ? null : listSlice.getList();
}
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index c0aebeed596a..7a806bdf473d 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -118,11 +118,11 @@ public final class AutomaticZenRule implements Parcelable {
name = source.readString();
}
interruptionFilter = source.readInt();
- conditionId = source.readParcelable(null, android.net.Uri.class);
- owner = source.readParcelable(null, android.content.ComponentName.class);
- configurationActivity = source.readParcelable(null, android.content.ComponentName.class);
+ conditionId = source.readParcelable(null);
+ owner = source.readParcelable(null);
+ configurationActivity = source.readParcelable(null);
creationTime = source.readLong();
- mZenPolicy = source.readParcelable(null, android.service.notification.ZenPolicy.class);
+ mZenPolicy = source.readParcelable(null);
mModified = source.readInt() == ENABLED;
mPkg = source.readString();
}
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 0bb6ffa3a035..7812aba210e7 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -430,8 +430,8 @@ public class BroadcastOptions extends ComponentOptions {
* permissions set by {@link #setRequireAllOfPermissions(String[])}, and none of the
* permissions set by {@link #setRequireNoneOfPermissions(String[])} to get the broadcast.
*
- * @param requiredPermissions a list of Strings of permission the receiver must have, or null
- * to clear any previously set value.
+ * @param requiredPermissions a list of Strings of permission the receiver must have. Set to
+ * null or an empty array to clear any previously set value.
* @hide
*/
@SystemApi
@@ -449,8 +449,8 @@ public class BroadcastOptions extends ComponentOptions {
* permissions set by {@link #setRequireAllOfPermissions(String[])}, and none of the
* permissions set by {@link #setRequireNoneOfPermissions(String[])} to get the broadcast.
*
- * @param excludedPermissions a list of Strings of permission the receiver must not have,
- * or null to clear any previously set value.
+ * @param excludedPermissions a list of Strings of permission the receiver must not have. Set to
+ * null or an empty array to clear any previously set value.
* @hide
*/
@SystemApi
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index f3e9f105500e..fe512ffbaac3 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -113,6 +113,7 @@ import java.nio.ByteOrder;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -2170,6 +2171,11 @@ class ContextImpl extends Context {
}
@Override
+ public void selfRevokePermissions(@NonNull Collection<String> permissions) {
+ getSystemService(PermissionManager.class).selfRevokePermissions(permissions);
+ }
+
+ @Override
public int checkCallingPermission(String permission) {
if (permission == null) {
throw new IllegalArgumentException("permission is null");
diff --git a/core/java/android/app/GrantedUriPermission.java b/core/java/android/app/GrantedUriPermission.java
index a71cb4a11af8..48d5b8cc126b 100644
--- a/core/java/android/app/GrantedUriPermission.java
+++ b/core/java/android/app/GrantedUriPermission.java
@@ -68,7 +68,7 @@ public class GrantedUriPermission implements Parcelable {
};
private GrantedUriPermission(Parcel in) {
- uri = in.readParcelable(null, android.net.Uri.class);
+ uri = in.readParcelable(null);
packageName = in.readString();
}
}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index b052bc53ddbf..a9ec11edd680 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -178,17 +178,16 @@ interface IActivityTaskManager {
Point getAppTaskThumbnailSize();
/**
* Only callable from the system. This token grants a temporary permission to call
- * #startActivityAsCallerWithToken. The token will time out after
- * START_AS_CALLER_TOKEN_TIMEOUT if it is not used.
+ * #startActivityAsCaller. The token will time out after START_AS_CALLER_TOKEN_TIMEOUT
+ * if it is not used.
*
- * @param delegatorToken The Binder token referencing the system Activity that wants to delegate
- * the #startActivityAsCaller to another app. The "caller" will be the caller of this
- * activity's token, not the delegate's caller (which is probably the delegator itself).
+ * @param componentName The component name of the delegated component that is allowed to
+ * call #startActivityAsCaller with the returned token.
*
* @return Returns a token that can be given to a "delegate" app that may call
* #startActivityAsCaller
*/
- IBinder requestStartActivityPermissionToken(in IBinder delegatorToken);
+ IBinder requestStartActivityPermissionToken(in ComponentName componentName);
oneway void releaseSomeActivities(in IApplicationThread app);
Bitmap getTaskDescriptionIcon(in String filename, int userId);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 77af474a04ac..4e32e9a41869 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1341,15 +1341,43 @@ public final class LoadedApk {
return mResources;
}
+ /**
+ * Used to investigate "duplicate app objects" bug (b/185177290).
+ * makeApplication() should only be called on the main thread, so no synchronization should
+ * be needed, but syncing anyway just in case.
+ */
+ @GuardedBy("sApplicationCache")
+ private static final ArrayMap<String, Application> sApplicationCache = new ArrayMap<>(4);
+
@UnsupportedAppUsage
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
-
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "makeApplication");
+ // For b/185177290.
+ final boolean wrongUser =
+ UserHandle.myUserId() != UserHandle.getUserId(mApplicationInfo.uid);
+ if (wrongUser) {
+ Slog.wtf(TAG, "makeApplication called with wrong appinfo UID: myUserId="
+ + UserHandle.myUserId() + " appinfo.uid=" + mApplicationInfo.uid);
+ }
+ synchronized (sApplicationCache) {
+ final Application cached = sApplicationCache.get(mPackageName);
+ if (cached != null) {
+ // Looks like this is always happening for the system server, because
+ // the LoadedApk created in systemMain() -> attach() isn't cached properly?
+ if (!"android".equals(mPackageName)) {
+ Slog.wtf(TAG, "App instance already created for package=" + mPackageName
+ + " instance=" + cached);
+ }
+ // TODO Return the cached one, unles it's for the wrong user?
+ // For now, we just add WTF checks.
+ }
+ }
+
Application app = null;
final String myProcessName = Process.myProcessName();
@@ -1397,6 +1425,9 @@ public final class LoadedApk {
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
+ synchronized (sApplicationCache) {
+ sApplicationCache.put(mPackageName, app);
+ }
if (instrumentation != null) {
try {
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index f97415ca20c8..cd6df0b231d9 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -100,7 +100,7 @@ public final class NotificationChannelGroup implements Parcelable {
} else {
mDescription = null;
}
- in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader(), android.app.NotificationChannel.class);
+ in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader());
mBlocked = in.readBoolean();
mUserLockedFields = in.readInt();
}
diff --git a/core/java/android/app/RemoteInputHistoryItem.java b/core/java/android/app/RemoteInputHistoryItem.java
index 32f89819fb1f..091db3f142ae 100644
--- a/core/java/android/app/RemoteInputHistoryItem.java
+++ b/core/java/android/app/RemoteInputHistoryItem.java
@@ -48,7 +48,7 @@ public class RemoteInputHistoryItem implements Parcelable {
protected RemoteInputHistoryItem(Parcel in) {
mText = in.readCharSequence();
mMimeType = in.readStringNoHelper();
- mUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
+ mUri = in.readParcelable(Uri.class.getClassLoader());
}
public static final Creator<RemoteInputHistoryItem> CREATOR =
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7969cda7b84d..73ebdf6a4545 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2885,6 +2885,38 @@ public class DevicePolicyManager {
public static final int RESULT_UPDATE_DEVICE_MANAGEMENT_ROLE_HOLDER_UNRECOVERABLE_ERROR = 2;
/**
+ * An {@link Intent} extra which resolves to a custom user consent screen.
+ *
+ * <p>If this extra is provided to the device management role holder via either {@link
+ * #ACTION_ROLE_HOLDER_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE} or {@link
+ * #ACTION_ROLE_HOLDER_PROVISION_MANAGED_PROFILE}, the device management role holder must
+ * launch this intent which shows the custom user consent screen, replacing its own standard
+ * consent screen.
+ *
+ * <p>If this extra is provided, it is the responsibility of the intent handler to show the
+ * list of disclaimers which are normally shown by the standard consent screen:
+ * <ul>
+ * <li>Disclaimers set by the IT admin via the {@link #EXTRA_PROVISIONING_DISCLAIMERS}
+ * provisioning extra</li>
+ * <li>For fully-managed device provisioning, disclaimers defined in system apps via the
+ * {@link #EXTRA_PROVISIONING_DISCLAIMER_HEADER} and {@link
+ * #EXTRA_PROVISIONING_DISCLAIMER_CONTENT} metadata in their manifests</li>
+ * <li>General disclaimer relevant to the provisioning mode</li>
+ * </ul>
+ *
+ * <p>If the custom consent screens are granted by the user {@link Activity#RESULT_OK} is
+ * returned, otherwise {@link Activity#RESULT_CANCELED} is returned. The device management
+ * role holder should ensure that the provisioning flow terminates immediately if consent
+ * is not granted by the user.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ @SystemApi
+ public static final String EXTRA_PROVISIONING_ROLE_HOLDER_CUSTOM_USER_CONSENT_INTENT =
+ "android.app.extra.PROVISIONING_ROLE_HOLDER_CUSTOM_USER_CONSENT_INTENT";
+
+ /**
* Maximum supported password length. Kind-of arbitrary.
* @hide
*/
diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java
index 6e49e956fe7e..e1f6af0cc128 100644
--- a/core/java/android/app/assist/AssistStructure.java
+++ b/core/java/android/app/assist/AssistStructure.java
@@ -815,13 +815,13 @@ public class AssistStructure implements Parcelable {
mAutofillHints = in.readStringArray();
}
if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_VALUE) != 0) {
- mAutofillValue = in.readParcelable(null, android.view.autofill.AutofillValue.class);
+ mAutofillValue = in.readParcelable(null);
}
if ((autofillFlags & AUTOFILL_FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
mAutofillOptions = in.readCharSequenceArray();
}
if ((autofillFlags & AUTOFILL_FLAGS_HAS_HTML_INFO) != 0) {
- mHtmlInfo = in.readParcelable(null, android.view.ViewStructure.HtmlInfo.class);
+ mHtmlInfo = in.readParcelable(null);
}
if ((autofillFlags & AUTOFILL_FLAGS_HAS_MIN_TEXT_EMS) != 0) {
mMinEms = in.readInt();
@@ -886,7 +886,7 @@ public class AssistStructure implements Parcelable {
mWebDomain = in.readString();
}
if ((flags&FLAGS_HAS_LOCALE_LIST) != 0) {
- mLocaleList = in.readParcelable(null, android.os.LocaleList.class);
+ mLocaleList = in.readParcelable(null);
}
if ((flags & FLAGS_HAS_MIME_TYPES) != 0) {
mReceiveContentMimeTypes = in.readStringArray();
diff --git a/core/java/android/app/communal/CommunalManager.java b/core/java/android/app/communal/CommunalManager.java
index 22bd9d17715a..c7368ade2dcc 100644
--- a/core/java/android/app/communal/CommunalManager.java
+++ b/core/java/android/app/communal/CommunalManager.java
@@ -17,7 +17,6 @@
package android.app.communal;
import android.Manifest;
-import android.annotation.NonNull;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
@@ -26,9 +25,6 @@ import android.annotation.TestApi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.RemoteException;
-import android.util.ArrayMap;
-
-import java.util.concurrent.Executor;
/**
* System private class for talking with the
@@ -41,12 +37,10 @@ import java.util.concurrent.Executor;
@RequiresFeature(PackageManager.FEATURE_COMMUNAL_MODE)
public final class CommunalManager {
private final ICommunalManager mService;
- private final ArrayMap<CommunalModeListener, ICommunalModeListener> mCommunalModeListeners;
/** @hide */
public CommunalManager(ICommunalManager service) {
mService = service;
- mCommunalModeListeners = new ArrayMap<>();
}
/**
@@ -65,72 +59,4 @@ public final class CommunalManager {
throw e.rethrowFromSystemServer();
}
}
-
- /**
- * Checks whether or not the communal view is currently showing over the lockscreen.
- */
- @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
- public boolean isCommunalMode() {
- try {
- return mService.isCommunalMode();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
- * Listener for communal state changes.
- */
- @FunctionalInterface
- public interface CommunalModeListener {
- /**
- * Callback function that executes when the communal state changes.
- */
- void onCommunalModeChanged(boolean isCommunalMode);
- }
-
- /**
- * Registers a callback to execute when the communal state changes.
- *
- * @param listener The listener to add to receive communal state changes.
- * @param executor {@link Executor} to dispatch to. To dispatch the callback to the main
- * thread of your application, use
- * {@link android.content.Context#getMainExecutor()}.
- */
- @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
- public void addCommunalModeListener(@NonNull Executor executor,
- @NonNull CommunalModeListener listener) {
- synchronized (mCommunalModeListeners) {
- try {
- ICommunalModeListener iListener = new ICommunalModeListener.Stub() {
- @Override
- public void onCommunalModeChanged(boolean isCommunalMode) {
- executor.execute(() -> listener.onCommunalModeChanged(isCommunalMode));
- }
- };
- mService.addCommunalModeListener(iListener);
- mCommunalModeListeners.put(listener, iListener);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
-
- /**
- * Unregisters a callback that executes when communal state changes.
- */
- @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
- public void removeCommunalModeListener(@NonNull CommunalModeListener listener) {
- synchronized (mCommunalModeListeners) {
- ICommunalModeListener iListener = mCommunalModeListeners.get(listener);
- if (iListener != null) {
- try {
- mService.removeCommunalModeListener(iListener);
- mCommunalModeListeners.remove(listener);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
- }
}
diff --git a/core/java/android/app/communal/ICommunalManager.aidl b/core/java/android/app/communal/ICommunalManager.aidl
index 869891e079e0..df9d7cec05f7 100644
--- a/core/java/android/app/communal/ICommunalManager.aidl
+++ b/core/java/android/app/communal/ICommunalManager.aidl
@@ -16,8 +16,6 @@
package android.app.communal;
-import android.app.communal.ICommunalModeListener;
-
/**
* System private API for talking with the communal manager service that handles communal mode
* state.
@@ -26,7 +24,4 @@ import android.app.communal.ICommunalModeListener;
*/
interface ICommunalManager {
oneway void setCommunalViewShowing(boolean isShowing);
- boolean isCommunalMode();
- void addCommunalModeListener(in ICommunalModeListener listener);
- void removeCommunalModeListener(in ICommunalModeListener listener);
} \ No newline at end of file
diff --git a/core/java/android/app/people/ConversationChannel.java b/core/java/android/app/people/ConversationChannel.java
index ab350f225e52..2bf71b0183c6 100644
--- a/core/java/android/app/people/ConversationChannel.java
+++ b/core/java/android/app/people/ConversationChannel.java
@@ -83,16 +83,16 @@ public final class ConversationChannel implements Parcelable {
}
public ConversationChannel(Parcel in) {
- mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader(), android.content.pm.ShortcutInfo.class);
+ mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
mUid = in.readInt();
- mNotificationChannel = in.readParcelable(NotificationChannel.class.getClassLoader(), android.app.NotificationChannel.class);
+ mNotificationChannel = in.readParcelable(NotificationChannel.class.getClassLoader());
mNotificationChannelGroup =
- in.readParcelable(NotificationChannelGroup.class.getClassLoader(), android.app.NotificationChannelGroup.class);
+ in.readParcelable(NotificationChannelGroup.class.getClassLoader());
mLastEventTimestamp = in.readLong();
mHasActiveNotifications = in.readBoolean();
mHasBirthdayToday = in.readBoolean();
mStatuses = new ArrayList<>();
- in.readParcelableList(mStatuses, ConversationStatus.class.getClassLoader(), android.app.people.ConversationStatus.class);
+ in.readParcelableList(mStatuses, ConversationStatus.class.getClassLoader());
}
@Override
diff --git a/core/java/android/app/people/ConversationStatus.java b/core/java/android/app/people/ConversationStatus.java
index a7b61b37d14e..8038158b1f97 100644
--- a/core/java/android/app/people/ConversationStatus.java
+++ b/core/java/android/app/people/ConversationStatus.java
@@ -126,7 +126,7 @@ public final class ConversationStatus implements Parcelable {
mActivity = p.readInt();
mAvailability = p.readInt();
mDescription = p.readCharSequence();
- mIcon = p.readParcelable(Icon.class.getClassLoader(), android.graphics.drawable.Icon.class);
+ mIcon = p.readParcelable(Icon.class.getClassLoader());
mStartTimeMs = p.readLong();
mEndTimeMs = p.readLong();
}
diff --git a/core/java/android/app/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
index 4337111636a0..e11861f49be8 100644
--- a/core/java/android/app/people/PeopleSpaceTile.java
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -472,9 +472,9 @@ public class PeopleSpaceTile implements Parcelable {
public PeopleSpaceTile(Parcel in) {
mId = in.readString();
mUserName = in.readCharSequence();
- mUserIcon = in.readParcelable(Icon.class.getClassLoader(), android.graphics.drawable.Icon.class);
- mContactUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
- mUserHandle = in.readParcelable(UserHandle.class.getClassLoader(), android.os.UserHandle.class);
+ mUserIcon = in.readParcelable(Icon.class.getClassLoader());
+ mContactUri = in.readParcelable(Uri.class.getClassLoader());
+ mUserHandle = in.readParcelable(UserHandle.class.getClassLoader());
mPackageName = in.readString();
mBirthdayText = in.readString();
mLastInteractionTimestamp = in.readLong();
@@ -483,12 +483,12 @@ public class PeopleSpaceTile implements Parcelable {
mNotificationContent = in.readCharSequence();
mNotificationSender = in.readCharSequence();
mNotificationCategory = in.readString();
- mNotificationDataUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
+ mNotificationDataUri = in.readParcelable(Uri.class.getClassLoader());
mMessagesCount = in.readInt();
- mIntent = in.readParcelable(Intent.class.getClassLoader(), android.content.Intent.class);
+ mIntent = in.readParcelable(Intent.class.getClassLoader());
mNotificationTimestamp = in.readLong();
mStatuses = new ArrayList<>();
- in.readParcelableList(mStatuses, ConversationStatus.class.getClassLoader(), android.app.people.ConversationStatus.class);
+ in.readParcelableList(mStatuses, ConversationStatus.class.getClassLoader());
mCanBypassDnd = in.readBoolean();
mIsPackageSuspended = in.readBoolean();
mIsUserQuieted = in.readBoolean();
diff --git a/core/java/android/app/prediction/AppTargetEvent.java b/core/java/android/app/prediction/AppTargetEvent.java
index 51e3953ead4f..963e750e4fd1 100644
--- a/core/java/android/app/prediction/AppTargetEvent.java
+++ b/core/java/android/app/prediction/AppTargetEvent.java
@@ -72,7 +72,7 @@ public final class AppTargetEvent implements Parcelable {
}
private AppTargetEvent(Parcel parcel) {
- mTarget = parcel.readParcelable(null, android.app.prediction.AppTarget.class);
+ mTarget = parcel.readParcelable(null);
mLocation = parcel.readString();
mAction = parcel.readInt();
}
diff --git a/core/java/android/app/servertransaction/ClientTransaction.java b/core/java/android/app/servertransaction/ClientTransaction.java
index 30a6c311bd1e..fbb37db52014 100644
--- a/core/java/android/app/servertransaction/ClientTransaction.java
+++ b/core/java/android/app/servertransaction/ClientTransaction.java
@@ -197,11 +197,11 @@ public class ClientTransaction implements Parcelable, ObjectPoolItem {
if (readActivityToken) {
mActivityToken = in.readStrongBinder();
}
- mLifecycleStateRequest = in.readParcelable(getClass().getClassLoader(), android.app.servertransaction.ActivityLifecycleItem.class);
+ mLifecycleStateRequest = in.readParcelable(getClass().getClassLoader());
final boolean readActivityCallbacks = in.readBoolean();
if (readActivityCallbacks) {
mActivityCallbacks = new ArrayList<>();
- in.readParcelableList(mActivityCallbacks, getClass().getClassLoader(), android.app.servertransaction.ClientTransactionItem.class);
+ in.readParcelableList(mActivityCallbacks, getClass().getClassLoader());
}
}
diff --git a/core/java/android/app/smartspace/SmartspaceTargetEvent.java b/core/java/android/app/smartspace/SmartspaceTargetEvent.java
index 89caab764591..61f8723ca393 100644
--- a/core/java/android/app/smartspace/SmartspaceTargetEvent.java
+++ b/core/java/android/app/smartspace/SmartspaceTargetEvent.java
@@ -96,7 +96,7 @@ public final class SmartspaceTargetEvent implements Parcelable {
}
private SmartspaceTargetEvent(Parcel parcel) {
- mSmartspaceTarget = parcel.readParcelable(null, android.app.smartspace.SmartspaceTarget.class);
+ mSmartspaceTarget = parcel.readParcelable(null);
mSmartspaceActionId = parcel.readString();
mEventType = parcel.readInt();
}
diff --git a/core/java/android/app/time/ExternalTimeSuggestion.java b/core/java/android/app/time/ExternalTimeSuggestion.java
index 0f98b4451983..8e281c07c45d 100644
--- a/core/java/android/app/time/ExternalTimeSuggestion.java
+++ b/core/java/android/app/time/ExternalTimeSuggestion.java
@@ -101,11 +101,11 @@ public final class ExternalTimeSuggestion implements Parcelable {
}
private static ExternalTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */, android.os.TimestampedValue.class);
+ TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
ExternalTimeSuggestion suggestion =
new ExternalTimeSuggestion(utcTime.getReferenceTimeMillis(), utcTime.getValue());
@SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */, java.lang.String.class);
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
return suggestion;
}
diff --git a/core/java/android/app/time/TimeCapabilitiesAndConfig.java b/core/java/android/app/time/TimeCapabilitiesAndConfig.java
index 71fce14a80b1..4a1044760064 100644
--- a/core/java/android/app/time/TimeCapabilitiesAndConfig.java
+++ b/core/java/android/app/time/TimeCapabilitiesAndConfig.java
@@ -59,8 +59,8 @@ public final class TimeCapabilitiesAndConfig implements Parcelable {
@NonNull
private static TimeCapabilitiesAndConfig readFromParcel(Parcel in) {
- TimeCapabilities capabilities = in.readParcelable(null, android.app.time.TimeCapabilities.class);
- TimeConfiguration configuration = in.readParcelable(null, android.app.time.TimeConfiguration.class);
+ TimeCapabilities capabilities = in.readParcelable(null);
+ TimeConfiguration configuration = in.readParcelable(null);
return new TimeCapabilitiesAndConfig(capabilities, configuration);
}
diff --git a/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java b/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java
index cd91b0431b28..a9ea76f77958 100644
--- a/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java
+++ b/core/java/android/app/time/TimeZoneCapabilitiesAndConfig.java
@@ -61,8 +61,8 @@ public final class TimeZoneCapabilitiesAndConfig implements Parcelable {
@NonNull
private static TimeZoneCapabilitiesAndConfig createFromParcel(Parcel in) {
- TimeZoneCapabilities capabilities = in.readParcelable(null, android.app.time.TimeZoneCapabilities.class);
- TimeZoneConfiguration configuration = in.readParcelable(null, android.app.time.TimeZoneConfiguration.class);
+ TimeZoneCapabilities capabilities = in.readParcelable(null);
+ TimeZoneConfiguration configuration = in.readParcelable(null);
return new TimeZoneCapabilitiesAndConfig(capabilities, configuration);
}
diff --git a/core/java/android/app/timedetector/GnssTimeSuggestion.java b/core/java/android/app/timedetector/GnssTimeSuggestion.java
index 8ccff6227c79..6478a2dd2aa9 100644
--- a/core/java/android/app/timedetector/GnssTimeSuggestion.java
+++ b/core/java/android/app/timedetector/GnssTimeSuggestion.java
@@ -66,10 +66,10 @@ public final class GnssTimeSuggestion implements Parcelable {
}
private static GnssTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */, android.os.TimestampedValue.class);
+ TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
GnssTimeSuggestion suggestion = new GnssTimeSuggestion(utcTime);
@SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */, java.lang.String.class);
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
return suggestion;
}
diff --git a/core/java/android/app/timedetector/ManualTimeSuggestion.java b/core/java/android/app/timedetector/ManualTimeSuggestion.java
index 1699a5f8c8ae..299e9518e329 100644
--- a/core/java/android/app/timedetector/ManualTimeSuggestion.java
+++ b/core/java/android/app/timedetector/ManualTimeSuggestion.java
@@ -66,10 +66,10 @@ public final class ManualTimeSuggestion implements Parcelable {
}
private static ManualTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */, android.os.TimestampedValue.class);
+ TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
ManualTimeSuggestion suggestion = new ManualTimeSuggestion(utcTime);
@SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */, java.lang.String.class);
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
return suggestion;
}
diff --git a/core/java/android/app/timedetector/NetworkTimeSuggestion.java b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
index 20300832d2fc..a5259c27ec42 100644
--- a/core/java/android/app/timedetector/NetworkTimeSuggestion.java
+++ b/core/java/android/app/timedetector/NetworkTimeSuggestion.java
@@ -66,10 +66,10 @@ public final class NetworkTimeSuggestion implements Parcelable {
}
private static NetworkTimeSuggestion createFromParcel(Parcel in) {
- TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */, android.os.TimestampedValue.class);
+ TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
NetworkTimeSuggestion suggestion = new NetworkTimeSuggestion(utcTime);
@SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */, java.lang.String.class);
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
return suggestion;
}
diff --git a/core/java/android/app/timedetector/TelephonyTimeSuggestion.java b/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
index 52d0bbea701e..6c3a304ed3a7 100644
--- a/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
+++ b/core/java/android/app/timedetector/TelephonyTimeSuggestion.java
@@ -77,10 +77,10 @@ public final class TelephonyTimeSuggestion implements Parcelable {
private static TelephonyTimeSuggestion createFromParcel(Parcel in) {
int slotIndex = in.readInt();
TelephonyTimeSuggestion suggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
- .setUtcTime(in.readParcelable(null /* classLoader */, android.os.TimestampedValue.class))
+ .setUtcTime(in.readParcelable(null /* classLoader */))
.build();
@SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */, java.lang.String.class);
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
if (debugInfo != null) {
suggestion.addDebugInfo(debugInfo);
}
diff --git a/core/java/android/app/timezone/RulesState.java b/core/java/android/app/timezone/RulesState.java
index 516ad033a936..ee88ec54d08f 100644
--- a/core/java/android/app/timezone/RulesState.java
+++ b/core/java/android/app/timezone/RulesState.java
@@ -195,12 +195,12 @@ public final class RulesState implements Parcelable {
private static RulesState createFromParcel(Parcel in) {
String baseRulesVersion = in.readString();
- DistroFormatVersion distroFormatVersionSupported = in.readParcelable(null, android.app.timezone.DistroFormatVersion.class);
+ DistroFormatVersion distroFormatVersionSupported = in.readParcelable(null);
boolean operationInProgress = in.readByte() == BYTE_TRUE;
int distroStagedState = in.readByte();
- DistroRulesVersion stagedDistroRulesVersion = in.readParcelable(null, android.app.timezone.DistroRulesVersion.class);
+ DistroRulesVersion stagedDistroRulesVersion = in.readParcelable(null);
int installedDistroStatus = in.readByte();
- DistroRulesVersion installedDistroRulesVersion = in.readParcelable(null, android.app.timezone.DistroRulesVersion.class);
+ DistroRulesVersion installedDistroRulesVersion = in.readParcelable(null);
return new RulesState(baseRulesVersion, distroFormatVersionSupported, operationInProgress,
distroStagedState, stagedDistroRulesVersion,
installedDistroStatus, installedDistroRulesVersion);
diff --git a/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java
index 387319edc5e7..01a60b1fa025 100644
--- a/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/ManualTimeZoneSuggestion.java
@@ -65,7 +65,7 @@ public final class ManualTimeZoneSuggestion implements Parcelable {
String zoneId = in.readString();
ManualTimeZoneSuggestion suggestion = new ManualTimeZoneSuggestion(zoneId);
@SuppressWarnings("unchecked")
- ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */, java.lang.String.class);
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
return suggestion;
}
diff --git a/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java b/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java
index e5b4e46ba285..eb6750f06d25 100644
--- a/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java
+++ b/core/java/android/app/timezonedetector/TelephonyTimeZoneSuggestion.java
@@ -165,7 +165,7 @@ public final class TelephonyTimeZoneSuggestion implements Parcelable {
.setQuality(in.readInt())
.build();
List<String> debugInfo =
- in.readArrayList(TelephonyTimeZoneSuggestion.class.getClassLoader(), java.lang.String.class);
+ in.readArrayList(TelephonyTimeZoneSuggestion.class.getClassLoader());
if (debugInfo != null) {
suggestion.addDebugInfo(debugInfo);
}
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 65b2775fd66b..177de835554b 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -156,7 +156,7 @@ public class TrustManager {
@Override
public void onTrustError(CharSequence message) {
- Message m = mHandler.obtainMessage(MSG_TRUST_ERROR);
+ Message m = mHandler.obtainMessage(MSG_TRUST_ERROR, trustListener);
m.getData().putCharSequence(DATA_MESSAGE, message);
m.sendToTarget();
}
diff --git a/core/java/android/app/usage/CacheQuotaHint.java b/core/java/android/app/usage/CacheQuotaHint.java
index ba6bcdc936ba..0ccb058d11cf 100644
--- a/core/java/android/app/usage/CacheQuotaHint.java
+++ b/core/java/android/app/usage/CacheQuotaHint.java
@@ -148,7 +148,7 @@ public final class CacheQuotaHint implements Parcelable {
return builder.setVolumeUuid(in.readString())
.setUid(in.readInt())
.setQuota(in.readLong())
- .setUsageStats(in.readParcelable(UsageStats.class.getClassLoader(), android.app.usage.UsageStats.class))
+ .setUsageStats(in.readParcelable(UsageStats.class.getClassLoader()))
.build();
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 856a8e1f8199..a695f6d2e7a7 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2249,17 +2249,17 @@ public final class BluetoothAdapter {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
- BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.FEATURE_SUPPORTED,
BluetoothStatusCodes.ERROR_UNKNOWN,
BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
- BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED,
+ BluetoothStatusCodes.FEATURE_NOT_SUPPORTED,
})
public @interface LeFeatureReturnValues {}
/**
- * Returns {@link BluetoothStatusCodes#SUCCESS} if the LE audio feature is
- * supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if
- * the feature is not supported or an error code.
+ * Returns {@link BluetoothStatusCodes#FEATURE_SUPPORTED} if the LE audio feature is
+ * supported, {@link BluetoothStatusCodes#FEATURE_NOT_SUPPORTED} if the feature is not
+ * supported, or an error code.
*
* @return whether the LE audio is supported
*/
@@ -2282,9 +2282,10 @@ public final class BluetoothAdapter {
}
/**
- * Returns {@link BluetoothStatusCodes#SUCCESS} if LE Periodic Advertising Sync Transfer Sender
- * feature is supported, returns {@link BluetoothStatusCodes#ERROR_FEATURE_NOT_SUPPORTED} if the
- * feature is not supported or an error code
+ * Returns {@link BluetoothStatusCodes#FEATURE_SUPPORTED} if LE Periodic Advertising Sync
+ * Transfer Sender feature is supported,
+ * {@link BluetoothStatusCodes#FEATURE_NOT_SUPPORTED} if the feature is not supported, or
+ * an error code
*
* @return whether the chipset supports the LE Periodic Advertising Sync Transfer Sender feature
*/
@@ -3064,6 +3065,9 @@ public final class BluetoothAdapter {
BluetoothCsipSetCoordinator csipSetCoordinator =
new BluetoothCsipSetCoordinator(context, listener, this);
return true;
+ } else if (profile == BluetoothProfile.LE_CALL_CONTROL) {
+ BluetoothLeCallControl tbs = new BluetoothLeCallControl(context, listener);
+ return true;
} else {
return false;
}
@@ -3166,6 +3170,10 @@ public final class BluetoothAdapter {
(BluetoothCsipSetCoordinator) proxy;
csipSetCoordinator.close();
break;
+ case BluetoothProfile.LE_CALL_CONTROL:
+ BluetoothLeCallControl tbs = (BluetoothLeCallControl) proxy;
+ tbs.close();
+ break;
}
}
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index 053e0db3d8a6..c5e986e895b2 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -313,7 +313,7 @@ public class BluetoothGattCharacteristic implements Parcelable {
};
private BluetoothGattCharacteristic(Parcel in) {
- mUuid = ((ParcelUuid) in.readParcelable(null, android.os.ParcelUuid.class)).getUuid();
+ mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
mInstance = in.readInt();
mProperties = in.readInt();
mPermissions = in.readInt();
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index 6ed4706b5fba..a35d5b99fd7b 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -187,7 +187,7 @@ public class BluetoothGattDescriptor implements Parcelable {
};
private BluetoothGattDescriptor(Parcel in) {
- mUuid = ((ParcelUuid) in.readParcelable(null, android.os.ParcelUuid.class)).getUuid();
+ mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
mInstance = in.readInt();
mPermissions = in.readInt();
}
diff --git a/core/java/android/bluetooth/BluetoothGattIncludedService.java b/core/java/android/bluetooth/BluetoothGattIncludedService.java
index 1ae2ca0a92e1..5580619033a6 100644
--- a/core/java/android/bluetooth/BluetoothGattIncludedService.java
+++ b/core/java/android/bluetooth/BluetoothGattIncludedService.java
@@ -76,7 +76,7 @@ public class BluetoothGattIncludedService implements Parcelable {
};
private BluetoothGattIncludedService(Parcel in) {
- mUuid = ((ParcelUuid) in.readParcelable(null, android.os.ParcelUuid.class)).getUuid();
+ mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
mInstanceId = in.readInt();
mServiceType = in.readInt();
}
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index 36bc4772e016..f64d09fc30d9 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -180,7 +180,7 @@ public class BluetoothGattService implements Parcelable {
};
private BluetoothGattService(Parcel in) {
- mUuid = ((ParcelUuid) in.readParcelable(null, android.os.ParcelUuid.class)).getUuid();
+ mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
mInstanceId = in.readInt();
mServiceType = in.readInt();
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index f2a6276ce8fe..2ed1eb40f8a4 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -18,6 +18,7 @@ package android.bluetooth;
import static android.bluetooth.BluetoothUtils.getSyncTimeout;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -44,6 +45,8 @@ import android.util.Log;
import com.android.modules.utils.SynchronousResultReceiver;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;
@@ -895,17 +898,36 @@ public final class BluetoothHeadset implements BluetoothProfile {
com.android.internal.R.bool.config_bluetooth_sco_off_call);
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
+ BluetoothHeadset.STATE_AUDIO_CONNECTING,
+ BluetoothHeadset.STATE_AUDIO_CONNECTED,
+ BluetoothStatusCodes.ERROR_TIMEOUT
+ })
+ public @interface GetAudioStateReturnValues {}
+
/**
* Get the current audio state of the Headset.
- * Note: This is an internal function and shouldn't be exposed
+ *
+ * @param device is the Bluetooth device for which the audio state is being queried
+ * @return the audio state of the device or an error code
+ * @throws IllegalArgumentException if the device is null
*
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @SystemApi
@RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public int getAudioState(BluetoothDevice device) {
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public @GetAudioStateReturnValues int getAudioState(@NonNull BluetoothDevice device) {
if (VDBG) log("getAudioState");
+ if (device == null) {
+ throw new IllegalArgumentException("device cannot be null");
+ }
final IBluetoothHeadset service = mService;
final int defaultValue = BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
if (service == null) {
@@ -916,8 +938,12 @@ public final class BluetoothHeadset implements BluetoothProfile {
final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
service.getAudioState(device, mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
+ } catch (RemoteException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ throw e.rethrowFromSystemServer();
+ } catch (TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ return BluetoothStatusCodes.ERROR_TIMEOUT;
}
}
return defaultValue;
@@ -1005,103 +1031,112 @@ public final class BluetoothHeadset implements BluetoothProfile {
}
}
- /**
- * Check if at least one headset's SCO audio is connected or connecting
- *
- * @return true if at least one device's SCO audio is connected or connecting, false otherwise
- * or on error
- * @hide
- */
- @RequiresLegacyBluetoothPermission
- @RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean isAudioOn() {
- if (VDBG) log("isAudioOn()");
- final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
- if (service == null) {
- Log.w(TAG, "Proxy not attached to service");
- if (DBG) log(Log.getStackTraceString(new Throwable()));
- } else if (isEnabled()) {
- try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
- service.isAudioOn(mAttributionSource, recv);
- return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
- Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
- }
- }
- return defaultValue;
- }
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_UNKNOWN,
+ BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
+ BluetoothStatusCodes.ERROR_TIMEOUT,
+ BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_CONNECTED,
+ BluetoothStatusCodes.ERROR_NO_ACTIVE_DEVICES,
+ BluetoothStatusCodes.ERROR_NOT_ACTIVE_DEVICE,
+ BluetoothStatusCodes.ERROR_AUDIO_ROUTE_BLOCKED,
+ BluetoothStatusCodes.ERROR_CALL_ACTIVE,
+ BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED
+ })
+ public @interface ConnectAudioReturnValues {}
/**
- * Initiates a connection of headset audio to the current active device
- *
- * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
- * If this function returns true, this intent will be broadcasted with
- * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
- *
- * <p> {@link #EXTRA_STATE} will transition from
- * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
- * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
- * in case of failure to establish the audio connection.
- *
- * Note that this intent will not be sent if {@link BluetoothHeadset#isAudioOn()} is true
- * before calling this method
+ * Initiates a connection of SCO audio to the current active HFP device. The active HFP device
+ * can be identified with {@link BluetoothAdapter#getActiveDevices(int)}.
+ * <p>
+ * If this function returns {@link BluetoothStatusCodes#SUCCESS}, the intent
+ * {@link #ACTION_AUDIO_STATE_CHANGED} will be broadcasted twice. First with {@link #EXTRA_STATE}
+ * set to {@link #STATE_AUDIO_CONNECTING}. This will be followed by a broadcast with
+ * {@link #EXTRA_STATE} set to either {@link #STATE_AUDIO_CONNECTED} if the audio connection is
+ * established or {@link #STATE_AUDIO_DISCONNECTED} if there was a failure in establishing the
+ * audio connection.
*
- * @return false if there was some error such as there is no active headset
+ * @return whether the connection was successfully initiated or an error code on failure
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
@RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean connectAudio() {
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public @ConnectAudioReturnValues int connectAudio() {
if (VDBG) log("connectAudio()");
final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
+ final int defaultValue = BluetoothStatusCodes.ERROR_UNKNOWN;
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
} else if (isEnabled()) {
try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
+ final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
service.connectAudio(mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
+ } catch (RemoteException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ throw e.rethrowFromSystemServer();
+ } catch (TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ return BluetoothStatusCodes.ERROR_TIMEOUT;
}
}
return defaultValue;
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_UNKNOWN,
+ BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
+ BluetoothStatusCodes.ERROR_TIMEOUT,
+ BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED,
+ BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED
+ })
+ public @interface DisconnectAudioReturnValues {}
+
/**
- * Initiates a disconnection of HFP SCO audio.
- * Tear down voice recognition or virtual voice call if any.
+ * Initiates a disconnection of HFP SCO audio from actively connected devices. It also tears
+ * down voice recognition or virtual voice call, if any exists.
*
- * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
- * If this function returns true, this intent will be broadcasted with
- * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}.
+ * <p> If this function returns {@link BluetoothStatusCodes#SUCCESS}, the intent
+ * {@link #ACTION_AUDIO_STATE_CHANGED} will be broadcasted with {@link #EXTRA_STATE} set to
+ * {@link #STATE_AUDIO_DISCONNECTED}.
*
- * @return false if audio is not connected, or on error, true otherwise
+ * @return whether the disconnection was initiated successfully or an error code on failure
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
@RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- public boolean disconnectAudio() {
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public @DisconnectAudioReturnValues int disconnectAudio() {
if (VDBG) log("disconnectAudio()");
final IBluetoothHeadset service = mService;
- final boolean defaultValue = false;
+ final int defaultValue = BluetoothStatusCodes.ERROR_UNKNOWN;
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
if (DBG) log(Log.getStackTraceString(new Throwable()));
} else if (isEnabled()) {
try {
- final SynchronousResultReceiver<Boolean> recv = new SynchronousResultReceiver();
+ final SynchronousResultReceiver<Integer> recv = new SynchronousResultReceiver();
service.disconnectAudio(mAttributionSource, recv);
return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
- } catch (RemoteException | TimeoutException e) {
+ } catch (RemoteException e) {
Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ throw e.rethrowFromSystemServer();
+ } catch (TimeoutException e) {
+ Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
+ return BluetoothStatusCodes.ERROR_TIMEOUT;
}
}
return defaultValue;
@@ -1386,7 +1421,10 @@ public final class BluetoothHeadset implements BluetoothProfile {
@SystemApi
@RequiresLegacyBluetoothPermission
@RequiresBluetoothConnectPermission
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean isInbandRingingEnabled() {
if (DBG) log("isInbandRingingEnabled()");
final IBluetoothHeadset service = mService;
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
index e9dd761efdf6..032b507f5d3c 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClientCall.java
@@ -292,7 +292,7 @@ public final class BluetoothHeadsetClientCall implements Parcelable, Attributabl
new Parcelable.Creator<BluetoothHeadsetClientCall>() {
@Override
public BluetoothHeadsetClientCall createFromParcel(Parcel in) {
- return new BluetoothHeadsetClientCall((BluetoothDevice) in.readParcelable(null, android.bluetooth.BluetoothDevice.class),
+ return new BluetoothHeadsetClientCall((BluetoothDevice) in.readParcelable(null),
in.readInt(), UUID.fromString(in.readString()), in.readInt(),
in.readString(), in.readInt() == 1, in.readInt() == 1,
in.readInt() == 1);
diff --git a/core/java/android/bluetooth/BluetoothLeCall.java b/core/java/android/bluetooth/BluetoothLeCall.java
new file mode 100644
index 000000000000..fb7789db25c7
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothLeCall.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2021 HIMSA II K/S - www.himsa.com.
+ * Represented by EHIMA - www.ehima.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelUuid;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * Representation of Call
+ *
+ * @hide
+ */
+public final class BluetoothLeCall implements Parcelable {
+
+ /** @hide */
+ @IntDef(prefix = "STATE_", value = {
+ STATE_INCOMING,
+ STATE_DIALING,
+ STATE_ALERTING,
+ STATE_ACTIVE,
+ STATE_LOCALLY_HELD,
+ STATE_REMOTELY_HELD,
+ STATE_LOCALLY_AND_REMOTELY_HELD
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface State {
+ }
+
+ /**
+ * A remote party is calling (incoming call).
+ *
+ * @hide
+ */
+ public static final int STATE_INCOMING = 0x00;
+
+ /**
+ * The process to call the remote party has started but the remote party is not
+ * being alerted (outgoing call).
+ *
+ * @hide
+ */
+ public static final int STATE_DIALING = 0x01;
+
+ /**
+ * A remote party is being alerted (outgoing call).
+ *
+ * @hide
+ */
+ public static final int STATE_ALERTING = 0x02;
+
+ /**
+ * The call is in an active conversation.
+ *
+ * @hide
+ */
+ public static final int STATE_ACTIVE = 0x03;
+
+ /**
+ * The call is connected but held locally. “Locally Held” implies that either
+ * the server or the client can affect the state.
+ *
+ * @hide
+ */
+ public static final int STATE_LOCALLY_HELD = 0x04;
+
+ /**
+ * The call is connected but held remotely. “Remotely Held” means that the state
+ * is controlled by the remote party of a call.
+ *
+ * @hide
+ */
+ public static final int STATE_REMOTELY_HELD = 0x05;
+
+ /**
+ * The call is connected but held both locally and remotely.
+ *
+ * @hide
+ */
+ public static final int STATE_LOCALLY_AND_REMOTELY_HELD = 0x06;
+
+ /**
+ * Whether the call direction is outgoing.
+ *
+ * @hide
+ */
+ public static final int FLAG_OUTGOING_CALL = 0x00000001;
+
+ /**
+ * Whether the call URI and Friendly Name are withheld by server.
+ *
+ * @hide
+ */
+ public static final int FLAG_WITHHELD_BY_SERVER = 0x00000002;
+
+ /**
+ * Whether the call URI and Friendly Name are withheld by network.
+ *
+ * @hide
+ */
+ public static final int FLAG_WITHHELD_BY_NETWORK = 0x00000004;
+
+ /** Unique UUID that identifies this call */
+ private UUID mUuid;
+
+ /** Remote Caller URI */
+ private String mUri;
+
+ /** Caller friendly name */
+ private String mFriendlyName;
+
+ /** Call state */
+ private @State int mState;
+
+ /** Call flags */
+ private int mCallFlags;
+
+ /** @hide */
+ public BluetoothLeCall(@NonNull BluetoothLeCall that) {
+ mUuid = new UUID(that.getUuid().getMostSignificantBits(),
+ that.getUuid().getLeastSignificantBits());
+ mUri = that.mUri;
+ mFriendlyName = that.mFriendlyName;
+ mState = that.mState;
+ mCallFlags = that.mCallFlags;
+ }
+
+ /** @hide */
+ public BluetoothLeCall(@NonNull UUID uuid, @NonNull String uri, @NonNull String friendlyName,
+ @State int state, int callFlags) {
+ mUuid = uuid;
+ mUri = uri;
+ mFriendlyName = friendlyName;
+ mState = state;
+ mCallFlags = callFlags;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ BluetoothLeCall that = (BluetoothLeCall) o;
+ return mUuid.equals(that.mUuid) && mUri.equals(that.mUri)
+ && mFriendlyName.equals(that.mFriendlyName) && mState == that.mState
+ && mCallFlags == that.mCallFlags;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUuid, mUri, mFriendlyName, mState, mCallFlags);
+ }
+
+ /**
+ * Returns a string representation of this BluetoothLeCall.
+ *
+ * <p>
+ * Currently this is the UUID.
+ *
+ * @return string representation of this BluetoothLeCall
+ */
+ @Override
+ public String toString() {
+ return mUuid.toString();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeParcelable(new ParcelUuid(mUuid), 0);
+ out.writeString(mUri);
+ out.writeString(mFriendlyName);
+ out.writeInt(mState);
+ out.writeInt(mCallFlags);
+ }
+
+ public static final @android.annotation.NonNull Parcelable.Creator<BluetoothLeCall> CREATOR =
+ new Parcelable.Creator<BluetoothLeCall>() {
+ public BluetoothLeCall createFromParcel(Parcel in) {
+ return new BluetoothLeCall(in);
+ }
+
+ public BluetoothLeCall[] newArray(int size) {
+ return new BluetoothLeCall[size];
+ }
+ };
+
+ private BluetoothLeCall(Parcel in) {
+ mUuid = ((ParcelUuid) in.readParcelable(null)).getUuid();
+ mUri = in.readString();
+ mFriendlyName = in.readString();
+ mState = in.readInt();
+ mCallFlags = in.readInt();
+ }
+
+ /**
+ * Returns an UUID of this BluetoothLeCall.
+ *
+ * <p>
+ * An UUID is unique identifier of a BluetoothLeCall.
+ *
+ * @return UUID of this BluetoothLeCall
+ * @hide
+ */
+ public @NonNull UUID getUuid() {
+ return mUuid;
+ }
+
+ /**
+ * Returns a URI of the remote party of this BluetoothLeCall.
+ *
+ * @return string representation of this BluetoothLeCall
+ * @hide
+ */
+ public @NonNull String getUri() {
+ return mUri;
+ }
+
+ /**
+ * Returns a friendly name of the call.
+ *
+ * @return friendly name representation of this BluetoothLeCall
+ * @hide
+ */
+ public @NonNull String getFriendlyName() {
+ return mFriendlyName;
+ }
+
+ /**
+ * Returns the call state.
+ *
+ * @return the state of this BluetoothLeCall
+ * @hide
+ */
+ public @State int getState() {
+ return mState;
+ }
+
+ /**
+ * Returns the call flags.
+ *
+ * @return call flags
+ * @hide
+ */
+ public int getCallFlags() {
+ return mCallFlags;
+ }
+
+ /**
+ * Whether the call direction is incoming.
+ *
+ * @return true if incoming call, false otherwise
+ * @hide
+ */
+ public boolean isIncomingCall() {
+ return (mCallFlags & FLAG_OUTGOING_CALL) == 0;
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothLeCallControl.java b/core/java/android/bluetooth/BluetoothLeCallControl.java
new file mode 100644
index 000000000000..fb080c9ec3e3
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothLeCallControl.java
@@ -0,0 +1,899 @@
+/*
+ * Copyright 2019 HIMSA II K/S - www.himsa.com.
+ * Represented by EHIMA - www.ehima.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.Manifest;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Log;
+import android.annotation.SuppressLint;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+
+/**
+ * This class provides the APIs to control the Call Control profile.
+ *
+ * <p>
+ * This class provides Bluetooth Telephone Bearer Service functionality,
+ * allowing applications to expose a GATT Service based interface to control the
+ * state of the calls by remote devices such as LE audio devices.
+ *
+ * <p>
+ * BluetoothLeCallControl is a proxy object for controlling the Bluetooth Telephone Bearer
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get the
+ * BluetoothLeCallControl proxy object.
+ *
+ * @hide
+ */
+public final class BluetoothLeCallControl implements BluetoothProfile {
+ private static final String TAG = "BluetoothLeCallControl";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ /** @hide */
+ @IntDef(prefix = "RESULT_", value = {
+ RESULT_SUCCESS,
+ RESULT_ERROR_UNKNOWN_CALL_ID,
+ RESULT_ERROR_INVALID_URI,
+ RESULT_ERROR_APPLICATION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Result {
+ }
+
+ /**
+ * Opcode write was successful.
+ *
+ * @hide
+ */
+ public static final int RESULT_SUCCESS = 0;
+
+ /**
+ * Unknown call Id has been used in the operation.
+ *
+ * @hide
+ */
+ public static final int RESULT_ERROR_UNKNOWN_CALL_ID = 1;
+
+ /**
+ * The URI provided in {@link Callback#onPlaceCallRequest} is invalid.
+ *
+ * @hide
+ */
+ public static final int RESULT_ERROR_INVALID_URI = 2;
+
+ /**
+ * Application internal error.
+ *
+ * @hide
+ */
+ public static final int RESULT_ERROR_APPLICATION = 3;
+
+ /** @hide */
+ @IntDef(prefix = "TERMINATION_REASON_", value = {
+ TERMINATION_REASON_INVALID_URI,
+ TERMINATION_REASON_FAIL,
+ TERMINATION_REASON_REMOTE_HANGUP,
+ TERMINATION_REASON_SERVER_HANGUP,
+ TERMINATION_REASON_LINE_BUSY,
+ TERMINATION_REASON_NETWORK_CONGESTION,
+ TERMINATION_REASON_CLIENT_HANGUP,
+ TERMINATION_REASON_NO_SERVICE,
+ TERMINATION_REASON_NO_ANSWER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface TerminationReason {
+ }
+
+ /**
+ * Remote Caller ID value used to place a call was formed improperly.
+ *
+ * @hide
+ */
+ public static final int TERMINATION_REASON_INVALID_URI = 0x00;
+
+ /**
+ * Call fail.
+ *
+ * @hide
+ */
+ public static final int TERMINATION_REASON_FAIL = 0x01;
+
+ /**
+ * Remote party ended call.
+ *
+ * @hide
+ */
+ public static final int TERMINATION_REASON_REMOTE_HANGUP = 0x02;
+
+ /**
+ * Call ended from the server.
+ *
+ * @hide
+ */
+ public static final int TERMINATION_REASON_SERVER_HANGUP = 0x03;
+
+ /**
+ * Line busy.
+ *
+ * @hide
+ */
+ public static final int TERMINATION_REASON_LINE_BUSY = 0x04;
+
+ /**
+ * Network congestion.
+ *
+ * @hide
+ */
+ public static final int TERMINATION_REASON_NETWORK_CONGESTION = 0x05;
+
+ /**
+ * Client terminated.
+ *
+ * @hide
+ */
+ public static final int TERMINATION_REASON_CLIENT_HANGUP = 0x06;
+
+ /**
+ * No service.
+ *
+ * @hide
+ */
+ public static final int TERMINATION_REASON_NO_SERVICE = 0x07;
+
+ /**
+ * No answer.
+ *
+ * @hide
+ */
+ public static final int TERMINATION_REASON_NO_ANSWER = 0x08;
+
+ /*
+ * Flag indicating support for hold/unhold call feature.
+ *
+ * @hide
+ */
+ public static final int CAPABILITY_HOLD_CALL = 0x00000001;
+
+ /**
+ * Flag indicating support for joining calls feature.
+ *
+ * @hide
+ */
+ public static final int CAPABILITY_JOIN_CALLS = 0x00000002;
+
+ private static final int MESSAGE_TBS_SERVICE_CONNECTED = 102;
+ private static final int MESSAGE_TBS_SERVICE_DISCONNECTED = 103;
+
+ private static final int REG_TIMEOUT = 10000;
+
+ /**
+ * The template class is used to call callback functions on events from the TBS
+ * server. Callback functions are wrapped in this class and registered to the
+ * Android system during app registration.
+ *
+ * @hide
+ */
+ public abstract static class Callback {
+
+ private static final String TAG = "BluetoothLeCallControl.Callback";
+
+ /**
+ * Called when a remote client requested to accept the call.
+ *
+ * <p>
+ * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
+ * request.
+ *
+ * @param requestId The Id of the request
+ * @param callId The call Id requested to be accepted
+ * @hide
+ */
+ public abstract void onAcceptCall(int requestId, @NonNull UUID callId);
+
+ /**
+ * A remote client has requested to terminate the call.
+ *
+ * <p>
+ * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
+ * request.
+ *
+ * @param requestId The Id of the request
+ * @param callId The call Id requested to terminate
+ * @hide
+ */
+ public abstract void onTerminateCall(int requestId, @NonNull UUID callId);
+
+ /**
+ * A remote client has requested to hold the call.
+ *
+ * <p>
+ * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
+ * request.
+ *
+ * @param requestId The Id of the request
+ * @param callId The call Id requested to be put on hold
+ * @hide
+ */
+ public void onHoldCall(int requestId, @NonNull UUID callId) {
+ Log.e(TAG, "onHoldCall: unimplemented, however CAPABILITY_HOLD_CALL is set!");
+ }
+
+ /**
+ * A remote client has requested to unhold the call.
+ *
+ * <p>
+ * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
+ * request.
+ *
+ * @param requestId The Id of the request
+ * @param callId The call Id requested to unhold
+ * @hide
+ */
+ public void onUnholdCall(int requestId, @NonNull UUID callId) {
+ Log.e(TAG, "onUnholdCall: unimplemented, however CAPABILITY_HOLD_CALL is set!");
+ }
+
+ /**
+ * A remote client has requested to place a call.
+ *
+ * <p>
+ * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
+ * request.
+ *
+ * @param requestId The Id of the request
+ * @param callId The Id to be assigned for the new call
+ * @param uri The caller URI requested
+ * @hide
+ */
+ public abstract void onPlaceCall(int requestId, @NonNull UUID callId, @NonNull String uri);
+
+ /**
+ * A remote client has requested to join the calls.
+ *
+ * <p>
+ * An application must call {@link BluetoothLeCallControl#requestResult} to complete the
+ * request.
+ *
+ * @param requestId The Id of the request
+ * @param callIds The call Id list requested to join
+ * @hide
+ */
+ public void onJoinCalls(int requestId, @NonNull List<UUID> callIds) {
+ Log.e(TAG, "onJoinCalls: unimplemented, however CAPABILITY_JOIN_CALLS is set!");
+ }
+ }
+
+ private class CallbackWrapper extends IBluetoothLeCallControlCallback.Stub {
+
+ private final Executor mExecutor;
+ private final Callback mCallback;
+
+ CallbackWrapper(Executor executor, Callback callback) {
+ mExecutor = executor;
+ mCallback = callback;
+ }
+
+ @Override
+ public void onBearerRegistered(int ccid) {
+ if (mCallback != null) {
+ mCcid = ccid;
+ } else {
+ // registration timeout
+ Log.e(TAG, "onBearerRegistered: mCallback is null");
+ }
+ }
+
+ @Override
+ public void onAcceptCall(int requestId, ParcelUuid uuid) {
+ final long identityToken = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onAcceptCall(requestId, uuid.getUuid()));
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ }
+
+ @Override
+ public void onTerminateCall(int requestId, ParcelUuid uuid) {
+ final long identityToken = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onTerminateCall(requestId, uuid.getUuid()));
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ }
+
+ @Override
+ public void onHoldCall(int requestId, ParcelUuid uuid) {
+ final long identityToken = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onHoldCall(requestId, uuid.getUuid()));
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ }
+
+ @Override
+ public void onUnholdCall(int requestId, ParcelUuid uuid) {
+ final long identityToken = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onUnholdCall(requestId, uuid.getUuid()));
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ }
+
+ @Override
+ public void onPlaceCall(int requestId, ParcelUuid uuid, String uri) {
+ final long identityToken = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onPlaceCall(requestId, uuid.getUuid(), uri));
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ }
+
+ @Override
+ public void onJoinCalls(int requestId, List<ParcelUuid> parcelUuids) {
+ List<UUID> uuids = new ArrayList<>();
+ for (ParcelUuid parcelUuid : parcelUuids) {
+ uuids.add(parcelUuid.getUuid());
+ }
+
+ final long identityToken = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onJoinCalls(requestId, uuids));
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
+ }
+ }
+ };
+
+ private Context mContext;
+ private ServiceListener mServiceListener;
+ private volatile IBluetoothLeCallControl mService;
+ private BluetoothAdapter mAdapter;
+ private int mCcid = 0;
+ private String mToken;
+ private Callback mCallback = null;
+
+ private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+ public void onBluetoothStateChange(boolean up) {
+ if (DBG)
+ Log.d(TAG, "onBluetoothStateChange: up=" + up);
+ if (!up) {
+ doUnbind();
+ } else {
+ doBind();
+ }
+ }
+ };
+
+ /**
+ * Create a BluetoothLeCallControl proxy object for interacting with the local Bluetooth
+ * telephone bearer service.
+ */
+ /* package */ BluetoothLeCallControl(Context context, ServiceListener listener) {
+ mContext = context;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mServiceListener = listener;
+
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+
+ doBind();
+ }
+
+ private boolean doBind() {
+ synchronized (mConnection) {
+ if (mService == null) {
+ if (VDBG)
+ Log.d(TAG, "Binding service...");
+ try {
+ return mAdapter.getBluetoothManager().
+ bindBluetoothProfileService(BluetoothProfile.LE_CALL_CONTROL,
+ mConnection);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to bind TelephoneBearerService", e);
+ }
+ }
+ }
+ return false;
+ }
+
+ private void doUnbind() {
+ synchronized (mConnection) {
+ if (mService != null) {
+ if (VDBG)
+ Log.d(TAG, "Unbinding service...");
+ try {
+ mAdapter.getBluetoothManager().
+ unbindBluetoothProfileService(BluetoothProfile.LE_CALL_CONTROL,
+ mConnection);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to unbind TelephoneBearerService", e);
+ } finally {
+ mService = null;
+ }
+ }
+ }
+ }
+
+ /* package */ void close() {
+ if (VDBG)
+ log("close()");
+ unregisterBearer();
+
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException re) {
+ Log.e(TAG, "", re);
+ }
+ }
+ mServiceListener = null;
+ doUnbind();
+ }
+
+ private IBluetoothLeCallControl getService() {
+ return mService;
+ }
+
+ /**
+ * Not supported
+ *
+ * @throws UnsupportedOperationException
+ */
+ @Override
+ public int getConnectionState(@Nullable BluetoothDevice device) {
+ throw new UnsupportedOperationException("not supported");
+ }
+
+ /**
+ * Not supported
+ *
+ * @throws UnsupportedOperationException
+ */
+ @Override
+ public @NonNull List<BluetoothDevice> getConnectedDevices() {
+ throw new UnsupportedOperationException("not supported");
+ }
+
+ /**
+ * Not supported
+ *
+ * @throws UnsupportedOperationException
+ */
+ @Override
+ public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
+ @NonNull int[] states) {
+ throw new UnsupportedOperationException("not supported");
+ }
+
+ /**
+ * Register Telephone Bearer exposing the interface that allows remote devices
+ * to track and control the call states.
+ *
+ * <p>
+ * This is an asynchronous call. The callback is used to notify success or
+ * failure if the function returns true.
+ *
+ * <p>
+ * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * <!-- The UCI is a String identifier of the telephone bearer as defined at
+ * https://www.bluetooth.com/specifications/assigned-numbers/uniform-caller-identifiers
+ * (login required). -->
+ *
+ * <!-- The examples of common URI schemes can be found in
+ * https://iana.org/assignments/uri-schemes/uri-schemes.xhtml -->
+ *
+ * <!-- The Technology is an integer value. The possible values are defined at
+ * https://www.bluetooth.com/specifications/assigned-numbers (login required).
+ * -->
+ *
+ * @param uci Bearer Unique Client Identifier
+ * @param uriSchemes URI Schemes supported list
+ * @param capabilities bearer capabilities
+ * @param provider Network provider name
+ * @param technology Network technology
+ * @param executor {@link Executor} object on which callback will be
+ * executed. The Executor object is required.
+ * @param callback {@link Callback} object to which callback messages will
+ * be sent. The Callback object is required.
+ * @return true on success, false otherwise
+ * @hide
+ */
+ @SuppressLint("ExecutorRegistration")
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public boolean registerBearer(@Nullable String uci,
+ @NonNull List<String> uriSchemes, int capabilities,
+ @NonNull String provider, int technology,
+ @NonNull Executor executor, @NonNull Callback callback) {
+ if (DBG) {
+ Log.d(TAG, "registerBearer");
+ }
+ if (callback == null) {
+ throw new IllegalArgumentException("null parameter: " + callback);
+ }
+ if (mCcid != 0) {
+ return false;
+ }
+
+ mToken = uci;
+
+ final IBluetoothLeCallControl service = getService();
+ if (service != null) {
+ if (mCallback != null) {
+ Log.e(TAG, "Bearer can be opened only once");
+ return false;
+ }
+
+ mCallback = callback;
+ try {
+ CallbackWrapper callbackWrapper = new CallbackWrapper(executor, callback);
+ service.registerBearer(mToken, callbackWrapper, uci, uriSchemes, capabilities,
+ provider, technology);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ mCallback = null;
+ return false;
+ }
+
+ if (mCcid == 0) {
+ mCallback = null;
+ return false;
+ }
+
+ return true;
+ }
+
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+
+ return false;
+ }
+
+ /**
+ * Unregister Telephone Bearer Service and destroy all the associated data.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void unregisterBearer() {
+ if (DBG) {
+ Log.d(TAG, "unregisterBearer");
+ }
+ if (mCcid == 0) {
+ return;
+ }
+
+ int ccid = mCcid;
+ mCcid = 0;
+ mCallback = null;
+
+ final IBluetoothLeCallControl service = getService();
+ if (service != null) {
+ try {
+ service.unregisterBearer(mToken);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ }
+
+ /**
+ * Get the Content Control ID (CCID) value.
+ *
+ * @return ccid Content Control ID value
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public int getContentControlId() {
+ return mCcid;
+ }
+
+ /**
+ * Notify about the newly added call.
+ *
+ * <p>
+ * This shall be called as early as possible after the call has been added.
+ *
+ * <p>
+ * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param call Newly added call
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void onCallAdded(@NonNull BluetoothLeCall call) {
+ if (DBG) {
+ Log.d(TAG, "onCallAdded: call=" + call);
+ }
+ if (mCcid == 0) {
+ return;
+ }
+
+ final IBluetoothLeCallControl service = getService();
+ if (service != null) {
+ try {
+ service.callAdded(mCcid, call);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ }
+
+ /**
+ * Notify about the removed call.
+ *
+ * <p>
+ * This shall be called as early as possible after the call has been removed.
+ *
+ * <p>
+ * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param callId The Id of a call that has been removed
+ * @param reason Call termination reason
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void onCallRemoved(@NonNull UUID callId, @TerminationReason int reason) {
+ if (DBG) {
+ Log.d(TAG, "callRemoved: callId=" + callId);
+ }
+ if (mCcid == 0) {
+ return;
+ }
+
+ final IBluetoothLeCallControl service = getService();
+ if (service != null) {
+ try {
+ service.callRemoved(mCcid, new ParcelUuid(callId), reason);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ }
+
+ /**
+ * Notify the call state change
+ *
+ * <p>
+ * This shall be called as early as possible after the state of the call has
+ * changed.
+ *
+ * <p>
+ * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param callId The call Id that state has been changed
+ * @param state Call state
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void onCallStateChanged(@NonNull UUID callId, @BluetoothLeCall.State int state) {
+ if (DBG) {
+ Log.d(TAG, "callStateChanged: callId=" + callId + " state=" + state);
+ }
+ if (mCcid == 0) {
+ return;
+ }
+
+ final IBluetoothLeCallControl service = getService();
+ if (service != null) {
+ try {
+ service.callStateChanged(mCcid, new ParcelUuid(callId), state);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ }
+
+ /**
+ * Provide the current calls list
+ *
+ * <p>
+ * This function must be invoked after registration if application has any
+ * calls.
+ *
+ * @param calls current calls list
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void currentCallsList(@NonNull List<BluetoothLeCall> calls) {
+ final IBluetoothLeCallControl service = getService();
+ if (service != null) {
+ try {
+ service.currentCallsList(mCcid, calls);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+ }
+
+ /**
+ * Provide the network current status
+ *
+ * <p>
+ * This function must be invoked on change of network state.
+ *
+ * <p>
+ * Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * <!-- The Technology is an integer value. The possible values are defined at
+ * https://www.bluetooth.com/specifications/assigned-numbers (login required).
+ * -->
+ *
+ * @param provider Network provider name
+ * @param technology Network technology
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void networkStateChanged(@NonNull String provider, int technology) {
+ if (DBG) {
+ Log.d(TAG, "networkStateChanged: provider=" + provider + ", technology=" + technology);
+ }
+ if (mCcid == 0) {
+ return;
+ }
+
+ final IBluetoothLeCallControl service = getService();
+ if (service != null) {
+ try {
+ service.networkStateChanged(mCcid, provider, technology);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+ if (service == null) {
+ Log.w(TAG, "Proxy not attached to service");
+ }
+ }
+
+ /**
+ * Send a response to a call control request to a remote device.
+ *
+ * <p>
+ * This function must be invoked in when a request is received by one of these
+ * callback methods:
+ *
+ * <ul>
+ * <li>{@link Callback#onAcceptCall}
+ * <li>{@link Callback#onTerminateCall}
+ * <li>{@link Callback#onHoldCall}
+ * <li>{@link Callback#onUnholdCall}
+ * <li>{@link Callback#onPlaceCall}
+ * <li>{@link Callback#onJoinCalls}
+ * </ul>
+ *
+ * @param requestId The ID of the request that was received with the callback
+ * @param result The result of the request to be sent to the remote devices
+ */
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void requestResult(int requestId, @Result int result) {
+ if (DBG) {
+ Log.d(TAG, "requestResult: requestId=" + requestId + " result=" + result);
+ }
+ if (mCcid == 0) {
+ return;
+ }
+
+ final IBluetoothLeCallControl service = getService();
+ if (service != null) {
+ try {
+ service.requestResult(mCcid, requestId, result);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+ }
+
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ private static boolean isValidDevice(@Nullable BluetoothDevice device) {
+ return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+
+ private final IBluetoothProfileServiceConnection mConnection =
+ new IBluetoothProfileServiceConnection.Stub() {
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ if (DBG) {
+ Log.d(TAG, "Proxy object connected");
+ }
+ mService = IBluetoothLeCallControl.Stub.asInterface(Binder.allowBlocking(service));
+ mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_TBS_SERVICE_CONNECTED));
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ if (DBG) {
+ Log.d(TAG, "Proxy object disconnected");
+ }
+ doUnbind();
+ mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_TBS_SERVICE_DISCONNECTED));
+ }
+ };
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_TBS_SERVICE_CONNECTED: {
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.LE_CALL_CONTROL,
+ BluetoothLeCallControl.this);
+ }
+ break;
+ }
+ case MESSAGE_TBS_SERVICE_DISCONNECTED: {
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.LE_CALL_CONTROL);
+ }
+ break;
+ }
+ }
+ }
+ };
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index e047e5d81a9d..d0f74e985729 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -240,12 +240,19 @@ public interface BluetoothProfile {
int LE_AUDIO_BROADCAST = 26;
/**
+ * @hide
+ * Telephone Bearer Service from Call Control Profile
+ *
+ */
+ int LE_CALL_CONTROL = 27;
+
+ /**
* Max profile ID. This value should be updated whenever a new profile is added to match
* the largest value assigned to a profile.
*
* @hide
*/
- int MAX_PROFILE_ID = 26;
+ int MAX_PROFILE_ID = 27;
/**
* Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
index fff32fffd8a7..a8ce4b411881 100644
--- a/core/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/core/java/android/bluetooth/BluetoothStatusCodes.java
@@ -20,7 +20,7 @@ import android.annotation.SystemApi;
/**
* A class with constants representing possible return values for Bluetooth APIs. General return
- * values occupy the range 0 to 99. Profile-specific return values occupy the range 100-999.
+ * values occupy the range 0 to 199. Profile-specific return values occupy the range 200-999.
* API-specific return values start at 1000. The exception to this is the "UNKNOWN" error code which
* occupies the max integer value.
*/
@@ -29,28 +29,28 @@ public final class BluetoothStatusCodes {
private BluetoothStatusCodes() {}
/**
- * Indicates that the API call was successful
+ * Indicates that the API call was successful.
*/
public static final int SUCCESS = 0;
/**
- * Error code indicating that Bluetooth is not enabled
+ * Error code indicating that Bluetooth is not enabled.
*/
public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1;
/**
* Error code indicating that the API call was initiated by neither the system nor the active
- * user
+ * user.
*/
public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2;
/**
- * Error code indicating that the Bluetooth Device specified is not bonded
+ * Error code indicating that the Bluetooth Device specified is not bonded.
*/
public static final int ERROR_DEVICE_NOT_BONDED = 3;
/**
- * Error code indicating that the Bluetooth Device specified is not connected, but is bonded
+ * Error code indicating that the Bluetooth Device specified is not connected, but is bonded.
*
* @hide
*/
@@ -58,7 +58,7 @@ public final class BluetoothStatusCodes {
/**
* Error code indicating that the caller does not have the
- * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission
+ * {@link android.Manifest.permission#BLUETOOTH_ADVERTISE} permission.
*
* @hide
*/
@@ -66,13 +66,13 @@ public final class BluetoothStatusCodes {
/**
* Error code indicating that the caller does not have the
- * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission
+ * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission.
*/
public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6;
/**
* Error code indicating that the caller does not have the
- * {@link android.Manifest.permission#BLUETOOTH_SCAN} permission
+ * {@link android.Manifest.permission#BLUETOOTH_SCAN} permission.
*
* @hide
*/
@@ -80,30 +80,67 @@ public final class BluetoothStatusCodes {
/**
* Error code indicating that the caller does not have the
- * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission
+ * {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission.
*/
public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8;
/**
* Error code indicating that the profile service is not bound. You can bind a profile service
- * by calling {@link BluetoothAdapter#getProfileProxy}
+ * by calling {@link BluetoothAdapter#getProfileProxy}.
*/
public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9;
/**
- * Error code indicating that the feature is not supported.
+ * Indicates that the feature is supported.
*/
- public static final int ERROR_FEATURE_NOT_SUPPORTED = 10;
+ public static final int FEATURE_SUPPORTED = 10;
+
+ /**
+ * Indicates that the feature is not supported.
+ */
+ public static final int FEATURE_NOT_SUPPORTED = 11;
+
+ /**
+ * Error code indicating that the device is not the active device for this profile.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_NOT_ACTIVE_DEVICE = 12;
+
+ /**
+ * Error code indicating that there are no active devices for the profile.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_NO_ACTIVE_DEVICES = 13;
+
+ /**
+ * Indicates that the Bluetooth profile is not connected to this device.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_PROFILE_NOT_CONNECTED = 14;
+
+ /**
+ * Error code indicating that the requested operation timed out.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_TIMEOUT = 15;
/**
* A GATT writeCharacteristic request is not permitted on the remote device.
*/
- public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101;
+ public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 200;
/**
* A GATT writeCharacteristic request is issued to a busy remote device.
*/
- public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102;
+ public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 201;
/**
* If another application has already requested {@link OobData} then another fetch will be
@@ -286,6 +323,38 @@ public final class BluetoothStatusCodes {
public static final int ERROR_LE_AUDIO_BROADCAST_SOURCE_DISABLE_ENCRYPTION_FAILED = 1115;
/**
+ * Indicates that there is already one device for which SCO audio is connected or connecting.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_AUDIO_DEVICE_ALREADY_CONNECTED = 1116;
+
+ /**
+ * Indicates that SCO audio was already not connected for this device.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_AUDIO_DEVICE_ALREADY_DISCONNECTED = 1117;
+
+ /**
+ * Indicates that there audio route is currently blocked by the system.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_AUDIO_ROUTE_BLOCKED = 1118;
+
+ /**
+ * Indicates that there is an active call preventing this operation from succeeding.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ERROR_CALL_ACTIVE = 1119;
+
+ /**
* Indicates that an unknown error has occurred has occurred.
*/
public static final int ERROR_UNKNOWN = Integer.MAX_VALUE;
diff --git a/core/java/android/bluetooth/BufferConstraints.java b/core/java/android/bluetooth/BufferConstraints.java
index 06b45ee5c8b5..97d97232b7a6 100644
--- a/core/java/android/bluetooth/BufferConstraints.java
+++ b/core/java/android/bluetooth/BufferConstraints.java
@@ -55,7 +55,7 @@ public final class BufferConstraints implements Parcelable {
BufferConstraints(Parcel in) {
mBufferConstraintList = new ArrayList<BufferConstraint>();
mBufferConstraints = new HashMap<Integer, BufferConstraint>();
- in.readList(mBufferConstraintList, BufferConstraint.class.getClassLoader(), android.bluetooth.BufferConstraint.class);
+ in.readList(mBufferConstraintList, BufferConstraint.class.getClassLoader());
for (int i = 0; i < mBufferConstraintList.size(); i++) {
mBufferConstraints.put(i, mBufferConstraintList.get(i));
}
diff --git a/core/java/android/bluetooth/le/AdvertiseSettings.java b/core/java/android/bluetooth/le/AdvertiseSettings.java
index 7129d762cd95..c52a6ee33989 100644
--- a/core/java/android/bluetooth/le/AdvertiseSettings.java
+++ b/core/java/android/bluetooth/le/AdvertiseSettings.java
@@ -16,6 +16,9 @@
package android.bluetooth.le;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.bluetooth.le.AdvertisingSetParameters.AddressTypeStatus;
import android.os.Parcel;
import android.os.Parcelable;
@@ -70,17 +73,21 @@ public final class AdvertiseSettings implements Parcelable {
*/
private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
+
private final int mAdvertiseMode;
private final int mAdvertiseTxPowerLevel;
private final int mAdvertiseTimeoutMillis;
private final boolean mAdvertiseConnectable;
+ private final int mOwnAddressType;
private AdvertiseSettings(int advertiseMode, int advertiseTxPowerLevel,
- boolean advertiseConnectable, int advertiseTimeout) {
+ boolean advertiseConnectable, int advertiseTimeout,
+ @AddressTypeStatus int ownAddressType) {
mAdvertiseMode = advertiseMode;
mAdvertiseTxPowerLevel = advertiseTxPowerLevel;
mAdvertiseConnectable = advertiseConnectable;
mAdvertiseTimeoutMillis = advertiseTimeout;
+ mOwnAddressType = ownAddressType;
}
private AdvertiseSettings(Parcel in) {
@@ -88,6 +95,7 @@ public final class AdvertiseSettings implements Parcelable {
mAdvertiseTxPowerLevel = in.readInt();
mAdvertiseConnectable = in.readInt() != 0;
mAdvertiseTimeoutMillis = in.readInt();
+ mOwnAddressType = in.readInt();
}
/**
@@ -118,12 +126,23 @@ public final class AdvertiseSettings implements Parcelable {
return mAdvertiseTimeoutMillis;
}
+ /**
+ * @return the own address type for advertising
+ *
+ * @hide
+ */
+ @SystemApi
+ public @AddressTypeStatus int getOwnAddressType() {
+ return mOwnAddressType;
+ }
+
@Override
public String toString() {
return "Settings [mAdvertiseMode=" + mAdvertiseMode
+ ", mAdvertiseTxPowerLevel=" + mAdvertiseTxPowerLevel
+ ", mAdvertiseConnectable=" + mAdvertiseConnectable
- + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis + "]";
+ + ", mAdvertiseTimeoutMillis=" + mAdvertiseTimeoutMillis
+ + ", mOwnAddressType=" + mOwnAddressType + "]";
}
@Override
@@ -137,6 +156,7 @@ public final class AdvertiseSettings implements Parcelable {
dest.writeInt(mAdvertiseTxPowerLevel);
dest.writeInt(mAdvertiseConnectable ? 1 : 0);
dest.writeInt(mAdvertiseTimeoutMillis);
+ dest.writeInt(mOwnAddressType);
}
public static final @android.annotation.NonNull Parcelable.Creator<AdvertiseSettings> CREATOR =
@@ -160,6 +180,7 @@ public final class AdvertiseSettings implements Parcelable {
private int mTxPowerLevel = ADVERTISE_TX_POWER_MEDIUM;
private int mTimeoutMillis = 0;
private boolean mConnectable = true;
+ private int mOwnAddressType = AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT;
/**
* Set advertise mode to control the advertising power and latency.
@@ -226,10 +247,31 @@ public final class AdvertiseSettings implements Parcelable {
}
/**
+ * Set own address type for advertising to control public or privacy mode. If used to set
+ * address type anything other than {@link AdvertisingSetParameters#ADDRESS_TYPE_DEFAULT},
+ * then it will require BLUETOOTH_PRIVILEGED permission and will be checked at the
+ * time of starting advertising.
+ *
+ * @throws IllegalArgumentException If the {@code ownAddressType} is invalid
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Builder setOwnAddressType(@AddressTypeStatus int ownAddressType) {
+ if (ownAddressType < AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT
+ || ownAddressType > AdvertisingSetParameters.ADDRESS_TYPE_RANDOM) {
+ throw new IllegalArgumentException("unknown address type " + ownAddressType);
+ }
+ mOwnAddressType = ownAddressType;
+ return this;
+ }
+
+ /**
* Build the {@link AdvertiseSettings} object.
*/
public AdvertiseSettings build() {
- return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutMillis);
+ return new AdvertiseSettings(mMode, mTxPowerLevel, mConnectable, mTimeoutMillis,
+ mOwnAddressType);
}
}
}
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index e39b198ae384..5c8fae65193d 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -16,11 +16,17 @@
package android.bluetooth.le;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* The {@link AdvertisingSetParameters} provide a way to adjust advertising
* preferences for each
@@ -97,6 +103,39 @@ public final class AdvertisingSetParameters implements Parcelable {
*/
private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000;
+ /** @hide */
+ @IntDef(prefix = "ADDRESS_TYPE_", value = {
+ ADDRESS_TYPE_DEFAULT,
+ ADDRESS_TYPE_PUBLIC,
+ ADDRESS_TYPE_RANDOM
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AddressTypeStatus {}
+
+ /**
+ * Advertise own address type that corresponds privacy settings of the device.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ADDRESS_TYPE_DEFAULT = -1;
+
+ /**
+ * Advertise own public address type.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ADDRESS_TYPE_PUBLIC = 0;
+
+ /**
+ * Generate and adverise own resolvable private address.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int ADDRESS_TYPE_RANDOM = 1;
+
private final boolean mIsLegacy;
private final boolean mIsAnonymous;
private final boolean mIncludeTxPower;
@@ -106,11 +145,12 @@ public final class AdvertisingSetParameters implements Parcelable {
private final boolean mScannable;
private final int mInterval;
private final int mTxPowerLevel;
+ private final int mOwnAddressType;
private AdvertisingSetParameters(boolean connectable, boolean scannable, boolean isLegacy,
boolean isAnonymous, boolean includeTxPower,
int primaryPhy, int secondaryPhy,
- int interval, int txPowerLevel) {
+ int interval, int txPowerLevel, @AddressTypeStatus int ownAddressType) {
mConnectable = connectable;
mScannable = scannable;
mIsLegacy = isLegacy;
@@ -120,6 +160,7 @@ public final class AdvertisingSetParameters implements Parcelable {
mSecondaryPhy = secondaryPhy;
mInterval = interval;
mTxPowerLevel = txPowerLevel;
+ mOwnAddressType = ownAddressType;
}
private AdvertisingSetParameters(Parcel in) {
@@ -132,6 +173,7 @@ public final class AdvertisingSetParameters implements Parcelable {
mSecondaryPhy = in.readInt();
mInterval = in.readInt();
mTxPowerLevel = in.readInt();
+ mOwnAddressType = in.readInt();
}
/**
@@ -197,6 +239,16 @@ public final class AdvertisingSetParameters implements Parcelable {
return mTxPowerLevel;
}
+ /**
+ * @return the own address type for advertising
+ *
+ * @hide
+ */
+ @SystemApi
+ public @AddressTypeStatus int getOwnAddressType() {
+ return mOwnAddressType;
+ }
+
@Override
public String toString() {
return "AdvertisingSetParameters [connectable=" + mConnectable
@@ -206,7 +258,8 @@ public final class AdvertisingSetParameters implements Parcelable {
+ ", primaryPhy=" + mPrimaryPhy
+ ", secondaryPhy=" + mSecondaryPhy
+ ", interval=" + mInterval
- + ", txPowerLevel=" + mTxPowerLevel + "]";
+ + ", txPowerLevel=" + mTxPowerLevel
+ + ", ownAddressType=" + mOwnAddressType + "]";
}
@Override
@@ -225,6 +278,7 @@ public final class AdvertisingSetParameters implements Parcelable {
dest.writeInt(mSecondaryPhy);
dest.writeInt(mInterval);
dest.writeInt(mTxPowerLevel);
+ dest.writeInt(mOwnAddressType);
}
public static final @android.annotation.NonNull Parcelable.Creator<AdvertisingSetParameters> CREATOR =
@@ -253,6 +307,7 @@ public final class AdvertisingSetParameters implements Parcelable {
private int mSecondaryPhy = BluetoothDevice.PHY_LE_1M;
private int mInterval = INTERVAL_LOW;
private int mTxPowerLevel = TX_POWER_MEDIUM;
+ private int mOwnAddressType = ADDRESS_TYPE_DEFAULT;
/**
* Set whether the advertisement type should be connectable or
@@ -399,6 +454,26 @@ public final class AdvertisingSetParameters implements Parcelable {
}
/**
+ * Set own address type for advertising to control public or privacy mode. If used to set
+ * address type anything other than {@link AdvertisingSetParameters#ADDRESS_TYPE_DEFAULT},
+ * then it will require BLUETOOTH_PRIVILEGED permission and will be checked at the
+ * time of starting advertising.
+ *
+ * @throws IllegalArgumentException If the {@code ownAddressType} is invalid
+ *
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Builder setOwnAddressType(@AddressTypeStatus int ownAddressType) {
+ if (ownAddressType < AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT
+ || ownAddressType > AdvertisingSetParameters.ADDRESS_TYPE_RANDOM) {
+ throw new IllegalArgumentException("unknown address type " + ownAddressType);
+ }
+ mOwnAddressType = ownAddressType;
+ return this;
+ }
+
+ /**
* Build the {@link AdvertisingSetParameters} object.
*
* @throws IllegalStateException if invalid combination of parameters is used.
@@ -431,7 +506,8 @@ public final class AdvertisingSetParameters implements Parcelable {
}
return new AdvertisingSetParameters(mConnectable, mScannable, mIsLegacy, mIsAnonymous,
- mIncludeTxPower, mPrimaryPhy, mSecondaryPhy, mInterval, mTxPowerLevel);
+ mIncludeTxPower, mPrimaryPhy, mSecondaryPhy, mInterval, mTxPowerLevel,
+ mOwnAddressType);
}
}
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index b9f8a57a75ea..879dceedaaec 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -138,6 +138,7 @@ public final class BluetoothLeAdvertiser {
parameters.setLegacyMode(true);
parameters.setConnectable(isConnectable);
parameters.setScannable(true); // legacy advertisements we support are always scannable
+ parameters.setOwnAddressType(settings.getOwnAddressType());
if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_POWER) {
parameters.setInterval(1600); // 1s
} else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_BALANCED) {
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 675fe05a7dec..b059193ae03f 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -200,28 +200,28 @@ public final class ScanFilter implements Parcelable {
address = in.readString();
}
if (in.readInt() == 1) {
- ParcelUuid uuid = in.readParcelable(ParcelUuid.class.getClassLoader(), android.os.ParcelUuid.class);
+ ParcelUuid uuid = in.readParcelable(ParcelUuid.class.getClassLoader());
builder.setServiceUuid(uuid);
if (in.readInt() == 1) {
ParcelUuid uuidMask = in.readParcelable(
- ParcelUuid.class.getClassLoader(), android.os.ParcelUuid.class);
+ ParcelUuid.class.getClassLoader());
builder.setServiceUuid(uuid, uuidMask);
}
}
if (in.readInt() == 1) {
ParcelUuid solicitationUuid = in.readParcelable(
- ParcelUuid.class.getClassLoader(), android.os.ParcelUuid.class);
+ ParcelUuid.class.getClassLoader());
builder.setServiceSolicitationUuid(solicitationUuid);
if (in.readInt() == 1) {
ParcelUuid solicitationUuidMask = in.readParcelable(
- ParcelUuid.class.getClassLoader(), android.os.ParcelUuid.class);
+ ParcelUuid.class.getClassLoader());
builder.setServiceSolicitationUuid(solicitationUuid,
solicitationUuidMask);
}
}
if (in.readInt() == 1) {
ParcelUuid servcieDataUuid =
- in.readParcelable(ParcelUuid.class.getClassLoader(), android.os.ParcelUuid.class);
+ in.readParcelable(ParcelUuid.class.getClassLoader());
if (in.readInt() == 1) {
int serviceDataLength = in.readInt();
byte[] serviceData = new byte[serviceDataLength];
diff --git a/core/java/android/companion/AssociationInfo.java b/core/java/android/companion/AssociationInfo.java
index 78d5137ebfba..f0566b856dbd 100644
--- a/core/java/android/companion/AssociationInfo.java
+++ b/core/java/android/companion/AssociationInfo.java
@@ -36,6 +36,10 @@ import java.util.Objects;
*/
public final class AssociationInfo implements Parcelable {
/**
+ * A String indicates the selfManaged device is not connected.
+ */
+ private static final String LAST_TIME_CONNECTED_NONE = "None";
+ /**
* A unique ID of this Association record.
* Disclosed to the clients (ie. companion applications) for referring to this record (eg. in
* {@code disassociate()} API call).
@@ -52,6 +56,11 @@ public final class AssociationInfo implements Parcelable {
private final boolean mSelfManaged;
private boolean mNotifyOnDeviceNearby;
private final long mTimeApprovedMs;
+ /**
+ * A long value indicates the last time connected reported by selfManaged devices
+ * Default value is Long.MAX_VALUE.
+ */
+ private long mLastTimeConnectedMs;
/**
* Creates a new Association.
@@ -62,7 +71,7 @@ public final class AssociationInfo implements Parcelable {
public AssociationInfo(int id, @UserIdInt int userId, @NonNull String packageName,
@Nullable MacAddress macAddress, @Nullable CharSequence displayName,
@Nullable String deviceProfile, boolean selfManaged, boolean notifyOnDeviceNearby,
- long timeApprovedMs) {
+ long timeApprovedMs, long lastTimeConnectedMs) {
if (id <= 0) {
throw new IllegalArgumentException("Association ID should be greater than 0");
}
@@ -83,6 +92,7 @@ public final class AssociationInfo implements Parcelable {
mSelfManaged = selfManaged;
mNotifyOnDeviceNearby = notifyOnDeviceNearby;
mTimeApprovedMs = timeApprovedMs;
+ mLastTimeConnectedMs = lastTimeConnectedMs;
}
/**
@@ -151,13 +161,21 @@ public final class AssociationInfo implements Parcelable {
}
/**
- * Should only be used by the CdmService.
+ * Should only be used by the CompanionDeviceManagerService.
* @hide
*/
public void setNotifyOnDeviceNearby(boolean notifyOnDeviceNearby) {
mNotifyOnDeviceNearby = notifyOnDeviceNearby;
}
+ /**
+ * Should only be used by the CompanionDeviceManagerService.
+ * @hide
+ */
+ public void setLastTimeConnected(long lastTimeConnectedMs) {
+ mLastTimeConnectedMs = lastTimeConnectedMs;
+ }
+
/** @hide */
public boolean isNotifyOnDeviceNearby() {
return mNotifyOnDeviceNearby;
@@ -174,6 +192,14 @@ public final class AssociationInfo implements Parcelable {
}
/**
+ * @return the last time self reported disconnected for selfManaged only.
+ * @hide
+ */
+ public Long getLastTimeConnectedMs() {
+ return mLastTimeConnectedMs;
+ }
+
+ /**
* Utility method for checking if the association represents a device with the given MAC
* address.
*
@@ -223,6 +249,9 @@ public final class AssociationInfo implements Parcelable {
+ ", mSelfManaged=" + mSelfManaged
+ ", mNotifyOnDeviceNearby=" + mNotifyOnDeviceNearby
+ ", mTimeApprovedMs=" + new Date(mTimeApprovedMs)
+ + ", mLastTimeConnectedMs=" + (
+ mLastTimeConnectedMs == Long.MAX_VALUE
+ ? LAST_TIME_CONNECTED_NONE : new Date(mLastTimeConnectedMs))
+ '}';
}
@@ -236,6 +265,7 @@ public final class AssociationInfo implements Parcelable {
&& mSelfManaged == that.mSelfManaged
&& mNotifyOnDeviceNearby == that.mNotifyOnDeviceNearby
&& mTimeApprovedMs == that.mTimeApprovedMs
+ && mLastTimeConnectedMs == that.mLastTimeConnectedMs
&& Objects.equals(mPackageName, that.mPackageName)
&& Objects.equals(mDeviceMacAddress, that.mDeviceMacAddress)
&& Objects.equals(mDisplayName, that.mDisplayName)
@@ -245,7 +275,8 @@ public final class AssociationInfo implements Parcelable {
@Override
public int hashCode() {
return Objects.hash(mId, mUserId, mPackageName, mDeviceMacAddress, mDisplayName,
- mDeviceProfile, mSelfManaged, mNotifyOnDeviceNearby, mTimeApprovedMs);
+ mDeviceProfile, mSelfManaged, mNotifyOnDeviceNearby, mTimeApprovedMs,
+ mLastTimeConnectedMs);
}
@Override
@@ -267,6 +298,7 @@ public final class AssociationInfo implements Parcelable {
dest.writeBoolean(mSelfManaged);
dest.writeBoolean(mNotifyOnDeviceNearby);
dest.writeLong(mTimeApprovedMs);
+ dest.writeLong(mLastTimeConnectedMs);
}
private AssociationInfo(@NonNull Parcel in) {
@@ -282,6 +314,7 @@ public final class AssociationInfo implements Parcelable {
mSelfManaged = in.readBoolean();
mNotifyOnDeviceNearby = in.readBoolean();
mTimeApprovedMs = in.readLong();
+ mLastTimeConnectedMs = in.readLong();
}
@NonNull
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
index 1d2f06d34c8c..18a59d863c46 100644
--- a/core/java/android/companion/AssociationRequest.java
+++ b/core/java/android/companion/AssociationRequest.java
@@ -595,7 +595,7 @@ public final class AssociationRequest implements Parcelable {
boolean forceConfirmation = (flg & 0x20) != 0;
boolean skipPrompt = (flg & 0x400) != 0;
List<DeviceFilter<?>> deviceFilters = new ArrayList<>();
- in.readParcelableList(deviceFilters, DeviceFilter.class.getClassLoader(), (Class<android.companion.DeviceFilter<?>>) (Class<?>) android.companion.DeviceFilter.class);
+ in.readParcelableList(deviceFilters, DeviceFilter.class.getClassLoader());
String deviceProfile = (flg & 0x4) == 0 ? null : in.readString();
CharSequence displayName = (flg & 0x8) == 0 ? null : (CharSequence) in.readCharSequence();
String packageName = (flg & 0x40) == 0 ? null : in.readString();
diff --git a/core/java/android/companion/BluetoothDeviceFilter.java b/core/java/android/companion/BluetoothDeviceFilter.java
index e0018f4bad42..be663f7bdc1d 100644
--- a/core/java/android/companion/BluetoothDeviceFilter.java
+++ b/core/java/android/companion/BluetoothDeviceFilter.java
@@ -70,7 +70,7 @@ public final class BluetoothDeviceFilter implements DeviceFilter<BluetoothDevice
}
private static List<ParcelUuid> readUuids(Parcel in) {
- return in.readParcelableList(new ArrayList<>(), ParcelUuid.class.getClassLoader(), android.os.ParcelUuid.class);
+ return in.readParcelableList(new ArrayList<>(), ParcelUuid.class.getClassLoader());
}
/** @hide */
diff --git a/core/java/android/companion/BluetoothLeDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java
index e6091f04a72a..58898cc095be 100644
--- a/core/java/android/companion/BluetoothLeDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLeDeviceFilter.java
@@ -252,7 +252,7 @@ public final class BluetoothLeDeviceFilter implements DeviceFilter<ScanResult> {
public BluetoothLeDeviceFilter createFromParcel(Parcel in) {
Builder builder = new Builder()
.setNamePattern(patternFromString(in.readString()))
- .setScanFilter(in.readParcelable(null, android.bluetooth.le.ScanFilter.class));
+ .setScanFilter(in.readParcelable(null));
byte[] rawDataFilter = in.createByteArray();
byte[] rawDataFilterMask = in.createByteArray();
if (rawDataFilter != null) {
diff --git a/core/java/android/companion/CompanionDeviceService.java b/core/java/android/companion/CompanionDeviceService.java
index 3237f7ca340a..12ced96a0ffb 100644
--- a/core/java/android/companion/CompanionDeviceService.java
+++ b/core/java/android/companion/CompanionDeviceService.java
@@ -28,9 +28,6 @@ import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
-
-import com.android.internal.util.function.pooled.PooledLambda;
-
import java.util.Objects;
/**
@@ -185,31 +182,24 @@ public abstract class CompanionDeviceService extends Service {
public void onBindCompanionDeviceService(@NonNull Intent intent) {
}
- class Stub extends ICompanionDeviceService.Stub {
+ private class Stub extends ICompanionDeviceService.Stub {
+ final Handler mMainHandler = Handler.getMain();
+ final CompanionDeviceService mService = CompanionDeviceService.this;
@Override
public void onDeviceAppeared(AssociationInfo associationInfo) {
- Handler.getMain().post(
- () -> CompanionDeviceService.this.onDeviceAppeared(associationInfo));
+ mMainHandler.postAtFrontOfQueue(() -> mService.onDeviceAppeared(associationInfo));
}
@Override
public void onDeviceDisappeared(AssociationInfo associationInfo) {
- Handler.getMain().post(
- () -> CompanionDeviceService.this.onDeviceDisappeared(associationInfo));
+ mMainHandler.postAtFrontOfQueue(() -> mService.onDeviceDisappeared(associationInfo));
}
+ @Override
public void onDispatchMessage(int messageId, int associationId, @NonNull byte[] message) {
- Handler.getMain().sendMessage(PooledLambda.obtainMessage(
- CompanionDeviceService::onDispatchMessage,
- CompanionDeviceService.this, messageId, associationId, message));
- }
-
- public final void dispatchMessage(int messageId, int associationId,
- @NonNull byte[] message) {
- Handler.getMain().sendMessage(PooledLambda.obtainMessage(
- CompanionDeviceService::dispatchMessage,
- CompanionDeviceService.this, messageId, associationId, message));
+ mMainHandler.postAtFrontOfQueue(
+ () -> mService.onDispatchMessage(messageId, associationId, message));
}
}
}
diff --git a/core/java/android/app/communal/ICommunalModeListener.aidl b/core/java/android/companion/SystemDataTransferRequest.aidl
index 006e782c52ee..19ae60effa7a 100644
--- a/core/java/android/app/communal/ICommunalModeListener.aidl
+++ b/core/java/android/companion/SystemDataTransferRequest.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,6 @@
* limitations under the License.
*/
-package android.app.communal;
+package android.companion;
-/**
- * System private API to be notified about communal mode changes.
- *
- * @hide
- */
-oneway interface ICommunalModeListener {
- void onCommunalModeChanged(boolean isCommunalMode);
-} \ No newline at end of file
+parcelable SystemDataTransferRequest;
diff --git a/core/java/android/companion/SystemDataTransferRequest.java b/core/java/android/companion/SystemDataTransferRequest.java
new file mode 100644
index 000000000000..e3b0369e203d
--- /dev/null
+++ b/core/java/android/companion/SystemDataTransferRequest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.companion;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.OneTimeUseBuilder;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A request for users to allow the companion app to transfer system data to the companion devices.
+ *
+ * @hide
+ */
+public final class SystemDataTransferRequest implements Parcelable {
+
+ private final int mAssociationId;
+ private final boolean mPermissionSyncAllPackages;
+ private final List<String> mPermissionSyncPackages;
+
+ /**
+ * @hide
+ */
+ public SystemDataTransferRequest(int associationId, boolean syncAllPackages,
+ @Nullable List<String> permissionSyncPackages) {
+ mAssociationId = associationId;
+ mPermissionSyncAllPackages = syncAllPackages;
+ mPermissionSyncPackages = permissionSyncPackages;
+ }
+
+ public int getAssociationId() {
+ return mAssociationId;
+ }
+
+ @NonNull
+ public boolean isPermissionSyncAllPackages() {
+ return mPermissionSyncAllPackages;
+ }
+
+ @NonNull
+ public List<String> getPermissionSyncPackages() {
+ return mPermissionSyncPackages;
+ }
+
+ /**
+ * A builder for {@link SystemDataTransferRequest}.
+ *
+ * <p>You have to call one of the below methods to create a valid request</p>
+ * <br>1. {@link #setPermissionSyncAllPackages()}
+ * <br>2. {@link #setPermissionSyncPackages(List)}
+ */
+ public static final class Builder extends OneTimeUseBuilder<SystemDataTransferRequest> {
+
+ private final int mAssociationId;
+ private boolean mPermissionSyncAllPackages;
+ private List<String> mPermissionSyncPackages = new ArrayList<>();
+
+ public Builder(int associationId) {
+ mAssociationId = associationId;
+ }
+
+ /**
+ * Call to sync permissions for all the packages. You can optionally call
+ * {@link #setPermissionSyncPackages(List)} to specify the packages to sync permissions.
+ *
+ * <p>The system will only sync permissions that are explicitly granted by the user.</p>
+ *
+ * <p>If a permission is granted or revoked by the system or a policy, even if the user has
+ * explicitly granted or revoked the permission earlier, the permission will be ignored.</p>
+ *
+ * <p>If a system or policy granted or revoked permission is granted or revoked by the user
+ * later, the permission will be ignored.</p>
+ *
+ * @see #setPermissionSyncPackages(List)
+ *
+ * @return the builder
+ */
+ @NonNull
+ public Builder setPermissionSyncAllPackages() {
+ mPermissionSyncAllPackages = true;
+ return this;
+ }
+
+ /**
+ * Set a list of packages to sync permissions. You can optionally call
+ * {@link #setPermissionSyncAllPackages()} to sync permissions for all the packages.
+ *
+ * @see #setPermissionSyncAllPackages()
+ *
+ * @param permissionSyncPackages packages to sync permissions
+ * @return builder
+ */
+ @NonNull
+ public Builder setPermissionSyncPackages(@NonNull List<String> permissionSyncPackages) {
+ mPermissionSyncPackages = permissionSyncPackages;
+ return this;
+ }
+
+ @Override
+ @NonNull
+ public SystemDataTransferRequest build() {
+ return new SystemDataTransferRequest(mAssociationId, mPermissionSyncAllPackages,
+ mPermissionSyncPackages);
+ }
+ }
+
+ SystemDataTransferRequest(Parcel in) {
+ mAssociationId = in.readInt();
+ mPermissionSyncAllPackages = in.readBoolean();
+ mPermissionSyncPackages = Arrays.asList(in.createString8Array());
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mAssociationId);
+ dest.writeBoolean(mPermissionSyncAllPackages);
+ dest.writeString8Array(mPermissionSyncPackages.toArray(new String[0]));
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Creator<SystemDataTransferRequest> CREATOR =
+ new Creator<SystemDataTransferRequest>() {
+ @Override
+ public SystemDataTransferRequest createFromParcel(Parcel in) {
+ return new SystemDataTransferRequest(in);
+ }
+
+ @Override
+ public SystemDataTransferRequest[] newArray(int size) {
+ return new SystemDataTransferRequest[size];
+ }
+ };
+}
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 0c065d9bd402..30775b19ab00 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -108,7 +108,7 @@ public class ContentProviderOperation implements Parcelable {
mExtras = null;
}
mSelection = source.readInt() != 0 ? source.readString8() : null;
- mSelectionArgs = source.readSparseArray(null, java.lang.Object.class);
+ mSelectionArgs = source.readSparseArray(null);
mExpectedCount = source.readInt() != 0 ? source.readInt() : null;
mYieldAllowed = source.readInt() != 0;
mExceptionAllowed = source.readInt() != 0;
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index bccfacf70842..2df6f9ae2bd6 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -94,8 +94,11 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
/**
* Interface to global information about an application environment. This is
@@ -6407,6 +6410,43 @@ public abstract class Context {
@Nullable String writePermission, int pid, int uid, @Intent.AccessUriMode int modeFlags,
@Nullable String message);
+
+ /**
+ * Triggers the asynchronous revocation of a permission.
+ *
+ * @param permName The name of the permission to be revoked.
+ * @see #selfRevokePermissions(Collection)
+ */
+ public void selfRevokePermission(@NonNull String permName) {
+ selfRevokePermissions(Collections.singletonList(permName));
+ }
+
+ /**
+ * Triggers the revocation of one or more permissions for the calling package. A package is only
+ * able to revoke a permission under the following conditions:
+ * <ul>
+ * <li>Each permission in {@code permissions} must be granted to the calling package.
+ * <li>Each permission in {@code permissions} must be a runtime permission.
+ * </ul>
+ * <p>
+ * For every permission in {@code permissions}, the entire permission group it belongs to will
+ * be revoked. The revocation happens asynchronously and kills all processes running in the
+ * calling UID. It will be triggered once it is safe to do so. In particular, it will not be
+ * triggered as long as the package remains in the foreground, or has any active manifest
+ * components (e.g. when another app is accessing a content provider in the package).
+ * <p>
+ * If you want to revoke the permissions right away, you could call {@code System.exit()}, but
+ * this could affect other apps that are accessing your app at the moment. For example, apps
+ * accessing a content provider in your app will all crash.
+ *
+ * @param permissions Collection of permissions to be revoked.
+ * @see PackageManager#getGroupOfPlatformPermission(String, Executor, Consumer)
+ * @see PackageManager#getPlatformPermissionsForGroup(String, Executor, Consumer)
+ */
+ public void selfRevokePermissions(@NonNull Collection<String> permissions) {
+ throw new AbstractMethodError("Must be overridden in implementing class");
+ }
+
/** @hide */
@IntDef(flag = true, prefix = { "CONTEXT_" }, value = {
CONTEXT_INCLUDE_CODE,
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 3a02004edb1f..805e499bba46 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -53,6 +53,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collection;
import java.util.List;
import java.util.concurrent.Executor;
@@ -1015,6 +1016,11 @@ public class ContextWrapper extends Context {
}
@Override
+ public void selfRevokePermissions(@NonNull Collection<String> permissions) {
+ mBase.selfRevokePermissions(permissions);
+ }
+
+ @Override
public Context createPackageContext(String packageName, int flags)
throws PackageManager.NameNotFoundException {
return mBase.createPackageContext(packageName, flags);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index af84392b5169..74c326d9386e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4391,9 +4391,9 @@ public class Intent implements Parcelable, Cloneable {
* restored from (corresponds to {@link android.os.Build.VERSION#SDK_INT}). The first three
* values are represented as strings, the fourth one as int.
*
- * <p>This broadcast is sent only for settings provider entries known to require special handling
- * around restore time. These entries are found in the BROADCAST_ON_RESTORE table within
- * the provider's backup agent implementation.
+ * <p>This broadcast is sent only for settings provider entries known to require special
+ * handling around restore time to specific receivers. These entries are found in the
+ * BROADCAST_ON_RESTORE table within the provider's backup agent implementation.
*
* @see #EXTRA_SETTING_NAME
* @see #EXTRA_SETTING_PREVIOUS_VALUE
@@ -4401,15 +4401,46 @@ public class Intent implements Parcelable, Cloneable {
* @see #EXTRA_SETTING_RESTORED_FROM_SDK_INT
* {@hide}
*/
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("ActionValue")
public static final String ACTION_SETTING_RESTORED = "android.os.action.SETTING_RESTORED";
- /** {@hide} */
+ /**
+ * String intent extra to be used with {@link ACTION_SETTING_RESTORED}.
+ * Contain the name of the restored setting.
+ * {@hide}
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("ActionValue")
public static final String EXTRA_SETTING_NAME = "setting_name";
- /** {@hide} */
+
+ /**
+ * String intent extra to be used with {@link ACTION_SETTING_RESTORED}.
+ * Contain the value of the {@link EXTRA_SETTING_NAME} settings entry prior to the restore
+ * operation.
+ * {@hide}
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("ActionValue")
public static final String EXTRA_SETTING_PREVIOUS_VALUE = "previous_value";
- /** {@hide} */
+
+ /**
+ * String intent extra to be used with {@link ACTION_SETTING_RESTORED}.
+ * Contain the value of the {@link EXTRA_SETTING_NAME} settings entry being restored.
+ * {@hide}
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("ActionValue")
public static final String EXTRA_SETTING_NEW_VALUE = "new_value";
- /** {@hide} */
+
+ /**
+ * Int intent extra to be used with {@link ACTION_SETTING_RESTORED}.
+ * Contain the version of the SDK that the setting has been restored from (corresponds to
+ * {@link android.os.Build.VERSION#SDK_INT}).
+ * {@hide}
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("ActionValue")
public static final String EXTRA_SETTING_RESTORED_FROM_SDK_INT = "restored_from_sdk_int";
/**
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 32827ae11e0b..b3435b1180c2 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -1182,7 +1182,7 @@ public class IntentFilter implements Parcelable {
public int match(Uri data, boolean wildcardSupported) {
String host = data.getHost();
if (host == null) {
- if (wildcardSupported && mWild) {
+ if (wildcardSupported && mWild && mHost.isEmpty()) {
// special case, if no host is provided, but the Authority is wildcard, match
return MATCH_CATEGORY_HOST;
} else {
diff --git a/core/java/android/content/PeriodicSync.java b/core/java/android/content/PeriodicSync.java
index 6830f5f34e75..432e81bad019 100644
--- a/core/java/android/content/PeriodicSync.java
+++ b/core/java/android/content/PeriodicSync.java
@@ -84,7 +84,7 @@ public class PeriodicSync implements Parcelable {
}
private PeriodicSync(Parcel in) {
- this.account = in.readParcelable(null, android.accounts.Account.class);
+ this.account = in.readParcelable(null);
this.authority = in.readString();
this.extras = in.readBundle();
this.period = in.readLong();
diff --git a/core/java/android/content/RestrictionEntry.java b/core/java/android/content/RestrictionEntry.java
index 63fcb49fff1b..8fd41f2c9e05 100644
--- a/core/java/android/content/RestrictionEntry.java
+++ b/core/java/android/content/RestrictionEntry.java
@@ -505,7 +505,7 @@ public class RestrictionEntry implements Parcelable {
mChoiceValues = in.readStringArray();
mCurrentValue = in.readString();
mCurrentValues = in.readStringArray();
- Parcelable[] parcelables = in.readParcelableArray(null);
+ Parcelable[] parcelables = in.readParcelableArray(null, RestrictionEntry.class);
if (parcelables != null) {
mRestrictions = new RestrictionEntry[parcelables.length];
for (int i = 0; i < parcelables.length; i++) {
diff --git a/core/java/android/content/SyncInfo.java b/core/java/android/content/SyncInfo.java
index 57101be6507e..017a92b1e8bb 100644
--- a/core/java/android/content/SyncInfo.java
+++ b/core/java/android/content/SyncInfo.java
@@ -99,7 +99,7 @@ public class SyncInfo implements Parcelable {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
SyncInfo(Parcel parcel) {
authorityId = parcel.readInt();
- account = parcel.readParcelable(Account.class.getClassLoader(), android.accounts.Account.class);
+ account = parcel.readParcelable(Account.class.getClassLoader());
authority = parcel.readString();
startTime = parcel.readLong();
}
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 83ce84e7a5cb..e1e6f75d152f 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -174,7 +174,7 @@ public class SyncRequest implements Parcelable {
mIsAuthority = (in.readInt() != 0);
mIsExpedited = (in.readInt() != 0);
mIsScheduledAsExpeditedJob = (in.readInt() != 0);
- mAccountToSync = in.readParcelable(null, android.accounts.Account.class);
+ mAccountToSync = in.readParcelable(null);
mAuthority = in.readString();
}
diff --git a/core/java/android/content/UndoManager.java b/core/java/android/content/UndoManager.java
index b2979f36e01b..87afbf874b37 100644
--- a/core/java/android/content/UndoManager.java
+++ b/core/java/android/content/UndoManager.java
@@ -777,7 +777,7 @@ public class UndoManager {
final int N = p.readInt();
for (int i=0; i<N; i++) {
UndoOwner owner = mManager.restoreOwner(p);
- UndoOperation op = (UndoOperation)p.readParcelable(loader, android.content.UndoOperation.class);
+ UndoOperation op = (UndoOperation)p.readParcelable(loader);
op.mOwner = owner;
mOperations.add(op);
}
diff --git a/core/java/android/content/UriPermission.java b/core/java/android/content/UriPermission.java
index 73477612985c..d3a9cb812539 100644
--- a/core/java/android/content/UriPermission.java
+++ b/core/java/android/content/UriPermission.java
@@ -47,7 +47,7 @@ public final class UriPermission implements Parcelable {
/** {@hide} */
public UriPermission(Parcel in) {
- mUri = in.readParcelable(null, android.net.Uri.class);
+ mUri = in.readParcelable(null);
mModeFlags = in.readInt();
mPersistedTime = in.readLong();
}
diff --git a/core/java/android/content/om/OverlayManagerTransaction.java b/core/java/android/content/om/OverlayManagerTransaction.java
index 868dab298108..73be0ffbf467 100644
--- a/core/java/android/content/om/OverlayManagerTransaction.java
+++ b/core/java/android/content/om/OverlayManagerTransaction.java
@@ -67,7 +67,7 @@ public class OverlayManagerTransaction
mRequests = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
final int request = source.readInt();
- final OverlayIdentifier overlay = source.readParcelable(null, android.content.om.OverlayIdentifier.class);
+ final OverlayIdentifier overlay = source.readParcelable(null);
final int userId = source.readInt();
final Bundle extras = source.readBundle(null);
mRequests.add(new Request(request, overlay, userId, extras));
diff --git a/core/java/android/content/pm/BaseParceledListSlice.java b/core/java/android/content/pm/BaseParceledListSlice.java
index 7bade740c9be..1e0deffbf8cd 100644
--- a/core/java/android/content/pm/BaseParceledListSlice.java
+++ b/core/java/android/content/pm/BaseParceledListSlice.java
@@ -50,10 +50,12 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
*/
private static final int MAX_IPC_SIZE = IBinder.getSuggestedMaxIpcSizeBytes();
- private final List<T> mList;
+ private List<T> mList;
private int mInlineCountLimit = Integer.MAX_VALUE;
+ private boolean mHasBeenParceled = false;
+
public BaseParceledListSlice(List<T> list) {
mList = list;
}
@@ -151,9 +153,17 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
* Write this to another Parcel. Note that this discards the internal Parcel
* and should not be used anymore. This is so we can pass this to a Binder
* where we won't have a chance to call recycle on this.
+ *
+ * This method can only be called once per BaseParceledListSlice to ensure that
+ * the referenced list can be cleaned up before the recipient cleans up the
+ * Binder reference.
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
+ if (mHasBeenParceled) {
+ throw new IllegalStateException("Can't Parcel a ParceledListSlice more than once");
+ }
+ mHasBeenParceled = true;
final int N = mList.size();
final int callFlags = flags;
dest.writeInt(N);
@@ -180,9 +190,17 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
throws RemoteException {
if (code != FIRST_CALL_TRANSACTION) {
return super.onTransact(code, data, reply, flags);
+ } else if (mList == null) {
+ throw new IllegalArgumentException("Attempt to transfer null list, "
+ + "did transfer finish?");
}
int i = data.readInt();
- if (DEBUG) Log.d(TAG, "Writing more @" + i + " of " + N);
+
+ if (DEBUG) {
+ Log.d(TAG, "Writing more @" + i + " of " + N + " to "
+ + Binder.getCallingPid() + ", sender=" + this);
+ }
+
while (i < N && reply.dataSize() < MAX_IPC_SIZE) {
reply.writeInt(1);
@@ -196,6 +214,9 @@ abstract class BaseParceledListSlice<T> implements Parcelable {
if (i < N) {
if (DEBUG) Log.d(TAG, "Breaking @" + i + " of " + N);
reply.writeInt(0);
+ } else {
+ if (DEBUG) Log.d(TAG, "Transfer complete, clearing mList reference");
+ mList = null;
}
return true;
}
diff --git a/core/java/android/content/pm/InstallSourceInfo.java b/core/java/android/content/pm/InstallSourceInfo.java
index 84d2ca389611..a45bf7930509 100644
--- a/core/java/android/content/pm/InstallSourceInfo.java
+++ b/core/java/android/content/pm/InstallSourceInfo.java
@@ -61,7 +61,7 @@ public final class InstallSourceInfo implements Parcelable {
private InstallSourceInfo(Parcel source) {
mInitiatingPackageName = source.readString();
- mInitiatingPackageSigningInfo = source.readParcelable(SigningInfo.class.getClassLoader(), android.content.pm.SigningInfo.class);
+ mInitiatingPackageSigningInfo = source.readParcelable(SigningInfo.class.getClassLoader());
mOriginatingPackageName = source.readString();
mInstallingPackageName = source.readString();
}
diff --git a/core/java/android/content/pm/InstantAppInfo.java b/core/java/android/content/pm/InstantAppInfo.java
index d6cfb0e70693..24d6a07ec4e8 100644
--- a/core/java/android/content/pm/InstantAppInfo.java
+++ b/core/java/android/content/pm/InstantAppInfo.java
@@ -65,7 +65,7 @@ public final class InstantAppInfo implements Parcelable {
mLabelText = parcel.readCharSequence();
mRequestedPermissions = parcel.readStringArray();
mGrantedPermissions = parcel.createStringArray();
- mApplicationInfo = parcel.readParcelable(null, android.content.pm.ApplicationInfo.class);
+ mApplicationInfo = parcel.readParcelable(null);
}
/**
diff --git a/core/java/android/content/pm/InstantAppIntentFilter.java b/core/java/android/content/pm/InstantAppIntentFilter.java
index 721b2616fbfd..123d2ba5aa8d 100644
--- a/core/java/android/content/pm/InstantAppIntentFilter.java
+++ b/core/java/android/content/pm/InstantAppIntentFilter.java
@@ -46,7 +46,7 @@ public final class InstantAppIntentFilter implements Parcelable {
InstantAppIntentFilter(Parcel in) {
mSplitName = in.readString();
- in.readList(mFilters, getClass().getClassLoader(), android.content.IntentFilter.class);
+ in.readList(mFilters, getClass().getClassLoader());
}
public String getSplitName() {
diff --git a/core/java/android/content/pm/InstantAppResolveInfo.java b/core/java/android/content/pm/InstantAppResolveInfo.java
index 6124638ccbcb..98815647f0c3 100644
--- a/core/java/android/content/pm/InstantAppResolveInfo.java
+++ b/core/java/android/content/pm/InstantAppResolveInfo.java
@@ -140,7 +140,7 @@ public final class InstantAppResolveInfo implements Parcelable {
mFilters = Collections.emptyList();
mVersionCode = -1;
} else {
- mDigest = in.readParcelable(null /*loader*/, android.content.pm.InstantAppResolveInfo.InstantAppDigest.class);
+ mDigest = in.readParcelable(null /*loader*/);
mPackageName = in.readString();
mFilters = new ArrayList<>();
in.readTypedList(mFilters, InstantAppIntentFilter.CREATOR);
diff --git a/core/java/android/content/pm/LauncherActivityInfoInternal.java b/core/java/android/content/pm/LauncherActivityInfoInternal.java
index 46c415df7525..417f168940b6 100644
--- a/core/java/android/content/pm/LauncherActivityInfoInternal.java
+++ b/core/java/android/content/pm/LauncherActivityInfoInternal.java
@@ -43,10 +43,10 @@ public class LauncherActivityInfoInternal implements Parcelable {
}
public LauncherActivityInfoInternal(Parcel source) {
- mActivityInfo = source.readParcelable(ActivityInfo.class.getClassLoader(), android.content.pm.ActivityInfo.class);
+ mActivityInfo = source.readParcelable(ActivityInfo.class.getClassLoader());
mComponentName = new ComponentName(mActivityInfo.packageName, mActivityInfo.name);
mIncrementalStatesInfo = source.readParcelable(
- IncrementalStatesInfo.class.getClassLoader(), android.content.pm.IncrementalStatesInfo.class);
+ IncrementalStatesInfo.class.getClassLoader());
}
public ComponentName getComponentName() {
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 495100b0ae52..d76dc782c367 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1754,11 +1754,11 @@ public class PackageInstaller {
installScenario = source.readInt();
sizeBytes = source.readLong();
appPackageName = source.readString();
- appIcon = source.readParcelable(null, android.graphics.Bitmap.class);
+ appIcon = source.readParcelable(null);
appLabel = source.readString();
- originatingUri = source.readParcelable(null, android.net.Uri.class);
+ originatingUri = source.readParcelable(null);
originatingUid = source.readInt();
- referrerUri = source.readParcelable(null, android.net.Uri.class);
+ referrerUri = source.readParcelable(null);
abiOverride = source.readString();
volumeUuid = source.readString();
grantedRuntimePermissions = source.readStringArray();
@@ -1770,7 +1770,7 @@ public class PackageInstaller {
forceQueryableOverride = source.readBoolean();
requiredInstalledVersionCode = source.readLong();
DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable(
- DataLoaderParamsParcel.class.getClassLoader(), android.content.pm.DataLoaderParamsParcel.class);
+ DataLoaderParamsParcel.class.getClassLoader());
if (dataLoaderParamsParcel != null) {
dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel);
}
@@ -2367,43 +2367,73 @@ public class PackageInstaller {
private static final int[] NO_SESSIONS = {};
/** @hide */
- @IntDef(prefix = { "STAGED_SESSION_" }, value = {
- STAGED_SESSION_NO_ERROR,
- STAGED_SESSION_VERIFICATION_FAILED,
- STAGED_SESSION_ACTIVATION_FAILED,
- STAGED_SESSION_UNKNOWN,
- STAGED_SESSION_CONFLICT})
+ @IntDef(prefix = { "SESSION_" }, value = {
+ SESSION_NO_ERROR,
+ SESSION_VERIFICATION_FAILED,
+ SESSION_ACTIVATION_FAILED,
+ SESSION_UNKNOWN_ERROR,
+ SESSION_CONFLICT})
@Retention(RetentionPolicy.SOURCE)
public @interface SessionErrorCode {}
/**
- * Constant indicating that no error occurred during the preparation or the activation of
- * this staged session.
+ * @deprecated use {@link #SESSION_NO_ERROR}.
*/
+ @Deprecated
public static final int STAGED_SESSION_NO_ERROR = 0;
/**
- * Constant indicating that an error occurred during the verification phase (pre-reboot) of
- * this staged session.
+ * @deprecated use {@link #SESSION_VERIFICATION_FAILED}.
*/
+ @Deprecated
public static final int STAGED_SESSION_VERIFICATION_FAILED = 1;
/**
- * Constant indicating that an error occurred during the activation phase (post-reboot) of
- * this staged session.
+ * @deprecated use {@link #SESSION_ACTIVATION_FAILED}.
*/
+ @Deprecated
public static final int STAGED_SESSION_ACTIVATION_FAILED = 2;
/**
- * Constant indicating that an unknown error occurred while processing this staged session.
+ * @deprecated use {@link #SESSION_UNKNOWN_ERROR}.
*/
+ @Deprecated
public static final int STAGED_SESSION_UNKNOWN = 3;
/**
- * Constant indicating that the session was in conflict with another staged session and had
- * to be sacrificed for resolution.
+ * @deprecated use {@link #SESSION_CONFLICT}.
*/
+ @Deprecated
public static final int STAGED_SESSION_CONFLICT = 4;
+ /**
+ * Constant indicating that no error occurred during the preparation or the activation of
+ * this session.
+ */
+ public static final int SESSION_NO_ERROR = 0;
+
+ /**
+ * Constant indicating that an error occurred during the verification phase of
+ * this session.
+ */
+ public static final int SESSION_VERIFICATION_FAILED = 1;
+
+ /**
+ * Constant indicating that an error occurred during the activation phase of
+ * this session.
+ */
+ public static final int SESSION_ACTIVATION_FAILED = 2;
+
+ /**
+ * Constant indicating that an unknown error occurred while processing this session.
+ */
+ public static final int SESSION_UNKNOWN_ERROR = 3;
+
+ /**
+ * Constant indicating that the session was in conflict with another session and had
+ * to be sacrificed for resolution.
+ */
+ public static final int SESSION_CONFLICT = 4;
+
private static String userActionToString(int requireUserAction) {
switch(requireUserAction) {
case SessionParams.USER_ACTION_REQUIRED:
@@ -2533,13 +2563,13 @@ public class PackageInstaller {
installScenario = source.readInt();
sizeBytes = source.readLong();
appPackageName = source.readString();
- appIcon = source.readParcelable(null, android.graphics.Bitmap.class);
+ appIcon = source.readParcelable(null);
appLabel = source.readString();
installLocation = source.readInt();
- originatingUri = source.readParcelable(null, android.net.Uri.class);
+ originatingUri = source.readParcelable(null);
originatingUid = source.readInt();
- referrerUri = source.readParcelable(null, android.net.Uri.class);
+ referrerUri = source.readParcelable(null);
grantedRuntimePermissions = source.readStringArray();
whitelistedRestrictedPermissions = source.createStringArrayList();
autoRevokePermissionsMode = source.readInt();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 819cbb0f347d..a6d846b43396 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4064,6 +4064,15 @@ public abstract class PackageManager {
@TestApi
public static final String FEATURE_COMMUNAL_MODE = "android.software.communal_mode";
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
+ * supports dream overlay feature, which is an informational layer shown on top of dreams.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_DREAM_OVERLAY = "android.software.dream_overlay";
+
/** @hide */
public static final boolean APP_ENUMERATION_ENABLED_BY_DEFAULT = true;
@@ -4221,6 +4230,17 @@ public abstract class PackageManager {
"android.content.pm.action.REQUEST_PERMISSIONS";
/**
+ * The action used to request that the user approve a permission request
+ * from the application. Sent from an application other than the one whose permissions
+ * will be granted. Can only be used by the system server.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_REQUEST_PERMISSIONS_FOR_OTHER =
+ "android.content.pm.action.REQUEST_PERMISSIONS_FOR_OTHER";
+
+ /**
* The names of the requested permissions.
* <p>
* <strong>Type:</strong> String[]
@@ -4328,8 +4348,9 @@ public abstract class PackageManager {
public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 1 << 5;
/**
- * Permission flag: The permission has to be reviewed before any of
- * the app components can run.
+ * Permission flag: If app targetSDK < M, then the permission has to be reviewed before any of
+ * the app components can run. If app targetSDK >= M, then the system might need to show a
+ * request dialog for this permission on behalf of an app.
*
* @hide
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index f31f78fb81f3..e2c91a4b1bea 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -7297,7 +7297,7 @@ public class PackageParser {
splitFlags = dest.createIntArray();
splitPrivateFlags = dest.createIntArray();
baseHardwareAccelerated = (dest.readInt() == 1);
- applicationInfo = dest.readParcelable(boot, android.content.pm.ApplicationInfo.class);
+ applicationInfo = dest.readParcelable(boot);
if (applicationInfo.permission != null) {
applicationInfo.permission = applicationInfo.permission.intern();
}
@@ -7305,19 +7305,19 @@ public class PackageParser {
// We don't serialize the "owner" package and the application info object for each of
// these components, in order to save space and to avoid circular dependencies while
// serialization. We need to fix them all up here.
- dest.readParcelableList(permissions, boot, android.content.pm.PackageParser.Permission.class);
+ dest.readParcelableList(permissions, boot);
fixupOwner(permissions);
- dest.readParcelableList(permissionGroups, boot, android.content.pm.PackageParser.PermissionGroup.class);
+ dest.readParcelableList(permissionGroups, boot);
fixupOwner(permissionGroups);
- dest.readParcelableList(activities, boot, android.content.pm.PackageParser.Activity.class);
+ dest.readParcelableList(activities, boot);
fixupOwner(activities);
- dest.readParcelableList(receivers, boot, android.content.pm.PackageParser.Activity.class);
+ dest.readParcelableList(receivers, boot);
fixupOwner(receivers);
- dest.readParcelableList(providers, boot, android.content.pm.PackageParser.Provider.class);
+ dest.readParcelableList(providers, boot);
fixupOwner(providers);
- dest.readParcelableList(services, boot, android.content.pm.PackageParser.Service.class);
+ dest.readParcelableList(services, boot);
fixupOwner(services);
- dest.readParcelableList(instrumentation, boot, android.content.pm.PackageParser.Instrumentation.class);
+ dest.readParcelableList(instrumentation, boot);
fixupOwner(instrumentation);
dest.readStringList(requestedPermissions);
@@ -7327,10 +7327,10 @@ public class PackageParser {
protectedBroadcasts = dest.createStringArrayList();
internStringArrayList(protectedBroadcasts);
- parentPackage = dest.readParcelable(boot, android.content.pm.PackageParser.Package.class);
+ parentPackage = dest.readParcelable(boot);
childPackages = new ArrayList<>();
- dest.readParcelableList(childPackages, boot, android.content.pm.PackageParser.Package.class);
+ dest.readParcelableList(childPackages, boot);
if (childPackages.size() == 0) {
childPackages = null;
}
@@ -7364,7 +7364,7 @@ public class PackageParser {
}
preferredActivityFilters = new ArrayList<>();
- dest.readParcelableList(preferredActivityFilters, boot, android.content.pm.PackageParser.ActivityIntentInfo.class);
+ dest.readParcelableList(preferredActivityFilters, boot);
if (preferredActivityFilters.size() == 0) {
preferredActivityFilters = null;
}
@@ -7385,7 +7385,7 @@ public class PackageParser {
}
mSharedUserLabel = dest.readInt();
- mSigningDetails = dest.readParcelable(boot, android.content.pm.PackageParser.SigningDetails.class);
+ mSigningDetails = dest.readParcelable(boot);
mPreferredOrder = dest.readInt();
@@ -7397,19 +7397,19 @@ public class PackageParser {
configPreferences = new ArrayList<>();
- dest.readParcelableList(configPreferences, boot, android.content.pm.ConfigurationInfo.class);
+ dest.readParcelableList(configPreferences, boot);
if (configPreferences.size() == 0) {
configPreferences = null;
}
reqFeatures = new ArrayList<>();
- dest.readParcelableList(reqFeatures, boot, android.content.pm.FeatureInfo.class);
+ dest.readParcelableList(reqFeatures, boot);
if (reqFeatures.size() == 0) {
reqFeatures = null;
}
featureGroups = new ArrayList<>();
- dest.readParcelableList(featureGroups, boot, android.content.pm.FeatureGroupInfo.class);
+ dest.readParcelableList(featureGroups, boot);
if (featureGroups.size() == 0) {
featureGroups = null;
}
@@ -7806,13 +7806,13 @@ public class PackageParser {
private Permission(Parcel in) {
super(in);
final ClassLoader boot = Object.class.getClassLoader();
- info = in.readParcelable(boot, android.content.pm.PermissionInfo.class);
+ info = in.readParcelable(boot);
if (info.group != null) {
info.group = info.group.intern();
}
tree = (in.readInt() == 1);
- group = in.readParcelable(boot, android.content.pm.PackageParser.PermissionGroup.class);
+ group = in.readParcelable(boot);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator<Permission>() {
@@ -7867,7 +7867,7 @@ public class PackageParser {
private PermissionGroup(Parcel in) {
super(in);
- info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.PermissionGroupInfo.class);
+ info = in.readParcelable(Object.class.getClassLoader());
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator<PermissionGroup>() {
@@ -8160,7 +8160,7 @@ public class PackageParser {
private Activity(Parcel in) {
super(in);
- info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.ActivityInfo.class);
+ info = in.readParcelable(Object.class.getClassLoader());
mHasMaxAspectRatio = in.readBoolean();
mHasMinAspectRatio = in.readBoolean();
@@ -8254,7 +8254,7 @@ public class PackageParser {
private Service(Parcel in) {
super(in);
- info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.ServiceInfo.class);
+ info = in.readParcelable(Object.class.getClassLoader());
for (ServiceIntentInfo aii : intents) {
aii.service = this;
@@ -8344,7 +8344,7 @@ public class PackageParser {
private Provider(Parcel in) {
super(in);
- info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.ProviderInfo.class);
+ info = in.readParcelable(Object.class.getClassLoader());
syncable = (in.readInt() == 1);
for (ProviderIntentInfo aii : intents) {
@@ -8436,7 +8436,7 @@ public class PackageParser {
private Instrumentation(Parcel in) {
super(in);
- info = in.readParcelable(Object.class.getClassLoader(), android.content.pm.InstrumentationInfo.class);
+ info = in.readParcelable(Object.class.getClassLoader());
if (info.targetPackage != null) {
info.targetPackage = info.targetPackage.intern();
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index 7696cbe0b631..78984bda24a7 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -174,7 +174,7 @@ public abstract class RegisteredServicesCache<V> {
// Register for user-related events
IntentFilter userFilter = new IntentFilter();
- sdFilter.addAction(Intent.ACTION_USER_REMOVED);
+ userFilter.addAction(Intent.ACTION_USER_REMOVED);
mContext.registerReceiver(mUserRemovedReceiver, userFilter, null, handler);
}
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 3443c757e6bc..f153566bf61a 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -34,9 +34,10 @@ import java.util.Objects;
/**
* This class provides information for a shared library. There are
- * three types of shared libraries: builtin - non-updatable part of
+ * four types of shared libraries: builtin - non-updatable part of
* the OS; dynamic - updatable backwards-compatible dynamically linked;
- * static - non backwards-compatible emulating static linking.
+ * static - non backwards-compatible emulating static linking;
+ * SDK - updatable backwards-incompatible dynamically loaded.
*/
public final class SharedLibraryInfo implements Parcelable {
@@ -45,6 +46,7 @@ public final class SharedLibraryInfo implements Parcelable {
TYPE_BUILTIN,
TYPE_DYNAMIC,
TYPE_STATIC,
+ TYPE_SDK,
})
@Retention(RetentionPolicy.SOURCE)
@interface Type{}
@@ -134,8 +136,8 @@ public final class SharedLibraryInfo implements Parcelable {
mName = parcel.readString8();
mVersion = parcel.readLong();
mType = parcel.readInt();
- mDeclaringPackage = parcel.readParcelable(null, android.content.pm.VersionedPackage.class);
- mDependentPackages = parcel.readArrayList(null, android.content.pm.VersionedPackage.class);
+ mDeclaringPackage = parcel.readParcelable(null);
+ mDependentPackages = parcel.readArrayList(null);
mDependencies = parcel.createTypedArrayList(SharedLibraryInfo.CREATOR);
mIsNative = parcel.readBoolean();
}
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 7d4f7ecef29c..613fb84812f8 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -2182,7 +2182,7 @@ public final class ShortcutInfo implements Parcelable {
mUserId = source.readInt();
mId = source.readString8();
mPackageName = source.readString8();
- mActivity = source.readParcelable(cl, android.content.ComponentName.class);
+ mActivity = source.readParcelable(cl);
mFlags = source.readInt();
mIconResId = source.readInt();
mLastChangedTimestamp = source.readLong();
@@ -2192,7 +2192,7 @@ public final class ShortcutInfo implements Parcelable {
return; // key information only.
}
- mIcon = source.readParcelable(cl, android.graphics.drawable.Icon.class);
+ mIcon = source.readParcelable(cl);
mTitle = source.readCharSequence();
mTitleResId = source.readInt();
mText = source.readCharSequence();
@@ -2202,7 +2202,7 @@ public final class ShortcutInfo implements Parcelable {
mIntents = source.readParcelableArray(cl, Intent.class);
mIntentPersistableExtrases = source.readParcelableArray(cl, PersistableBundle.class);
mRank = source.readInt();
- mExtras = source.readParcelable(cl, android.os.PersistableBundle.class);
+ mExtras = source.readParcelable(cl);
mBitmapPath = source.readString8();
mIconResName = source.readString8();
@@ -2221,7 +2221,7 @@ public final class ShortcutInfo implements Parcelable {
}
mPersons = source.readParcelableArray(cl, Person.class);
- mLocusId = source.readParcelable(cl, android.content.LocusId.class);
+ mLocusId = source.readParcelable(cl);
mIconUri = source.readString8();
mStartingThemeResName = source.readString8();
mExcludedSurfaces = source.readInt();
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 7dbfd08310be..be0d934f5133 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -704,8 +704,8 @@ public class ShortcutManager {
}
private ShareShortcutInfo(@NonNull Parcel in) {
- mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader(), android.content.pm.ShortcutInfo.class);
- mTargetComponent = in.readParcelable(ComponentName.class.getClassLoader(), android.content.ComponentName.class);
+ mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
+ mTargetComponent = in.readParcelable(ComponentName.class.getClassLoader());
}
@NonNull
diff --git a/core/java/android/content/pm/ShortcutQueryWrapper.java b/core/java/android/content/pm/ShortcutQueryWrapper.java
index 64337d86f7ec..c6134416adbc 100644
--- a/core/java/android/content/pm/ShortcutQueryWrapper.java
+++ b/core/java/android/content/pm/ShortcutQueryWrapper.java
@@ -143,7 +143,7 @@ public final class ShortcutQueryWrapper extends LauncherApps.ShortcutQuery imple
List<LocusId> locusIds = null;
if ((flg & 0x8) != 0) {
locusIds = new ArrayList<>();
- in.readParcelableList(locusIds, LocusId.class.getClassLoader(), android.content.LocusId.class);
+ in.readParcelableList(locusIds, LocusId.class.getClassLoader());
}
ComponentName activity = (flg & 0x10) == 0 ? null
: (ComponentName) in.readTypedObject(ComponentName.CREATOR);
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index 77b8be351bd1..d04c97c1e915 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -37,6 +37,9 @@
"name": "CarrierAppIntegrationTestCases"
},
{
+ "name": "ApkVerityTest"
+ },
+ {
"name": "CtsIncrementalInstallHostTestCases",
"options": [
{
@@ -135,6 +138,9 @@
"include-filter": "android.appsecurity.cts.AppSecurityTests#testPermissionDiffCert"
}
]
+ },
+ {
+ "name": "CtsInstallHostTestCases"
}
]
}
diff --git a/core/java/android/content/pm/VerifierInfo.java b/core/java/android/content/pm/VerifierInfo.java
index 868bb9cb995c..3e69ff555946 100644
--- a/core/java/android/content/pm/VerifierInfo.java
+++ b/core/java/android/content/pm/VerifierInfo.java
@@ -59,7 +59,7 @@ public class VerifierInfo implements Parcelable {
private VerifierInfo(Parcel source) {
packageName = source.readString();
- publicKey = (PublicKey) source.readSerializable(java.security.PublicKey.class.getClassLoader(), java.security.PublicKey.class);
+ publicKey = (PublicKey) source.readSerializable();
}
@Override
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index 23cae4c04467..ddab207437c2 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -1408,7 +1408,7 @@ public class ParsingPackageImpl implements ParsingPackage, ParsingPackageHidden,
this.processes = in.readHashMap(boot);
this.metaData = in.readBundle(boot);
this.volumeUuid = sForInternedString.unparcel(in);
- this.signingDetails = in.readParcelable(boot, android.content.pm.SigningDetails.class);
+ this.signingDetails = in.readParcelable(boot);
this.mPath = in.readString();
this.queriesIntents = in.createTypedArrayList(Intent.CREATOR);
this.queriesPackages = sForInternedStringList.unparcel(in);
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index f336672ffefa..e02eb7cca090 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -3519,7 +3519,7 @@ public class ParsingPackageUtils {
ArraySet<PublicKey> keys = new ArraySet<>(M);
for (int j = 0; j < M; ++j) {
- PublicKey pk = (PublicKey) in.readSerializable(java.security.PublicKey.class.getClassLoader(), java.security.PublicKey.class);
+ PublicKey pk = (PublicKey) in.readSerializable();
keys.add(pk);
}
diff --git a/core/java/android/content/pm/parsing/ParsingUtils.java b/core/java/android/content/pm/parsing/ParsingUtils.java
index 6dfb268c3d64..cce984eb93a7 100644
--- a/core/java/android/content/pm/parsing/ParsingUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingUtils.java
@@ -138,7 +138,7 @@ public class ParsingUtils {
final List<Pair<String, ParsedIntentInfo>> list = new ArrayList<>(size);
for (int i = 0; i < size; ++i) {
list.add(Pair.create(source.readString(), source.readParcelable(
- ParsedIntentInfoImpl.class.getClassLoader(), android.content.pm.parsing.component.ParsedIntentInfo.class)));
+ ParsedIntentInfoImpl.class.getClassLoader())));
}
return list;
diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionImpl.java b/core/java/android/content/pm/parsing/component/ParsedPermissionImpl.java
index 45038cf225fb..2145e441553a 100644
--- a/core/java/android/content/pm/parsing/component/ParsedPermissionImpl.java
+++ b/core/java/android/content/pm/parsing/component/ParsedPermissionImpl.java
@@ -116,7 +116,7 @@ public class ParsedPermissionImpl extends ParsedComponentImpl implements ParsedP
this.requestRes = in.readInt();
this.protectionLevel = in.readInt();
this.tree = in.readBoolean();
- this.parsedPermissionGroup = in.readParcelable(boot, android.content.pm.parsing.component.ParsedPermissionGroup.class);
+ this.parsedPermissionGroup = in.readParcelable(boot);
this.knownCerts = sForStringSet.unparcel(in);
}
diff --git a/core/java/android/content/res/TEST_MAPPING b/core/java/android/content/res/TEST_MAPPING
index 535afd361f01..3703f2e2152b 100644
--- a/core/java/android/content/res/TEST_MAPPING
+++ b/core/java/android/content/res/TEST_MAPPING
@@ -1,4 +1,12 @@
{
+ "imports": [
+ {
+ "path": "frameworks/base/core/tests/coretests/src/android/content/res"
+ },
+ {
+ "path": "frameworks/base/core/tests/coretests/src/com/android/internal/content/res"
+ }
+ ],
"presubmit": [
{
"name": "CtsResourcesLoaderTests"
diff --git a/core/java/android/debug/AdbManager.java b/core/java/android/debug/AdbManager.java
index 7714dd80f910..243f80187185 100644
--- a/core/java/android/debug/AdbManager.java
+++ b/core/java/android/debug/AdbManager.java
@@ -38,6 +38,7 @@ public class AdbManager {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
public static final String WIRELESS_DEBUG_STATE_CHANGED_ACTION =
"com.android.server.adb.WIRELESS_DEBUG_STATUS";
@@ -46,6 +47,7 @@ public class AdbManager {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
public static final String WIRELESS_DEBUG_PAIRED_DEVICES_ACTION =
"com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES";
@@ -59,6 +61,7 @@ public class AdbManager {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MANAGE_DEBUGGING)
public static final String WIRELESS_DEBUG_PAIRING_RESULT_ACTION =
"com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT";
diff --git a/core/java/android/graphics/fonts/FontUpdateRequest.java b/core/java/android/graphics/fonts/FontUpdateRequest.java
index dae09f0977a4..cda1638a24dc 100644
--- a/core/java/android/graphics/fonts/FontUpdateRequest.java
+++ b/core/java/android/graphics/fonts/FontUpdateRequest.java
@@ -235,7 +235,7 @@ public final class FontUpdateRequest implements Parcelable {
public Family createFromParcel(Parcel source) {
String familyName = source.readString8();
List<Font> fonts = source.readParcelableList(
- new ArrayList<>(), Font.class.getClassLoader(), android.graphics.fonts.FontUpdateRequest.Font.class);
+ new ArrayList<>(), Font.class.getClassLoader());
return new Family(familyName, fonts);
}
@@ -379,9 +379,9 @@ public final class FontUpdateRequest implements Parcelable {
protected FontUpdateRequest(Parcel in) {
mType = in.readInt();
- mFd = in.readParcelable(ParcelFileDescriptor.class.getClassLoader(), android.os.ParcelFileDescriptor.class);
+ mFd = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
mSignature = in.readBlob();
- mFontFamily = in.readParcelable(FontConfig.FontFamily.class.getClassLoader(), android.graphics.fonts.FontUpdateRequest.Family.class);
+ mFontFamily = in.readParcelable(FontConfig.FontFamily.class.getClassLoader());
}
public @Type int getType() {
diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java
index 0c03948e5368..e6b762a64384 100644
--- a/core/java/android/hardware/biometrics/PromptInfo.java
+++ b/core/java/android/hardware/biometrics/PromptInfo.java
@@ -65,7 +65,7 @@ public class PromptInfo implements Parcelable {
mAuthenticators = in.readInt();
mDisallowBiometricsIfPolicyExists = in.readBoolean();
mReceiveSystemEvents = in.readBoolean();
- mAllowedSensorIds = in.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class);
+ mAllowedSensorIds = in.readArrayList(Integer.class.getClassLoader());
mAllowBackgroundAuthentication = in.readBoolean();
mIgnoreEnrollmentState = in.readBoolean();
}
diff --git a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
index 1490ea1592a5..f365ee6066d0 100644
--- a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
+++ b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java
@@ -60,7 +60,7 @@ public class SensorPropertiesInternal implements Parcelable {
sensorStrength = in.readInt();
maxEnrollmentsPerUser = in.readInt();
componentInfo = new ArrayList<>();
- in.readList(componentInfo, ComponentInfoInternal.class.getClassLoader(), android.hardware.biometrics.ComponentInfoInternal.class);
+ in.readList(componentInfo, ComponentInfoInternal.class.getClassLoader());
resetLockoutRequiresHardwareAuthToken = in.readBoolean();
resetLockoutRequiresChallenge = in.readBoolean();
}
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 86ae3a311c9b..5df64e3cca9e 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -599,7 +599,8 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
synchronized (mSurfacesLock) {
mSurfaceSet.clear();
- Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader());
+ Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader(),
+ Surface.class);
if (parcelableArray != null) {
for (Parcelable p : parcelableArray) {
Surface s = (Surface) p;
diff --git a/core/java/android/hardware/face/FaceAuthenticationFrame.java b/core/java/android/hardware/face/FaceAuthenticationFrame.java
index a53aad74d4e0..f39d63411825 100644
--- a/core/java/android/hardware/face/FaceAuthenticationFrame.java
+++ b/core/java/android/hardware/face/FaceAuthenticationFrame.java
@@ -46,7 +46,7 @@ public final class FaceAuthenticationFrame implements Parcelable {
}
private FaceAuthenticationFrame(@NonNull Parcel source) {
- mData = source.readParcelable(FaceDataFrame.class.getClassLoader(), android.hardware.face.FaceDataFrame.class);
+ mData = source.readParcelable(FaceDataFrame.class.getClassLoader());
}
@Override
diff --git a/core/java/android/hardware/face/FaceEnrollFrame.java b/core/java/android/hardware/face/FaceEnrollFrame.java
index bbccee2e2c3d..822a57944449 100644
--- a/core/java/android/hardware/face/FaceEnrollFrame.java
+++ b/core/java/android/hardware/face/FaceEnrollFrame.java
@@ -73,9 +73,9 @@ public final class FaceEnrollFrame implements Parcelable {
}
private FaceEnrollFrame(@NonNull Parcel source) {
- mCell = source.readParcelable(FaceEnrollCell.class.getClassLoader(), android.hardware.face.FaceEnrollCell.class);
+ mCell = source.readParcelable(FaceEnrollCell.class.getClassLoader());
mStage = source.readInt();
- mData = source.readParcelable(FaceDataFrame.class.getClassLoader(), android.hardware.face.FaceDataFrame.class);
+ mData = source.readParcelable(FaceDataFrame.class.getClassLoader());
}
@Override
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index b97055976e3e..56f81423db4e 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -306,21 +306,22 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
throw new IllegalArgumentException("Must supply an enrollment callback");
}
- if (cancel != null && cancel.isCanceled()) {
- Slog.w(TAG, "enrollment already canceled");
- return;
+ if (cancel != null) {
+ if (cancel.isCanceled()) {
+ Slog.w(TAG, "enrollment already canceled");
+ return;
+ } else {
+ cancel.setOnCancelListener(new OnEnrollCancelListener());
+ }
}
if (mService != null) {
try {
mEnrollmentCallback = callback;
Trace.beginSection("FaceManager#enroll");
- final long enrollId = mService.enroll(userId, mToken, hardwareAuthToken,
- mServiceReceiver, mContext.getOpPackageName(), disabledFeatures,
- previewSurface, debugConsent);
- if (cancel != null) {
- cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId));
- }
+ mService.enroll(userId, mToken, hardwareAuthToken, mServiceReceiver,
+ mContext.getOpPackageName(), disabledFeatures, previewSurface,
+ debugConsent);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception in enroll: ", e);
// Though this may not be a hardware issue, it will cause apps to give up or
@@ -358,20 +359,21 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
throw new IllegalArgumentException("Must supply an enrollment callback");
}
- if (cancel != null && cancel.isCanceled()) {
- Slog.w(TAG, "enrollRemotely is already canceled.");
- return;
+ if (cancel != null) {
+ if (cancel.isCanceled()) {
+ Slog.w(TAG, "enrollRemotely is already canceled.");
+ return;
+ } else {
+ cancel.setOnCancelListener(new OnEnrollCancelListener());
+ }
}
if (mService != null) {
try {
mEnrollmentCallback = callback;
Trace.beginSection("FaceManager#enrollRemotely");
- final long enrolId = mService.enrollRemotely(userId, mToken, hardwareAuthToken,
- mServiceReceiver, mContext.getOpPackageName(), disabledFeatures);
- if (cancel != null) {
- cancel.setOnCancelListener(new OnEnrollCancelListener(enrolId));
- }
+ mService.enrollRemotely(userId, mToken, hardwareAuthToken, mServiceReceiver,
+ mContext.getOpPackageName(), disabledFeatures);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception in enrollRemotely: ", e);
// Though this may not be a hardware issue, it will cause apps to give up or
@@ -711,10 +713,10 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
}
}
- private void cancelEnrollment(long requestId) {
+ private void cancelEnrollment() {
if (mService != null) {
try {
- mService.cancelEnrollment(mToken, requestId);
+ mService.cancelEnrollment(mToken);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1098,16 +1100,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
}
private class OnEnrollCancelListener implements OnCancelListener {
- private final long mAuthRequestId;
-
- private OnEnrollCancelListener(long id) {
- mAuthRequestId = id;
- }
-
@Override
public void onCancel() {
- Slog.d(TAG, "Cancel face enrollment requested for: " + mAuthRequestId);
- cancelEnrollment(mAuthRequestId);
+ cancelEnrollment();
}
}
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 989b001ca8bf..e9198246dee3 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -76,16 +76,15 @@ interface IFaceService {
void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId);
// Start face enrollment
- long enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
- String opPackageName, in int [] disabledFeatures,
- in Surface previewSurface, boolean debugConsent);
+ void enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
+ String opPackageName, in int [] disabledFeatures, in Surface previewSurface, boolean debugConsent);
// Start remote face enrollment
- long enrollRemotely(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
+ void enrollRemotely(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,
String opPackageName, in int [] disabledFeatures);
// Cancel enrollment in progress
- void cancelEnrollment(IBinder token, long requestId);
+ void cancelEnrollment(IBinder token);
// Removes the specified face enrollment for the specified userId.
void remove(IBinder token, int faceId, int userId, IFaceServiceReceiver receiver,
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index acf9427b1241..fe04e5d35784 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -183,16 +183,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
}
private class OnEnrollCancelListener implements OnCancelListener {
- private final long mAuthRequestId;
-
- private OnEnrollCancelListener(long id) {
- mAuthRequestId = id;
- }
-
@Override
public void onCancel() {
- Slog.d(TAG, "Cancel fingerprint enrollment requested for: " + mAuthRequestId);
- cancelEnrollment(mAuthRequestId);
+ cancelEnrollment();
}
}
@@ -653,19 +646,20 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
throw new IllegalArgumentException("Must supply an enrollment callback");
}
- if (cancel != null && cancel.isCanceled()) {
- Slog.w(TAG, "enrollment already canceled");
- return;
+ if (cancel != null) {
+ if (cancel.isCanceled()) {
+ Slog.w(TAG, "enrollment already canceled");
+ return;
+ } else {
+ cancel.setOnCancelListener(new OnEnrollCancelListener());
+ }
}
if (mService != null) {
try {
mEnrollmentCallback = callback;
- final long enrollId = mService.enroll(mToken, hardwareAuthToken, userId,
- mServiceReceiver, mContext.getOpPackageName(), enrollReason);
- if (cancel != null) {
- cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId));
- }
+ mService.enroll(mToken, hardwareAuthToken, userId, mServiceReceiver,
+ mContext.getOpPackageName(), enrollReason);
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception in enroll: ", e);
// Though this may not be a hardware issue, it will cause apps to give up or try
@@ -1308,9 +1302,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
return allSensors.isEmpty() ? null : allSensors.get(0);
}
- private void cancelEnrollment(long requestId) {
+ private void cancelEnrollment() {
if (mService != null) try {
- mService.cancelEnrollment(mToken, requestId);
+ mService.cancelEnrollment(mToken);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index cbff8b11a72a..ba1dc6da62a6 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -84,11 +84,11 @@ interface IFingerprintService {
void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId);
// Start fingerprint enrollment
- long enroll(IBinder token, in byte [] hardwareAuthToken, int userId, IFingerprintServiceReceiver receiver,
+ void enroll(IBinder token, in byte [] hardwareAuthToken, int userId, IFingerprintServiceReceiver receiver,
String opPackageName, int enrollReason);
// Cancel enrollment in progress
- void cancelEnrollment(IBinder token, long requestId);
+ void cancelEnrollment(IBinder token);
// Any errors resulting from this call will be returned to the listener
void remove(IBinder token, int fingerId, int userId, IFingerprintServiceReceiver receiver,
diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
index 310ebe9ac093..78cca9601a2d 100644
--- a/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
+++ b/core/java/android/hardware/location/GeofenceHardwareMonitorEvent.java
@@ -81,7 +81,7 @@ public class GeofenceHardwareMonitorEvent implements Parcelable {
int monitoringType = source.readInt();
int monitoringStatus = source.readInt();
int sourceTechnologies = source.readInt();
- Location location = source.readParcelable(classLoader, android.location.Location.class);
+ Location location = source.readParcelable(classLoader);
return new GeofenceHardwareMonitorEvent(
monitoringType,
diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java
index 6ea2ac414704..4cc001a40146 100644
--- a/core/java/android/hardware/radio/RadioManager.java
+++ b/core/java/android/hardware/radio/RadioManager.java
@@ -436,7 +436,8 @@ public class RadioManager {
mNumAudioSources = in.readInt();
mIsInitializationRequired = in.readInt() == 1;
mIsCaptureSupported = in.readInt() == 1;
- Parcelable[] tmp = in.readParcelableArray(BandDescriptor.class.getClassLoader());
+ Parcelable[] tmp = in.readParcelableArray(BandDescriptor.class.getClassLoader(),
+ BandDescriptor.class);
mBands = new BandDescriptor[tmp.length];
for (int i = 0; i < tmp.length; i++) {
mBands[i] = (BandDescriptor) tmp[i];
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index afaa085c7cbd..afcb6fccb137 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -54,6 +54,7 @@ import static android.view.WindowInsets.Type.statusBars;
import static java.lang.annotation.RetentionPolicy.SOURCE;
+import android.annotation.AnyThread;
import android.annotation.CallSuper;
import android.annotation.DrawableRes;
import android.annotation.IntDef;
@@ -83,6 +84,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.os.Trace;
import android.provider.Settings;
import android.text.InputType;
@@ -302,6 +304,44 @@ public class InputMethodService extends AbstractInputMethodService {
static final boolean DEBUG = false;
/**
+ * Key for a boolean value that tells whether {@link InputMethodService} is responsible for
+ * rendering the back button and the IME switcher button or not when the gestural navigation is
+ * enabled.
+ *
+ * <p>This sysprop is just ignored when the gestural navigation mode is not enabled.</p>
+ *
+ * <p>
+ * To avoid complexity that is not necessary for production, you always need to reboot the
+ * device after modifying this flag as follows:
+ * <pre>
+ * $ adb root
+ * $ adb shell setprop persist.sys.ime.can_render_gestural_nav_buttons true
+ * $ adb reboot
+ * </pre>
+ * </p>
+ */
+ private static final String PROP_CAN_RENDER_GESTURAL_NAV_BUTTONS =
+ "persist.sys.ime.can_render_gestural_nav_buttons";
+
+ /**
+ * Returns whether {@link InputMethodService} is responsible for rendering the back button and
+ * the IME switcher button or not when the gestural navigation is enabled.
+ *
+ * <p>This method is supposed to be used with an assumption that the same value is returned in
+ * other processes. It is developers' responsibility for rebooting the device when the sysprop
+ * is modified.</p>
+ *
+ * @return {@code true} if {@link InputMethodService} is responsible for rendering the back
+ * button and the IME switcher button when the gestural navigation is enabled.
+ *
+ * @hide
+ */
+ @AnyThread
+ public static boolean canImeRenderGesturalNavButtons() {
+ return SystemProperties.getBoolean(PROP_CAN_RENDER_GESTURAL_NAV_BUTTONS, false);
+ }
+
+ /**
* Allows the system to optimize the back button affordance based on the presence of software
* keyboard.
*
@@ -523,6 +563,7 @@ public class InputMethodService extends AbstractInputMethodService {
private Handler mHandler;
private boolean mImeSurfaceScheduledForRemoval;
private ImsConfigurationTracker mConfigTracker = new ImsConfigurationTracker();
+ private boolean mDestroyed;
/**
* An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput}
@@ -599,6 +640,11 @@ public class InputMethodService extends AbstractInputMethodService {
@Override
public final void initializeInternal(@NonNull IBinder token,
IInputMethodPrivilegedOperations privilegedOperations, int configChanges) {
+ if (mDestroyed) {
+ Log.i(TAG, "The InputMethodService has already onDestroyed()."
+ + "Ignore the initialization.");
+ return;
+ }
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal");
mConfigTracker.onInitialize(configChanges);
mPrivOps.set(privilegedOperations);
@@ -1435,6 +1481,7 @@ public class InputMethodService extends AbstractInputMethodService {
}
@Override public void onDestroy() {
+ mDestroyed = true;
super.onDestroy();
mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
mInsetsComputer);
@@ -1811,15 +1858,19 @@ public class InputMethodService extends AbstractInputMethodService {
void updateExtractFrameVisibility() {
final int vis;
+ updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE);
+
if (isFullscreenMode()) {
vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE;
// "vis" should be applied for the extract frame as well in the fullscreen mode.
mExtractFrame.setVisibility(vis);
} else {
- vis = View.VISIBLE;
+ // mFullscreenArea visibility will according the candidate frame visibility once the
+ // extract frame is gone.
+ vis = mCandidatesVisibility;
mExtractFrame.setVisibility(View.GONE);
}
- updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE);
+
if (mDecorViewWasVisible && mFullscreenArea.getVisibility() != vis) {
int animRes = mThemeAttrs.getResourceId(vis == View.VISIBLE
? com.android.internal.R.styleable.InputMethodService_imeExtractEnterAnimation
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index fab692cba2f6..55541377a0bf 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -35,6 +35,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.content.pm.PackageManager;
import android.security.Credentials;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.VpnProfile;
@@ -70,6 +71,7 @@ import java.util.Objects;
* Exchange, Version 2 (IKEv2)</a>
*/
public final class Ikev2VpnProfile extends PlatformVpnProfile {
+ private static final String TAG = Ikev2VpnProfile.class.getSimpleName();
/** Prefix for when a Private Key is an alias to look for in KeyStore @hide */
public static final String PREFIX_KEYSTORE_ALIAS = "KEYSTORE_ALIAS:";
/** Prefix for when a Private Key is stored directly in the profile @hide */
@@ -163,6 +165,10 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
// UnmodifiableList doesn't make a defensive copy by default.
mAllowedAlgorithms = Collections.unmodifiableList(new ArrayList<>(allowedAlgorithms));
+ if (excludeLocalRoutes && !isBypassable) {
+ throw new IllegalArgumentException(
+ "Vpn should be byassable if excludeLocalRoutes is set");
+ }
mIsBypassable = isBypassable;
mIsMetered = isMetered;
@@ -520,7 +526,10 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
throw new IllegalArgumentException("Invalid auth method set");
}
- builder.setExcludeLocalRoutes(profile.excludeLocalRoutes);
+ if (profile.excludeLocalRoutes && !profile.isBypassable) {
+ Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN");
+ }
+ builder.setExcludeLocalRoutes(profile.excludeLocalRoutes && profile.isBypassable);
return builder.build();
}
@@ -907,9 +916,23 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
}
/**
- * Sets whether the local traffic is exempted from the VPN.
+ * Sets whether the local traffic is exempted from the VPN.
+ *
+ * When this is set, the system will not use the VPN network when an app
+ * tries to send traffic for an IP address that is on a local network.
+ *
+ * Note that there are important security implications. In particular, the
+ * networks that the device connects to typically decides what IP addresses
+ * are part of the local network. This means that for VPNs setting this
+ * flag, it is possible for anybody to set up a public network in such a
+ * way that traffic to arbitrary IP addresses will bypass the VPN, including
+ * traffic to services like DNS. When using this API, please consider the
+ * security implications for your particular case.
+ *
+ * Note that because the local traffic will always bypass the VPN,
+ * it is not possible to set this flag on a non-bypassable VPN.
*
- * @hide TODO(184750836): unhide once the implementation is completed
+ * @hide TODO(184750836): unhide once the implementation is completed
*/
@NonNull
@RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
diff --git a/core/java/android/net/InterfaceConfiguration.java b/core/java/android/net/InterfaceConfiguration.java
index 1c4089c0f366..37425ffc18aa 100644
--- a/core/java/android/net/InterfaceConfiguration.java
+++ b/core/java/android/net/InterfaceConfiguration.java
@@ -160,7 +160,6 @@ public class InterfaceConfiguration implements Parcelable {
}
}
- @SuppressWarnings("UnsafeParcelApi")
public static final @android.annotation.NonNull Creator<InterfaceConfiguration> CREATOR = new Creator<
InterfaceConfiguration>() {
public InterfaceConfiguration createFromParcel(Parcel in) {
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/core/java/android/net/InternalNetworkUpdateRequest.java
index 6f093835fb08..f42c4b7c420d 100644
--- a/core/java/android/net/InternalNetworkUpdateRequest.java
+++ b/core/java/android/net/InternalNetworkUpdateRequest.java
@@ -17,7 +17,6 @@
package android.net;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
@@ -27,7 +26,7 @@ import java.util.Objects;
public final class InternalNetworkUpdateRequest implements Parcelable {
@NonNull
private final StaticIpConfiguration mIpConfig;
- @Nullable
+ @NonNull
private final NetworkCapabilities mNetworkCapabilities;
@NonNull
@@ -37,20 +36,16 @@ public final class InternalNetworkUpdateRequest implements Parcelable {
@NonNull
public NetworkCapabilities getNetworkCapabilities() {
- return mNetworkCapabilities == null
- ? null : new NetworkCapabilities(mNetworkCapabilities);
+ return new NetworkCapabilities(mNetworkCapabilities);
}
/** @hide */
public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
- @Nullable final NetworkCapabilities networkCapabilities) {
+ @NonNull final NetworkCapabilities networkCapabilities) {
Objects.requireNonNull(ipConfig);
+ Objects.requireNonNull(networkCapabilities);
mIpConfig = new StaticIpConfiguration(ipConfig);
- if (null == networkCapabilities) {
- mNetworkCapabilities = null;
- } else {
- mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
- }
+ mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
}
private InternalNetworkUpdateRequest(@NonNull final Parcel source) {
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 596f4317dce3..ab1f5420fb3f 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -142,8 +142,8 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
}
private NetworkPolicy(Parcel source) {
- template = source.readParcelable(null, android.net.NetworkTemplate.class);
- cycleRule = source.readParcelable(null, android.util.RecurrenceRule.class);
+ template = source.readParcelable(null);
+ cycleRule = source.readParcelable(null);
warningBytes = source.readLong();
limitBytes = source.readLong();
lastWarningSnooze = source.readLong();
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index 2ced05693755..1ae1b050d32f 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -41,6 +41,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.NetworkUtilsInternal;
import com.android.internal.net.VpnConfig;
@@ -50,6 +51,7 @@ import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -471,6 +473,13 @@ public class VpnService extends Service {
}
}
+ private static void checkNonPrefixBytes(@NonNull InetAddress address, int prefixLength) {
+ final IpPrefix prefix = new IpPrefix(address, prefixLength);
+ if (!prefix.getAddress().equals(address)) {
+ throw new IllegalArgumentException("Bad address");
+ }
+ }
+
/**
* Helper class to create a VPN interface. This class should be always
* used within the scope of the outer {@link VpnService}.
@@ -481,9 +490,9 @@ public class VpnService extends Service {
private final VpnConfig mConfig = new VpnConfig();
@UnsupportedAppUsage
- private final List<LinkAddress> mAddresses = new ArrayList<LinkAddress>();
+ private final List<LinkAddress> mAddresses = new ArrayList<>();
@UnsupportedAppUsage
- private final List<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
+ private final List<RouteInfo> mRoutes = new ArrayList<>();
public Builder() {
mConfig.user = VpnService.this.getClass().getName();
@@ -555,7 +564,6 @@ public class VpnService extends Service {
throw new IllegalArgumentException("Bad address");
}
mAddresses.add(new LinkAddress(address, prefixLength));
- mConfig.updateAllowedFamilies(address);
return this;
}
@@ -579,28 +587,68 @@ public class VpnService extends Service {
* Add a network route to the VPN interface. Both IPv4 and IPv6
* routes are supported.
*
+ * If a route with the same destination is already present, its type will be updated.
+ *
+ * @throws IllegalArgumentException if the route is invalid.
+ */
+ @NonNull
+ private Builder addRoute(@NonNull IpPrefix prefix, int type) {
+ check(prefix.getAddress(), prefix.getPrefixLength());
+
+ final RouteInfo newRoute = new RouteInfo(prefix, /* gateway */
+ null, /* interface */ null, type);
+
+ final int index = findRouteIndexByDestination(newRoute);
+
+ if (index == -1) {
+ mRoutes.add(newRoute);
+ } else {
+ mRoutes.set(index, newRoute);
+ }
+
+ return this;
+ }
+
+ /**
+ * Add a network route to the VPN interface. Both IPv4 and IPv6
+ * routes are supported.
+ *
* Adding a route implicitly allows traffic from that address family
* (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
*
+ * Calling this method overrides previous calls to {@link #excludeRoute} for the same
+ * destination.
+ *
+ * If multiple routes match the packet destination, route with the longest prefix takes
+ * precedence.
+ *
* @throws IllegalArgumentException if the route is invalid.
*/
@NonNull
public Builder addRoute(@NonNull InetAddress address, int prefixLength) {
- check(address, prefixLength);
+ checkNonPrefixBytes(address, prefixLength);
- int offset = prefixLength / 8;
- byte[] bytes = address.getAddress();
- if (offset < bytes.length) {
- for (bytes[offset] <<= prefixLength % 8; offset < bytes.length; ++offset) {
- if (bytes[offset] != 0) {
- throw new IllegalArgumentException("Bad address");
- }
- }
- }
- mRoutes.add(new RouteInfo(new IpPrefix(address, prefixLength), null, null,
- RouteInfo.RTN_UNICAST));
- mConfig.updateAllowedFamilies(address);
- return this;
+ return addRoute(new IpPrefix(address, prefixLength), RouteInfo.RTN_UNICAST);
+ }
+
+ /**
+ * Add a network route to the VPN interface. Both IPv4 and IPv6
+ * routes are supported.
+ *
+ * Adding a route implicitly allows traffic from that address family
+ * (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
+ *
+ * Calling this method overrides previous calls to {@link #excludeRoute} for the same
+ * destination.
+ *
+ * If multiple routes match the packet destination, route with the longest prefix takes
+ * precedence.
+ *
+ * @throws IllegalArgumentException if the route is invalid.
+ */
+ @NonNull
+ public Builder addRoute(@NonNull IpPrefix prefix) {
+ return addRoute(prefix, RouteInfo.RTN_UNICAST);
}
/**
@@ -611,6 +659,12 @@ public class VpnService extends Service {
* Adding a route implicitly allows traffic from that address family
* (i.e., IPv4 or IPv6) to be routed over the VPN. @see #allowFamily
*
+ * Calling this method overrides previous calls to {@link #excludeRoute} for the same
+ * destination.
+ *
+ * If multiple routes match the packet destination, route with the longest prefix takes
+ * precedence.
+ *
* @throws IllegalArgumentException if the route is invalid.
* @see #addRoute(InetAddress, int)
*/
@@ -620,6 +674,23 @@ public class VpnService extends Service {
}
/**
+ * Exclude a network route from the VPN interface. Both IPv4 and IPv6
+ * routes are supported.
+ *
+ * Calling this method overrides previous calls to {@link #addRoute} for the same
+ * destination.
+ *
+ * If multiple routes match the packet destination, route with the longest prefix takes
+ * precedence.
+ *
+ * @throws IllegalArgumentException if the route is invalid.
+ */
+ @NonNull
+ public Builder excludeRoute(@NonNull IpPrefix prefix) {
+ return addRoute(prefix, RouteInfo.RTN_THROW);
+ }
+
+ /**
* Add a DNS server to the VPN connection. Both IPv4 and IPv6
* addresses are supported. If none is set, the DNS servers of
* the default network will be used.
@@ -900,5 +971,23 @@ public class VpnService extends Service {
throw new IllegalStateException(e);
}
}
+
+ private int findRouteIndexByDestination(RouteInfo route) {
+ for (int i = 0; i < mRoutes.size(); i++) {
+ if (mRoutes.get(i).getDestination().equals(route.getDestination())) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Method for testing, to observe mRoutes while builder is being used.
+ * @hide
+ */
+ @VisibleForTesting
+ public List<RouteInfo> routes() {
+ return Collections.unmodifiableList(mRoutes);
+ }
}
}
diff --git a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
index 1ac3f0a6d7d1..125b5730b2ed 100644
--- a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
@@ -15,6 +15,9 @@
*/
package android.net.vcn;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.getMatchCriteriaString;
+
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_DESERIALIZER;
import static com.android.server.vcn.util.PersistableBundleUtils.INTEGER_SERIALIZER;
@@ -23,8 +26,12 @@ import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZ
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.net.NetworkCapabilities;
+import android.net.vcn.VcnUnderlyingNetworkTemplate.MatchCriteria;
import android.os.PersistableBundle;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.ArraySet;
@@ -37,32 +44,36 @@ import java.util.Collections;
import java.util.Objects;
import java.util.Set;
-// TODO: Add documents
-/** @hide */
+/**
+ * This class represents a configuration for a network template class of underlying cellular
+ * networks.
+ *
+ * <p>See {@link VcnUnderlyingNetworkTemplate}
+ */
public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetworkTemplate {
private static final String ALLOWED_NETWORK_PLMN_IDS_KEY = "mAllowedNetworkPlmnIds";
@NonNull private final Set<String> mAllowedNetworkPlmnIds;
private static final String ALLOWED_SPECIFIC_CARRIER_IDS_KEY = "mAllowedSpecificCarrierIds";
@NonNull private final Set<Integer> mAllowedSpecificCarrierIds;
- private static final String ALLOW_ROAMING_KEY = "mAllowRoaming";
- private final boolean mAllowRoaming;
+ private static final String ROAMING_MATCH_KEY = "mRoamingMatchCriteria";
+ private final int mRoamingMatchCriteria;
- private static final String REQUIRE_OPPORTUNISTIC_KEY = "mRequireOpportunistic";
- private final boolean mRequireOpportunistic;
+ private static final String OPPORTUNISTIC_MATCH_KEY = "mOpportunisticMatchCriteria";
+ private final int mOpportunisticMatchCriteria;
private VcnCellUnderlyingNetworkTemplate(
int networkQuality,
- boolean allowMetered,
+ int meteredMatchCriteria,
Set<String> allowedNetworkPlmnIds,
Set<Integer> allowedSpecificCarrierIds,
- boolean allowRoaming,
- boolean requireOpportunistic) {
- super(NETWORK_PRIORITY_TYPE_CELL, networkQuality, allowMetered);
+ int roamingMatchCriteria,
+ int opportunisticMatchCriteria) {
+ super(NETWORK_PRIORITY_TYPE_CELL, networkQuality, meteredMatchCriteria);
mAllowedNetworkPlmnIds = new ArraySet<>(allowedNetworkPlmnIds);
mAllowedSpecificCarrierIds = new ArraySet<>(allowedSpecificCarrierIds);
- mAllowRoaming = allowRoaming;
- mRequireOpportunistic = requireOpportunistic;
+ mRoamingMatchCriteria = roamingMatchCriteria;
+ mOpportunisticMatchCriteria = opportunisticMatchCriteria;
validate();
}
@@ -72,15 +83,17 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
protected void validate() {
super.validate();
validatePlmnIds(mAllowedNetworkPlmnIds);
- Objects.requireNonNull(mAllowedSpecificCarrierIds, "allowedCarrierIds is null");
+ Objects.requireNonNull(mAllowedSpecificCarrierIds, "matchingCarrierIds is null");
+ validateMatchCriteria(mRoamingMatchCriteria, "mRoamingMatchCriteria");
+ validateMatchCriteria(mOpportunisticMatchCriteria, "mOpportunisticMatchCriteria");
}
- private static void validatePlmnIds(Set<String> allowedNetworkPlmnIds) {
- Objects.requireNonNull(allowedNetworkPlmnIds, "allowedNetworkPlmnIds is null");
+ private static void validatePlmnIds(Set<String> matchingOperatorPlmnIds) {
+ Objects.requireNonNull(matchingOperatorPlmnIds, "matchingOperatorPlmnIds is null");
// A valid PLMN is a concatenation of MNC and MCC, and thus consists of 5 or 6 decimal
// digits.
- for (String id : allowedNetworkPlmnIds) {
+ for (String id : matchingOperatorPlmnIds) {
if ((id.length() == 5 || id.length() == 6) && id.matches("[0-9]+")) {
continue;
} else {
@@ -97,7 +110,7 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
Objects.requireNonNull(in, "PersistableBundle is null");
final int networkQuality = in.getInt(NETWORK_QUALITY_KEY);
- final boolean allowMetered = in.getBoolean(ALLOW_METERED_KEY);
+ final int meteredMatchCriteria = in.getInt(METERED_MATCH_KEY);
final PersistableBundle plmnIdsBundle =
in.getPersistableBundle(ALLOWED_NETWORK_PLMN_IDS_KEY);
@@ -114,16 +127,16 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
PersistableBundleUtils.toList(
specificCarrierIdsBundle, INTEGER_DESERIALIZER));
- final boolean allowRoaming = in.getBoolean(ALLOW_ROAMING_KEY);
- final boolean requireOpportunistic = in.getBoolean(REQUIRE_OPPORTUNISTIC_KEY);
+ final int roamingMatchCriteria = in.getInt(ROAMING_MATCH_KEY);
+ final int opportunisticMatchCriteria = in.getInt(OPPORTUNISTIC_MATCH_KEY);
return new VcnCellUnderlyingNetworkTemplate(
networkQuality,
- allowMetered,
+ meteredMatchCriteria,
allowedNetworkPlmnIds,
allowedSpecificCarrierIds,
- allowRoaming,
- requireOpportunistic);
+ roamingMatchCriteria,
+ opportunisticMatchCriteria);
}
/** @hide */
@@ -143,35 +156,51 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
new ArrayList<>(mAllowedSpecificCarrierIds), INTEGER_SERIALIZER);
result.putPersistableBundle(ALLOWED_SPECIFIC_CARRIER_IDS_KEY, specificCarrierIdsBundle);
- result.putBoolean(ALLOW_ROAMING_KEY, mAllowRoaming);
- result.putBoolean(REQUIRE_OPPORTUNISTIC_KEY, mRequireOpportunistic);
+ result.putInt(ROAMING_MATCH_KEY, mRoamingMatchCriteria);
+ result.putInt(OPPORTUNISTIC_MATCH_KEY, mOpportunisticMatchCriteria);
return result;
}
- /** Retrieve the allowed PLMN IDs, or an empty set if any PLMN ID is acceptable. */
+ /**
+ * Retrieve the matching operator PLMN IDs, or an empty set if any PLMN ID is acceptable.
+ *
+ * @see Builder#setOperatorPlmnIds(Set)
+ */
@NonNull
- public Set<String> getAllowedOperatorPlmnIds() {
+ public Set<String> getOperatorPlmnIds() {
return Collections.unmodifiableSet(mAllowedNetworkPlmnIds);
}
/**
- * Retrieve the allowed specific carrier IDs, or an empty set if any specific carrier ID is
- * acceptable.
+ * Retrieve the matching sim specific carrier IDs, or an empty set if any sim specific carrier
+ * ID is acceptable.
+ *
+ * @see Builder#setSimSpecificCarrierIds(Set)
*/
@NonNull
- public Set<Integer> getAllowedSpecificCarrierIds() {
+ public Set<Integer> getSimSpecificCarrierIds() {
return Collections.unmodifiableSet(mAllowedSpecificCarrierIds);
}
- /** Return if roaming is allowed. */
- public boolean allowRoaming() {
- return mAllowRoaming;
+ /**
+ * Return the matching criteria for roaming networks.
+ *
+ * @see Builder#setRoaming(int)
+ */
+ @MatchCriteria
+ public int getRoaming() {
+ return mRoamingMatchCriteria;
}
- /** Return if requiring an opportunistic network. */
- public boolean requireOpportunistic() {
- return mRequireOpportunistic;
+ /**
+ * Return the matching criteria for opportunistic cellular subscriptions.
+ *
+ * @see Builder#setOpportunistic(int)
+ */
+ @MatchCriteria
+ public int getOpportunistic() {
+ return mOpportunisticMatchCriteria;
}
@Override
@@ -180,8 +209,8 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
super.hashCode(),
mAllowedNetworkPlmnIds,
mAllowedSpecificCarrierIds,
- mAllowRoaming,
- mRequireOpportunistic);
+ mRoamingMatchCriteria,
+ mOpportunisticMatchCriteria);
}
@Override
@@ -197,8 +226,8 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
final VcnCellUnderlyingNetworkTemplate rhs = (VcnCellUnderlyingNetworkTemplate) other;
return Objects.equals(mAllowedNetworkPlmnIds, rhs.mAllowedNetworkPlmnIds)
&& Objects.equals(mAllowedSpecificCarrierIds, rhs.mAllowedSpecificCarrierIds)
- && mAllowRoaming == rhs.mAllowRoaming
- && mRequireOpportunistic == rhs.mRequireOpportunistic;
+ && mRoamingMatchCriteria == rhs.mRoamingMatchCriteria
+ && mOpportunisticMatchCriteria == rhs.mOpportunisticMatchCriteria;
}
/** @hide */
@@ -206,77 +235,137 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
void dumpTransportSpecificFields(IndentingPrintWriter pw) {
pw.println("mAllowedNetworkPlmnIds: " + mAllowedNetworkPlmnIds.toString());
pw.println("mAllowedSpecificCarrierIds: " + mAllowedSpecificCarrierIds.toString());
- pw.println("mAllowRoaming: " + mAllowRoaming);
- pw.println("mRequireOpportunistic: " + mRequireOpportunistic);
+ pw.println("mRoamingMatchCriteria: " + getMatchCriteriaString(mRoamingMatchCriteria));
+ pw.println(
+ "mOpportunisticMatchCriteria: "
+ + getMatchCriteriaString(mOpportunisticMatchCriteria));
}
- /** This class is used to incrementally build WifiNetworkPriority objects. */
- public static final class Builder extends VcnUnderlyingNetworkTemplate.Builder<Builder> {
+ /** This class is used to incrementally build VcnCellUnderlyingNetworkTemplate objects. */
+ public static final class Builder {
+ private int mNetworkQuality = NETWORK_QUALITY_ANY;
+ private int mMeteredMatchCriteria = MATCH_ANY;
+
@NonNull private final Set<String> mAllowedNetworkPlmnIds = new ArraySet<>();
@NonNull private final Set<Integer> mAllowedSpecificCarrierIds = new ArraySet<>();
- private boolean mAllowRoaming = false;
- private boolean mRequireOpportunistic = false;
+ private int mRoamingMatchCriteria = MATCH_ANY;
+ private int mOpportunisticMatchCriteria = MATCH_ANY;
/** Construct a Builder object. */
public Builder() {}
/**
- * Set allowed operator PLMN IDs.
+ * Set the required network quality to match this template.
+ *
+ * <p>Network quality is a aggregation of multiple signals that reflect the network link
+ * metrics. For example, the network validation bit (see {@link
+ * NetworkCapabilities#NET_CAPABILITY_VALIDATED}), estimated first hop transport bandwidth
+ * and signal strength.
+ *
+ * @param networkQuality the required network quality. Defaults to NETWORK_QUALITY_ANY
+ * @hide
+ */
+ @NonNull
+ public Builder setNetworkQuality(@NetworkQuality int networkQuality) {
+ validateNetworkQuality(networkQuality);
+
+ mNetworkQuality = networkQuality;
+ return this;
+ }
+
+ /**
+ * Set the matching criteria for metered networks.
+ *
+ * <p>A template where setMetered(MATCH_REQUIRED) will only match metered networks (one
+ * without NET_CAPABILITY_NOT_METERED). A template where setMetered(MATCH_FORBIDDEN) will
+ * only match a network that is not metered (one with NET_CAPABILITY_NOT_METERED).
+ *
+ * @param matchCriteria the matching criteria for metered networks. Defaults to {@link
+ * #MATCH_ANY}.
+ * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED
+ */
+ // The matching getter is defined in the super class. Please see {@link
+ // VcnUnderlyingNetworkTemplate#getMetered()}
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @NonNull
+ public Builder setMetered(@MatchCriteria int matchCriteria) {
+ validateMatchCriteria(matchCriteria, "setMetered");
+
+ mMeteredMatchCriteria = matchCriteria;
+ return this;
+ }
+
+ /**
+ * Set operator PLMN IDs with which a network can match this template.
*
* <p>This is used to distinguish cases where roaming agreements may dictate a different
* priority from a partner's networks.
*
- * @param allowedNetworkPlmnIds the allowed operator PLMN IDs in String. Defaults to an
- * empty set, allowing ANY PLMN ID. A valid PLMN is a concatenation of MNC and MCC, and
- * thus consists of 5 or 6 decimal digits. See {@link SubscriptionInfo#getMccString()}
- * and {@link SubscriptionInfo#getMncString()}.
+ * @param operatorPlmnIds the matching operator PLMN IDs in String. Network with one of the
+ * matching PLMN IDs can match this template. If the set is empty, any PLMN ID will
+ * match. The default is an empty set. A valid PLMN is a concatenation of MNC and MCC,
+ * and thus consists of 5 or 6 decimal digits.
+ * @see SubscriptionInfo#getMccString()
+ * @see SubscriptionInfo#getMncString()
*/
@NonNull
- public Builder setAllowedOperatorPlmnIds(@NonNull Set<String> allowedNetworkPlmnIds) {
- validatePlmnIds(allowedNetworkPlmnIds);
+ public Builder setOperatorPlmnIds(@NonNull Set<String> operatorPlmnIds) {
+ validatePlmnIds(operatorPlmnIds);
mAllowedNetworkPlmnIds.clear();
- mAllowedNetworkPlmnIds.addAll(allowedNetworkPlmnIds);
+ mAllowedNetworkPlmnIds.addAll(operatorPlmnIds);
return this;
}
/**
- * Set allowed specific carrier IDs.
+ * Set sim specific carrier IDs with which a network can match this template.
*
- * @param allowedSpecificCarrierIds the allowed specific carrier IDs. Defaults to an empty
- * set, allowing ANY carrier ID. See {@link TelephonyManager#getSimSpecificCarrierId()}.
+ * @param simSpecificCarrierIds the matching sim specific carrier IDs. Network with one of
+ * the sim specific carrier IDs can match this template. If the set is empty, any
+ * carrier ID will match. The default is an empty set.
+ * @see TelephonyManager#getSimSpecificCarrierId()
*/
@NonNull
- public Builder setAllowedSpecificCarrierIds(
- @NonNull Set<Integer> allowedSpecificCarrierIds) {
- Objects.requireNonNull(allowedSpecificCarrierIds, "allowedCarrierIds is null");
+ public Builder setSimSpecificCarrierIds(@NonNull Set<Integer> simSpecificCarrierIds) {
+ Objects.requireNonNull(simSpecificCarrierIds, "simSpecificCarrierIds is null");
+
mAllowedSpecificCarrierIds.clear();
- mAllowedSpecificCarrierIds.addAll(allowedSpecificCarrierIds);
+ mAllowedSpecificCarrierIds.addAll(simSpecificCarrierIds);
return this;
}
/**
- * Set if roaming is allowed.
+ * Set the matching criteria for roaming networks.
*
- * @param allowRoaming the flag to indicate if roaming is allowed. Defaults to {@code
- * false}.
+ * <p>A template where setRoaming(MATCH_REQUIRED) will only match roaming networks (one
+ * without NET_CAPABILITY_NOT_ROAMING). A template where setRoaming(MATCH_FORBIDDEN) will
+ * only match a network that is not roaming (one with NET_CAPABILITY_NOT_ROAMING).
+ *
+ * @param matchCriteria the matching criteria for roaming networks. Defaults to {@link
+ * #MATCH_ANY}.
+ * @see NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING
*/
@NonNull
- public Builder setAllowRoaming(boolean allowRoaming) {
- mAllowRoaming = allowRoaming;
+ public Builder setRoaming(@MatchCriteria int matchCriteria) {
+ validateMatchCriteria(matchCriteria, "setRoaming");
+
+ mRoamingMatchCriteria = matchCriteria;
return this;
}
/**
- * Set if requiring an opportunistic network.
+ * Set the matching criteria for opportunistic cellular subscriptions.
*
- * @param requireOpportunistic the flag to indicate if caller requires an opportunistic
- * network. Defaults to {@code false}.
+ * @param matchCriteria the matching criteria for opportunistic cellular subscriptions.
+ * Defaults to {@link #MATCH_ANY}.
+ * @see SubscriptionManager#setOpportunistic(boolean, int)
*/
@NonNull
- public Builder setRequireOpportunistic(boolean requireOpportunistic) {
- mRequireOpportunistic = requireOpportunistic;
+ public Builder setOpportunistic(@MatchCriteria int matchCriteria) {
+ validateMatchCriteria(matchCriteria, "setOpportunistic");
+
+ mOpportunisticMatchCriteria = matchCriteria;
return this;
}
@@ -285,17 +374,11 @@ public final class VcnCellUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
public VcnCellUnderlyingNetworkTemplate build() {
return new VcnCellUnderlyingNetworkTemplate(
mNetworkQuality,
- mAllowMetered,
+ mMeteredMatchCriteria,
mAllowedNetworkPlmnIds,
mAllowedSpecificCarrierIds,
- mAllowRoaming,
- mRequireOpportunistic);
- }
-
- /** @hide */
- @Override
- Builder self() {
- return this;
+ mRoamingMatchCriteria,
+ mOpportunisticMatchCriteria);
}
}
}
diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index fd3fe3731b74..caab15251f58 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -173,7 +173,7 @@ public final class VcnConfig implements Parcelable {
new Parcelable.Creator<VcnConfig>() {
@NonNull
public VcnConfig createFromParcel(Parcel in) {
- return new VcnConfig((PersistableBundle) in.readParcelable(null, android.os.PersistableBundle.class));
+ return new VcnConfig((PersistableBundle) in.readParcelable(null));
}
@NonNull
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index d07c24a6529c..92956e859fc7 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -16,6 +16,7 @@
package android.net.vcn;
import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
@@ -42,7 +43,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
@@ -162,30 +163,24 @@ public final class VcnGatewayConnectionConfig {
/** @hide */
@VisibleForTesting(visibility = Visibility.PRIVATE)
- public static final LinkedHashSet<VcnUnderlyingNetworkTemplate>
- DEFAULT_UNDERLYING_NETWORK_PRIORITIES = new LinkedHashSet<>();
+ public static final List<VcnUnderlyingNetworkTemplate> DEFAULT_UNDERLYING_NETWORK_TEMPLATES =
+ new ArrayList<>();
static {
- DEFAULT_UNDERLYING_NETWORK_PRIORITIES.add(
+ DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add(
new VcnCellUnderlyingNetworkTemplate.Builder()
.setNetworkQuality(NETWORK_QUALITY_OK)
- .setAllowMetered(true /* allowMetered */)
- .setAllowRoaming(true /* allowRoaming */)
- .setRequireOpportunistic(true /* requireOpportunistic */)
+ .setOpportunistic(MATCH_REQUIRED)
.build());
- DEFAULT_UNDERLYING_NETWORK_PRIORITIES.add(
+ DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add(
new VcnWifiUnderlyingNetworkTemplate.Builder()
.setNetworkQuality(NETWORK_QUALITY_OK)
- .setAllowMetered(true /* allowMetered */)
.build());
- DEFAULT_UNDERLYING_NETWORK_PRIORITIES.add(
+ DEFAULT_UNDERLYING_NETWORK_TEMPLATES.add(
new VcnCellUnderlyingNetworkTemplate.Builder()
.setNetworkQuality(NETWORK_QUALITY_OK)
- .setAllowMetered(true /* allowMetered */)
- .setAllowRoaming(true /* allowRoaming */)
- .setRequireOpportunistic(false /* requireOpportunistic */)
.build());
}
@@ -200,9 +195,9 @@ public final class VcnGatewayConnectionConfig {
/** @hide */
@VisibleForTesting(visibility = Visibility.PRIVATE)
- public static final String UNDERLYING_NETWORK_PRIORITIES_KEY = "mUnderlyingNetworkPriorities";
+ public static final String UNDERLYING_NETWORK_TEMPLATES_KEY = "mUnderlyingNetworkTemplates";
- @NonNull private final LinkedHashSet<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkPriorities;
+ @NonNull private final List<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkTemplates;
private static final String MAX_MTU_KEY = "mMaxMtu";
private final int mMaxMtu;
@@ -215,7 +210,7 @@ public final class VcnGatewayConnectionConfig {
@NonNull String gatewayConnectionName,
@NonNull IkeTunnelConnectionParams tunnelConnectionParams,
@NonNull Set<Integer> exposedCapabilities,
- @NonNull LinkedHashSet<VcnUnderlyingNetworkTemplate> underlyingNetworkPriorities,
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
@NonNull long[] retryIntervalsMs,
@IntRange(from = MIN_MTU_V6) int maxMtu) {
mGatewayConnectionName = gatewayConnectionName;
@@ -224,9 +219,9 @@ public final class VcnGatewayConnectionConfig {
mRetryIntervalsMs = retryIntervalsMs;
mMaxMtu = maxMtu;
- mUnderlyingNetworkPriorities = new LinkedHashSet<>(underlyingNetworkPriorities);
- if (mUnderlyingNetworkPriorities.isEmpty()) {
- mUnderlyingNetworkPriorities.addAll(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
+ mUnderlyingNetworkTemplates = new ArrayList<>(underlyingNetworkTemplates);
+ if (mUnderlyingNetworkTemplates.isEmpty()) {
+ mUnderlyingNetworkTemplates.addAll(DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
}
validate();
@@ -250,22 +245,19 @@ public final class VcnGatewayConnectionConfig {
mExposedCapabilities = new TreeSet<>(PersistableBundleUtils.toList(
exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
- final PersistableBundle networkPrioritiesBundle =
- in.getPersistableBundle(UNDERLYING_NETWORK_PRIORITIES_KEY);
+ final PersistableBundle networkTemplatesBundle =
+ in.getPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY);
- if (networkPrioritiesBundle == null) {
- // UNDERLYING_NETWORK_PRIORITIES_KEY was added in Android T. Thus
+ if (networkTemplatesBundle == null) {
+ // UNDERLYING_NETWORK_TEMPLATES_KEY was added in Android T. Thus
// VcnGatewayConnectionConfig created on old platforms will not have this data and will
// be assigned with the default value
- mUnderlyingNetworkPriorities =
- new LinkedHashSet<>(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
-
+ mUnderlyingNetworkTemplates = new ArrayList<>(DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
} else {
- mUnderlyingNetworkPriorities =
- new LinkedHashSet<>(
- PersistableBundleUtils.toList(
- networkPrioritiesBundle,
- VcnUnderlyingNetworkTemplate::fromPersistableBundle));
+ mUnderlyingNetworkTemplates =
+ PersistableBundleUtils.toList(
+ networkTemplatesBundle,
+ VcnUnderlyingNetworkTemplate::fromPersistableBundle);
}
mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
@@ -285,7 +277,7 @@ public final class VcnGatewayConnectionConfig {
checkValidCapability(cap);
}
- Objects.requireNonNull(mUnderlyingNetworkPriorities, "underlyingNetworkPriorities is null");
+ validateNetworkTemplateList(mUnderlyingNetworkTemplates);
Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null");
validateRetryInterval(mRetryIntervalsMs);
@@ -314,6 +306,19 @@ public final class VcnGatewayConnectionConfig {
}
}
+ private static void validateNetworkTemplateList(
+ List<VcnUnderlyingNetworkTemplate> networkPriorityRules) {
+ Objects.requireNonNull(networkPriorityRules, "networkPriorityRules is null");
+
+ Set<VcnUnderlyingNetworkTemplate> existingRules = new ArraySet<>();
+ for (VcnUnderlyingNetworkTemplate rule : networkPriorityRules) {
+ Objects.requireNonNull(rule, "Found null value VcnUnderlyingNetworkTemplate");
+ if (!existingRules.add(rule)) {
+ throw new IllegalArgumentException("Found duplicate VcnUnderlyingNetworkTemplate");
+ }
+ }
+ }
+
/**
* Returns the configured Gateway Connection name.
*
@@ -368,15 +373,13 @@ public final class VcnGatewayConnectionConfig {
}
/**
- * Retrieve the configured VcnUnderlyingNetworkTemplate list, or a default list if it is not
- * configured.
+ * Retrieve the VcnUnderlyingNetworkTemplate list, or a default list if it is not configured.
*
- * @see Builder#setVcnUnderlyingNetworkPriorities(LinkedHashSet<VcnUnderlyingNetworkTemplate>)
- * @hide
+ * @see Builder#setVcnUnderlyingNetworkPriorities(List)
*/
@NonNull
- public LinkedHashSet<VcnUnderlyingNetworkTemplate> getVcnUnderlyingNetworkPriorities() {
- return new LinkedHashSet<>(mUnderlyingNetworkPriorities);
+ public List<VcnUnderlyingNetworkTemplate> getVcnUnderlyingNetworkPriorities() {
+ return new ArrayList<>(mUnderlyingNetworkTemplates);
}
/**
@@ -415,15 +418,15 @@ public final class VcnGatewayConnectionConfig {
PersistableBundleUtils.fromList(
new ArrayList<>(mExposedCapabilities),
PersistableBundleUtils.INTEGER_SERIALIZER);
- final PersistableBundle networkPrioritiesBundle =
+ final PersistableBundle networkTemplatesBundle =
PersistableBundleUtils.fromList(
- new ArrayList<>(mUnderlyingNetworkPriorities),
+ mUnderlyingNetworkTemplates,
VcnUnderlyingNetworkTemplate::toPersistableBundle);
result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle);
result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
- result.putPersistableBundle(UNDERLYING_NETWORK_PRIORITIES_KEY, networkPrioritiesBundle);
+ result.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, networkTemplatesBundle);
result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
result.putInt(MAX_MTU_KEY, mMaxMtu);
@@ -436,7 +439,7 @@ public final class VcnGatewayConnectionConfig {
mGatewayConnectionName,
mTunnelConnectionParams,
mExposedCapabilities,
- mUnderlyingNetworkPriorities,
+ mUnderlyingNetworkTemplates,
Arrays.hashCode(mRetryIntervalsMs),
mMaxMtu);
}
@@ -451,7 +454,7 @@ public final class VcnGatewayConnectionConfig {
return mGatewayConnectionName.equals(rhs.mGatewayConnectionName)
&& mTunnelConnectionParams.equals(rhs.mTunnelConnectionParams)
&& mExposedCapabilities.equals(rhs.mExposedCapabilities)
- && mUnderlyingNetworkPriorities.equals(rhs.mUnderlyingNetworkPriorities)
+ && mUnderlyingNetworkTemplates.equals(rhs.mUnderlyingNetworkTemplates)
&& Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
&& mMaxMtu == rhs.mMaxMtu;
}
@@ -465,8 +468,8 @@ public final class VcnGatewayConnectionConfig {
@NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
@NonNull
- private final LinkedHashSet<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkPriorities =
- new LinkedHashSet<>(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
+ private final List<VcnUnderlyingNetworkTemplate> mUnderlyingNetworkTemplates =
+ new ArrayList<>(DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
@NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
private int mMaxMtu = DEFAULT_MAX_MTU;
@@ -539,27 +542,37 @@ public final class VcnGatewayConnectionConfig {
}
/**
- * Set the VcnUnderlyingNetworkTemplate list.
+ * Set the list of templates to match underlying networks against, in high-to-low priority
+ * order.
+ *
+ * <p>To select the VCN underlying network, the VCN connection will go through all the
+ * network candidates and return a network matching the highest priority rule.
+ *
+ * <p>If multiple networks match the same rule, the VCN will prefer an already-selected
+ * network as opposed to a new/unselected network. However, if both are new/unselected
+ * networks, a network will be chosen arbitrarily amongst the networks matching the highest
+ * priority rule.
*
- * @param underlyingNetworkPriorities a list of unique VcnUnderlyingNetworkPriorities that
- * are ordered from most to least preferred, or an empty list to use the default
- * prioritization. The default network prioritization is Opportunistic cellular, Carrier
- * WiFi and Macro cellular
- * @return
+ * <p>If all networks fail to match the rules provided, an underlying network will still be
+ * selected (at random if necessary).
+ *
+ * @param underlyingNetworkTemplates a list of unique VcnUnderlyingNetworkTemplates that are
+ * ordered from most to least preferred, or an empty list to use the default
+ * prioritization. The default network prioritization order is Opportunistic cellular,
+ * Carrier WiFi and then Macro cellular.
+ * @return this {@link Builder} instance, for chaining
*/
- /** @hide */
@NonNull
public Builder setVcnUnderlyingNetworkPriorities(
- @NonNull LinkedHashSet<VcnUnderlyingNetworkTemplate> underlyingNetworkPriorities) {
- Objects.requireNonNull(
- mUnderlyingNetworkPriorities, "underlyingNetworkPriorities is null");
+ @NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates) {
+ validateNetworkTemplateList(underlyingNetworkTemplates);
- mUnderlyingNetworkPriorities.clear();
+ mUnderlyingNetworkTemplates.clear();
- if (underlyingNetworkPriorities.isEmpty()) {
- mUnderlyingNetworkPriorities.addAll(DEFAULT_UNDERLYING_NETWORK_PRIORITIES);
+ if (underlyingNetworkTemplates.isEmpty()) {
+ mUnderlyingNetworkTemplates.addAll(DEFAULT_UNDERLYING_NETWORK_TEMPLATES);
} else {
- mUnderlyingNetworkPriorities.addAll(underlyingNetworkPriorities);
+ mUnderlyingNetworkTemplates.addAll(underlyingNetworkTemplates);
}
return this;
@@ -629,7 +642,7 @@ public final class VcnGatewayConnectionConfig {
mGatewayConnectionName,
mTunnelConnectionParams,
mExposedCapabilities,
- mUnderlyingNetworkPriorities,
+ mUnderlyingNetworkTemplates,
mRetryIntervalsMs,
mMaxMtu);
}
diff --git a/core/java/android/net/vcn/VcnNetworkPolicyResult.java b/core/java/android/net/vcn/VcnNetworkPolicyResult.java
index fca084a00a79..14e70cfeb18a 100644
--- a/core/java/android/net/vcn/VcnNetworkPolicyResult.java
+++ b/core/java/android/net/vcn/VcnNetworkPolicyResult.java
@@ -114,7 +114,7 @@ public final class VcnNetworkPolicyResult implements Parcelable {
public static final @NonNull Creator<VcnNetworkPolicyResult> CREATOR =
new Creator<VcnNetworkPolicyResult>() {
public VcnNetworkPolicyResult createFromParcel(Parcel in) {
- return new VcnNetworkPolicyResult(in.readBoolean(), in.readParcelable(null, android.net.NetworkCapabilities.class));
+ return new VcnNetworkPolicyResult(in.readBoolean(), in.readParcelable(null));
}
public VcnNetworkPolicyResult[] newArray(int size) {
diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java
index 5c47b28a7c74..25a257423ce2 100644
--- a/core/java/android/net/vcn/VcnTransportInfo.java
+++ b/core/java/android/net/vcn/VcnTransportInfo.java
@@ -146,7 +146,7 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
new Creator<VcnTransportInfo>() {
public VcnTransportInfo createFromParcel(Parcel in) {
final int subId = in.readInt();
- final WifiInfo wifiInfo = in.readParcelable(null, android.net.wifi.WifiInfo.class);
+ final WifiInfo wifiInfo = in.readParcelable(null);
// If all fields are their null values, return null TransportInfo to avoid
// leaking information about this being a VCN Network (instead of macro
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java b/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
index 2b5305d05dcd..b0d4f3be248f 100644
--- a/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkPolicy.java
@@ -106,7 +106,7 @@ public final class VcnUnderlyingNetworkPolicy implements Parcelable {
public static final @NonNull Creator<VcnUnderlyingNetworkPolicy> CREATOR =
new Creator<VcnUnderlyingNetworkPolicy>() {
public VcnUnderlyingNetworkPolicy createFromParcel(Parcel in) {
- return new VcnUnderlyingNetworkPolicy(in.readParcelable(null, android.net.vcn.VcnNetworkPolicyResult.class));
+ return new VcnUnderlyingNetworkPolicy(in.readParcelable(null));
}
public VcnUnderlyingNetworkPolicy[] newArray(int size) {
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
index d306d5cb6826..60fc936072fb 100644
--- a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
@@ -15,6 +15,8 @@
*/
package android.net.vcn;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
+
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import android.annotation.IntDef;
@@ -31,17 +33,24 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
-// TODO: Add documents
-/** @hide */
+/**
+ * This class represents a template containing set of underlying network requirements for doing
+ * route selection.
+ *
+ * <p>Apps provisioning a VCN can configure the underlying network priority for each Gateway
+ * Connection by setting a list (in priority order, most to least preferred) of the appropriate
+ * subclasses in the VcnGatewayConnectionConfig. See {@link
+ * VcnGatewayConnectionConfig.Builder#setVcnUnderlyingNetworkPriorities}
+ */
public abstract class VcnUnderlyingNetworkTemplate {
/** @hide */
- protected static final int NETWORK_PRIORITY_TYPE_WIFI = 1;
+ static final int NETWORK_PRIORITY_TYPE_WIFI = 1;
/** @hide */
- protected static final int NETWORK_PRIORITY_TYPE_CELL = 2;
+ static final int NETWORK_PRIORITY_TYPE_CELL = 2;
- /** Denotes that any network quality is acceptable */
+ /** Denotes that any network quality is acceptable. @hide */
public static final int NETWORK_QUALITY_ANY = 0;
- /** Denotes that network quality needs to be OK */
+ /** Denotes that network quality needs to be OK. @hide */
public static final int NETWORK_QUALITY_OK = 100000;
private static final SparseArray<String> NETWORK_QUALITY_TO_STRING_MAP = new SparseArray<>();
@@ -56,34 +65,82 @@ public abstract class VcnUnderlyingNetworkTemplate {
@IntDef({NETWORK_QUALITY_OK, NETWORK_QUALITY_ANY})
public @interface NetworkQuality {}
+ /**
+ * Used to configure the matching criteria of a network characteristic. This may include network
+ * capabilities, or cellular subscription information. Denotes that networks with or without the
+ * characteristic are both acceptable to match this template.
+ */
+ public static final int MATCH_ANY = 0;
+
+ /**
+ * Used to configure the matching criteria of a network characteristic. This may include network
+ * capabilities, or cellular subscription information. Denotes that a network MUST have the
+ * capability in order to match this template.
+ */
+ public static final int MATCH_REQUIRED = 1;
+
+ /**
+ * Used to configure the matching criteria of a network characteristic. This may include network
+ * capabilities, or cellular subscription information. Denotes that a network MUST NOT have the
+ * capability in order to match this template.
+ */
+ public static final int MATCH_FORBIDDEN = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({MATCH_ANY, MATCH_REQUIRED, MATCH_FORBIDDEN})
+ public @interface MatchCriteria {}
+
+ private static final SparseArray<String> MATCH_CRITERIA_TO_STRING_MAP = new SparseArray<>();
+
+ static {
+ MATCH_CRITERIA_TO_STRING_MAP.put(MATCH_ANY, "MATCH_ANY");
+ MATCH_CRITERIA_TO_STRING_MAP.put(MATCH_REQUIRED, "MATCH_REQUIRED");
+ MATCH_CRITERIA_TO_STRING_MAP.put(MATCH_FORBIDDEN, "MATCH_FORBIDDEN");
+ }
+
private static final String NETWORK_PRIORITY_TYPE_KEY = "mNetworkPriorityType";
private final int mNetworkPriorityType;
/** @hide */
- protected static final String NETWORK_QUALITY_KEY = "mNetworkQuality";
+ static final String NETWORK_QUALITY_KEY = "mNetworkQuality";
+
private final int mNetworkQuality;
/** @hide */
- protected static final String ALLOW_METERED_KEY = "mAllowMetered";
- private final boolean mAllowMetered;
+ static final String METERED_MATCH_KEY = "mMeteredMatchCriteria";
+
+ private final int mMeteredMatchCriteria;
/** @hide */
- protected VcnUnderlyingNetworkTemplate(
- int networkPriorityType, int networkQuality, boolean allowMetered) {
+ VcnUnderlyingNetworkTemplate(
+ int networkPriorityType, int networkQuality, int meteredMatchCriteria) {
mNetworkPriorityType = networkPriorityType;
mNetworkQuality = networkQuality;
- mAllowMetered = allowMetered;
+ mMeteredMatchCriteria = meteredMatchCriteria;
}
- private static void validateNetworkQuality(int networkQuality) {
+ /** @hide */
+ static void validateNetworkQuality(int networkQuality) {
Preconditions.checkArgument(
networkQuality == NETWORK_QUALITY_ANY || networkQuality == NETWORK_QUALITY_OK,
"Invalid networkQuality:" + networkQuality);
}
/** @hide */
+ static void validateMatchCriteria(int meteredMatchCriteria, String matchingCapability) {
+ Preconditions.checkArgument(
+ MATCH_CRITERIA_TO_STRING_MAP.contains(meteredMatchCriteria),
+ "Invalid matching criteria: "
+ + meteredMatchCriteria
+ + " for "
+ + matchingCapability);
+ }
+
+ /** @hide */
protected void validate() {
validateNetworkQuality(mNetworkQuality);
+ validateMatchCriteria(mMeteredMatchCriteria, "mMeteredMatchCriteria");
}
/** @hide */
@@ -112,14 +169,14 @@ public abstract class VcnUnderlyingNetworkTemplate {
result.putInt(NETWORK_PRIORITY_TYPE_KEY, mNetworkPriorityType);
result.putInt(NETWORK_QUALITY_KEY, mNetworkQuality);
- result.putBoolean(ALLOW_METERED_KEY, mAllowMetered);
+ result.putInt(METERED_MATCH_KEY, mMeteredMatchCriteria);
return result;
}
@Override
public int hashCode() {
- return Objects.hash(mNetworkPriorityType, mNetworkQuality, mAllowMetered);
+ return Objects.hash(mNetworkPriorityType, mNetworkQuality, mMeteredMatchCriteria);
}
@Override
@@ -131,7 +188,17 @@ public abstract class VcnUnderlyingNetworkTemplate {
final VcnUnderlyingNetworkTemplate rhs = (VcnUnderlyingNetworkTemplate) other;
return mNetworkPriorityType == rhs.mNetworkPriorityType
&& mNetworkQuality == rhs.mNetworkQuality
- && mAllowMetered == rhs.mAllowMetered;
+ && mMeteredMatchCriteria == rhs.mMeteredMatchCriteria;
+ }
+
+ /** @hide */
+ static String getNameString(SparseArray<String> toStringMap, int key) {
+ return toStringMap.get(key, "Invalid value " + key);
+ }
+
+ /** @hide */
+ static String getMatchCriteriaString(int meteredMatchCriteria) {
+ return getNameString(MATCH_CRITERIA_TO_STRING_MAP, meteredMatchCriteria);
}
/** @hide */
@@ -148,65 +215,32 @@ public abstract class VcnUnderlyingNetworkTemplate {
pw.println(
"mNetworkQuality: "
- + NETWORK_QUALITY_TO_STRING_MAP.get(
- mNetworkQuality, "Invalid value " + mNetworkQuality));
- pw.println("mAllowMetered: " + mAllowMetered);
+ + getNameString(NETWORK_QUALITY_TO_STRING_MAP, mNetworkQuality));
+ pw.println("mMeteredMatchCriteria: " + getMatchCriteriaString(mMeteredMatchCriteria));
dumpTransportSpecificFields(pw);
pw.decreaseIndent();
}
- /** Retrieve the required network quality. */
+ /**
+ * Retrieve the required network quality to match this template.
+ *
+ * @see Builder#setNetworkQuality(int)
+ * @hide
+ */
@NetworkQuality
public int getNetworkQuality() {
return mNetworkQuality;
}
- /** Return if a metered network is allowed. */
- public boolean allowMetered() {
- return mAllowMetered;
- }
-
/**
- * This class is used to incrementally build VcnUnderlyingNetworkTemplate objects.
+ * Return the matching criteria for metered networks.
*
- * @param <T> The subclass to be built.
+ * @see VcnWifiUnderlyingNetworkTemplate.Builder#setMetered(int)
+ * @see VcnCellUnderlyingNetworkTemplate.Builder#setMetered(int)
*/
- public abstract static class Builder<T extends Builder<T>> {
- /** @hide */
- protected int mNetworkQuality = NETWORK_QUALITY_ANY;
- /** @hide */
- protected boolean mAllowMetered = false;
-
- /** @hide */
- protected Builder() {}
-
- /**
- * Set the required network quality.
- *
- * @param networkQuality the required network quality. Defaults to NETWORK_QUALITY_ANY
- */
- @NonNull
- public T setNetworkQuality(@NetworkQuality int networkQuality) {
- validateNetworkQuality(networkQuality);
-
- mNetworkQuality = networkQuality;
- return self();
- }
-
- /**
- * Set if a metered network is allowed.
- *
- * @param allowMetered the flag to indicate if a metered network is allowed, defaults to
- * {@code false}
- */
- @NonNull
- public T setAllowMetered(boolean allowMetered) {
- mAllowMetered = allowMetered;
- return self();
- }
-
- /** @hide */
- abstract T self();
+ @MatchCriteria
+ public int getMetered() {
+ return mMeteredMatchCriteria;
}
}
diff --git a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
index 6bbb2bfecda4..272ca9dd7583 100644
--- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
@@ -16,31 +16,59 @@
package android.net.vcn;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
+import static com.android.server.vcn.util.PersistableBundleUtils.STRING_DESERIALIZER;
+import static com.android.server.vcn.util.PersistableBundleUtils.STRING_SERIALIZER;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.net.NetworkCapabilities;
import android.os.PersistableBundle;
+import android.util.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.vcn.util.PersistableBundleUtils;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Objects;
+import java.util.Set;
-// TODO: Add documents
-/** @hide */
+/**
+ * This class represents a configuration for a network template class of underlying Carrier WiFi
+ * networks.
+ *
+ * <p>See {@link VcnUnderlyingNetworkTemplate}
+ */
public final class VcnWifiUnderlyingNetworkTemplate extends VcnUnderlyingNetworkTemplate {
- private static final String SSID_KEY = "mSsid";
- @Nullable private final String mSsid;
+ private static final String SSIDS_KEY = "mSsids";
+ @Nullable private final Set<String> mSsids;
private VcnWifiUnderlyingNetworkTemplate(
- int networkQuality, boolean allowMetered, String ssid) {
- super(NETWORK_PRIORITY_TYPE_WIFI, networkQuality, allowMetered);
- mSsid = ssid;
+ int networkQuality, int meteredMatchCriteria, Set<String> ssids) {
+ super(NETWORK_PRIORITY_TYPE_WIFI, networkQuality, meteredMatchCriteria);
+ mSsids = new ArraySet<>(ssids);
validate();
}
/** @hide */
+ @Override
+ protected void validate() {
+ super.validate();
+ validateSsids(mSsids);
+ }
+
+ private static void validateSsids(Set<String> ssids) {
+ Objects.requireNonNull(ssids, "ssids is null");
+
+ for (String ssid : ssids) {
+ Objects.requireNonNull(ssid, "found null value ssid");
+ }
+ }
+
+ /** @hide */
@NonNull
@VisibleForTesting(visibility = Visibility.PROTECTED)
public static VcnWifiUnderlyingNetworkTemplate fromPersistableBundle(
@@ -48,9 +76,14 @@ public final class VcnWifiUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
Objects.requireNonNull(in, "PersistableBundle is null");
final int networkQuality = in.getInt(NETWORK_QUALITY_KEY);
- final boolean allowMetered = in.getBoolean(ALLOW_METERED_KEY);
- final String ssid = in.getString(SSID_KEY);
- return new VcnWifiUnderlyingNetworkTemplate(networkQuality, allowMetered, ssid);
+ final int meteredMatchCriteria = in.getInt(METERED_MATCH_KEY);
+
+ final PersistableBundle ssidsBundle = in.getPersistableBundle(SSIDS_KEY);
+ Objects.requireNonNull(ssidsBundle, "ssidsBundle is null");
+ final Set<String> ssids =
+ new ArraySet<String>(
+ PersistableBundleUtils.toList(ssidsBundle, STRING_DESERIALIZER));
+ return new VcnWifiUnderlyingNetworkTemplate(networkQuality, meteredMatchCriteria, ssids);
}
/** @hide */
@@ -59,13 +92,17 @@ public final class VcnWifiUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
@VisibleForTesting(visibility = Visibility.PROTECTED)
public PersistableBundle toPersistableBundle() {
final PersistableBundle result = super.toPersistableBundle();
- result.putString(SSID_KEY, mSsid);
+
+ final PersistableBundle ssidsBundle =
+ PersistableBundleUtils.fromList(new ArrayList<>(mSsids), STRING_SERIALIZER);
+ result.putPersistableBundle(SSIDS_KEY, ssidsBundle);
+
return result;
}
@Override
public int hashCode() {
- return Objects.hash(super.hashCode(), mSsid);
+ return Objects.hash(super.hashCode(), mSsids);
}
@Override
@@ -79,49 +116,95 @@ public final class VcnWifiUnderlyingNetworkTemplate extends VcnUnderlyingNetwork
}
final VcnWifiUnderlyingNetworkTemplate rhs = (VcnWifiUnderlyingNetworkTemplate) other;
- return mSsid.equals(rhs.mSsid);
+ return mSsids.equals(rhs.mSsids);
}
/** @hide */
@Override
void dumpTransportSpecificFields(IndentingPrintWriter pw) {
- pw.println("mSsid: " + mSsid);
+ pw.println("mSsids: " + mSsids);
}
- /** Retrieve the required SSID, or {@code null} if there is no requirement on SSID. */
- @Nullable
- public String getSsid() {
- return mSsid;
+ /**
+ * Retrieve the matching SSIDs, or an empty set if any SSID is acceptable.
+ *
+ * @see Builder#setSsids(Set)
+ */
+ @NonNull
+ public Set<String> getSsids() {
+ return Collections.unmodifiableSet(mSsids);
}
/** This class is used to incrementally build VcnWifiUnderlyingNetworkTemplate objects. */
- public static class Builder extends VcnUnderlyingNetworkTemplate.Builder<Builder> {
- @Nullable private String mSsid;
+ public static final class Builder {
+ private int mNetworkQuality = NETWORK_QUALITY_ANY;
+ private int mMeteredMatchCriteria = MATCH_ANY;
+ @NonNull private final Set<String> mSsids = new ArraySet<>();
/** Construct a Builder object. */
public Builder() {}
/**
- * Set the required SSID.
+ * Set the required network quality to match this template.
*
- * @param ssid the required SSID, or {@code null} if any SSID is acceptable.
+ * <p>Network quality is a aggregation of multiple signals that reflect the network link
+ * metrics. For example, the network validation bit (see {@link
+ * NetworkCapabilities#NET_CAPABILITY_VALIDATED}), estimated first hop transport bandwidth
+ * and signal strength.
+ *
+ * @param networkQuality the required network quality. Defaults to NETWORK_QUALITY_ANY
+ * @hide
*/
@NonNull
- public Builder setSsid(@Nullable String ssid) {
- mSsid = ssid;
+ public Builder setNetworkQuality(@NetworkQuality int networkQuality) {
+ validateNetworkQuality(networkQuality);
+
+ mNetworkQuality = networkQuality;
return this;
}
- /** Build the VcnWifiUnderlyingNetworkTemplate. */
+ /**
+ * Set the matching criteria for metered networks.
+ *
+ * <p>A template where setMetered(MATCH_REQUIRED) will only match metered networks (one
+ * without NET_CAPABILITY_NOT_METERED). A template where setMetered(MATCH_FORBIDDEN) will
+ * only match a network that is not metered (one with NET_CAPABILITY_NOT_METERED).
+ *
+ * @param matchCriteria the matching criteria for metered networks. Defaults to {@link
+ * #MATCH_ANY}.
+ * @see NetworkCapabilities#NET_CAPABILITY_NOT_METERED
+ */
+ // The matching getter is defined in the super class. Please see {@link
+ // VcnUnderlyingNetworkTemplate#getMetered()}
+ @SuppressLint("MissingGetterMatchingBuilder")
@NonNull
- public VcnWifiUnderlyingNetworkTemplate build() {
- return new VcnWifiUnderlyingNetworkTemplate(mNetworkQuality, mAllowMetered, mSsid);
+ public Builder setMetered(@MatchCriteria int matchCriteria) {
+ validateMatchCriteria(matchCriteria, "setMetered");
+
+ mMeteredMatchCriteria = matchCriteria;
+ return this;
}
- /** @hide */
- @Override
- Builder self() {
+ /**
+ * Set the SSIDs with which a network can match this priority rule.
+ *
+ * @param ssids the matching SSIDs. Network with one of the matching SSIDs can match this
+ * priority rule. If the set is empty, any SSID will match. The default is an empty set.
+ */
+ @NonNull
+ public Builder setSsids(@NonNull Set<String> ssids) {
+ validateSsids(ssids);
+
+ mSsids.clear();
+ mSsids.addAll(ssids);
return this;
}
+
+ /** Build the VcnWifiUnderlyingNetworkTemplate. */
+ @NonNull
+ public VcnWifiUnderlyingNetworkTemplate build() {
+ return new VcnWifiUnderlyingNetworkTemplate(
+ mNetworkQuality, mMeteredMatchCriteria, mSsids);
+ }
}
}
diff --git a/core/java/android/nfc/BeamShareData.java b/core/java/android/nfc/BeamShareData.java
index 6a40f98fe21c..ed3b74ab6308 100644
--- a/core/java/android/nfc/BeamShareData.java
+++ b/core/java/android/nfc/BeamShareData.java
@@ -47,13 +47,13 @@ public final class BeamShareData implements Parcelable {
@Override
public BeamShareData createFromParcel(Parcel source) {
Uri[] uris = null;
- NdefMessage msg = source.readParcelable(NdefMessage.class.getClassLoader(), android.nfc.NdefMessage.class);
+ NdefMessage msg = source.readParcelable(NdefMessage.class.getClassLoader());
int numUris = source.readInt();
if (numUris > 0) {
uris = new Uri[numUris];
source.readTypedArray(uris, Uri.CREATOR);
}
- UserHandle userHandle = source.readParcelable(UserHandle.class.getClassLoader(), android.os.UserHandle.class);
+ UserHandle userHandle = source.readParcelable(UserHandle.class.getClassLoader());
int flags = source.readInt();
return new BeamShareData(msg, uris, userHandle, flags);
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 72fb4ae03a63..c62df407ca77 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -654,7 +654,7 @@ public final class Message implements Parcelable {
arg1 = source.readInt();
arg2 = source.readInt();
if (source.readInt() != 0) {
- obj = source.readParcelable(getClass().getClassLoader(), java.lang.Object.class);
+ obj = source.readParcelable(getClass().getClassLoader());
}
when = source.readLong();
data = source.readBundle();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 92d652df35d9..d4a338bef02b 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -335,6 +335,12 @@ public final class PowerManager {
public static final int USER_ACTIVITY_EVENT_FACE_DOWN = 5;
/**
+ * User activity event type: There is a change in the device state.
+ * @hide
+ */
+ public static final int USER_ACTIVITY_EVENT_DEVICE_STATE = 6;
+
+ /**
* User activity flag: If already dimmed, extend the dim timeout
* but do not brighten. This flag is useful for keeping the screen on
* a little longer without causing a visible change such as when
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 70aaa5e52c44..ebbfe47c4417 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -2993,7 +2993,7 @@ public final class StrictMode {
* should be removed.
*/
public ViolationInfo(Parcel in, boolean unsetGatheringBit) {
- mViolation = (Violation) in.readSerializable(android.os.strictmode.Violation.class.getClassLoader(), android.os.strictmode.Violation.class);
+ mViolation = (Violation) in.readSerializable();
int binderStackSize = in.readInt();
for (int i = 0; i < binderStackSize; i++) {
StackTraceElement[] traceElements = new StackTraceElement[in.readInt()];
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index b4f3fa0ae80c..edf628004728 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1657,41 +1657,49 @@ public class UserManager {
public @interface UserSwitchabilityResult {}
/**
- * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
- * user has been successfully removed.
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * the specified user has been successfully removed.
+ *
* @hide
*/
+ @SystemApi
public static final int REMOVE_RESULT_REMOVED = 0;
/**
- * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
- * user has had its {@link UserInfo#FLAG_EPHEMERAL} flag set to {@code true}, so that it will be
- * removed when the user is stopped or on boot.
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * the specified user is marked so that it will be removed when the user is stopped or on boot.
+ *
* @hide
*/
- public static final int REMOVE_RESULT_SET_EPHEMERAL = 1;
+ @SystemApi
+ public static final int REMOVE_RESULT_DEFERRED = 1;
/**
- * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified
- * user is already in the process of being removed.
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * the specified user is already in the process of being removed.
+ *
* @hide
*/
+ @SystemApi
public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2;
/**
- * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that an error occurred
- * that prevented the user from being removed or set as ephemeral.
+ * A response code from {@link #removeUserWhenPossible(UserHandle, boolean)} indicating that
+ * an error occurred that prevented the user from being removed or set as ephemeral.
+ *
* @hide
*/
+ @SystemApi
public static final int REMOVE_RESULT_ERROR = 3;
/**
- * Possible response codes from {@link #removeUserOrSetEphemeral(int)}.
+ * Possible response codes from {@link #removeUserWhenPossible(UserHandle, boolean)}.
+ *
* @hide
*/
@IntDef(prefix = { "REMOVE_RESULT_" }, value = {
REMOVE_RESULT_REMOVED,
- REMOVE_RESULT_SET_EPHEMERAL,
+ REMOVE_RESULT_DEFERRED,
REMOVE_RESULT_ALREADY_BEING_REMOVED,
REMOVE_RESULT_ERROR,
})
@@ -4728,12 +4736,42 @@ public class UserManager {
* the current user, then set the user as ephemeral so that it will be removed when it is
* stopped.
*
- * @param evenWhenDisallowed when {@code true}, user is removed even if the caller user has the
+ * @param overrideDevicePolicy when {@code true}, user is removed even if the caller has
+ * the {@link #DISALLOW_REMOVE_USER} or {@link #DISALLOW_REMOVE_MANAGED_PROFILE} restriction
+ *
+ * @return the result code {@link #REMOVE_RESULT_REMOVED}, {@link #REMOVE_RESULT_DEFERRED},
+ * {@link #REMOVE_RESULT_ALREADY_BEING_REMOVED}, or {@link #REMOVE_RESULT_ERROR}.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS})
+ public int removeUserWhenPossible(@NonNull UserHandle user,
+ boolean overrideDevicePolicy) {
+ try {
+ return mService.removeUserOrSetEphemeral(user.getIdentifier(), overrideDevicePolicy);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Immediately removes the user or, if the user cannot be removed, such as when the user is
+ * the current user, then set the user as ephemeral so that it will be removed when it is
+ * stopped.
+ *
+ * @param evenWhenDisallowed when {@code true}, user is removed even if the caller has the
* {@link #DISALLOW_REMOVE_USER} or {@link #DISALLOW_REMOVE_MANAGED_PROFILE} restriction
*
* @return the {@link RemoveResult} code
+ *
+ * @deprecated TODO(b/199446770): remove this call after converting all calls to
+ * removeUserWhenPossible(UserHandle, boolean)
+ *
* @hide
*/
+ @Deprecated
@RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
Manifest.permission.CREATE_USERS})
public @RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId,
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index 58315736f37f..8834725cc3e9 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -32,32 +32,30 @@ import java.util.Objects;
public final class VibrationAttributes implements Parcelable {
private static final String TAG = "VibrationAttributes";
- /**
- * @hide
- */
+ /** @hide */
@IntDef(prefix = { "USAGE_CLASS_" }, value = {
USAGE_CLASS_UNKNOWN,
USAGE_CLASS_ALARM,
USAGE_CLASS_FEEDBACK,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface UsageClass{}
+ public @interface UsageClass {}
- /**
- * @hide
- */
+ /** @hide */
@IntDef(prefix = { "USAGE_" }, value = {
USAGE_UNKNOWN,
+ USAGE_ACCESSIBILITY,
USAGE_ALARM,
- USAGE_RINGTONE,
- USAGE_NOTIFICATION,
USAGE_COMMUNICATION_REQUEST,
- USAGE_TOUCH,
- USAGE_PHYSICAL_EMULATION,
USAGE_HARDWARE_FEEDBACK,
+ USAGE_MEDIA,
+ USAGE_NOTIFICATION,
+ USAGE_PHYSICAL_EMULATION,
+ USAGE_RINGTONE,
+ USAGE_TOUCH,
})
@Retention(RetentionPolicy.SOURCE)
- public @interface Usage{}
+ public @interface Usage {}
/**
* Vibration usage filter value to match all usages.
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 41ab062ee822..5de455695c01 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -260,7 +260,7 @@ public abstract class VibrationEffect implements Parcelable {
for (int i = 0; i < timings.length; i++) {
float parsedAmplitude = amplitudes[i] == DEFAULT_AMPLITUDE
? DEFAULT_AMPLITUDE : (float) amplitudes[i] / MAX_AMPLITUDE;
- segments.add(new StepSegment(parsedAmplitude, /* frequency= */ 0, (int) timings[i]));
+ segments.add(new StepSegment(parsedAmplitude, /* frequencyHz= */ 0, (int) timings[i]));
}
VibrationEffect effect = new Composed(segments, repeat);
effect.validate();
@@ -576,7 +576,7 @@ public abstract class VibrationEffect implements Parcelable {
private final int mRepeatIndex;
Composed(@NonNull Parcel in) {
- this(in.readArrayList(VibrationEffectSegment.class.getClassLoader(), android.os.vibrator.VibrationEffectSegment.class), in.readInt());
+ this(in.readArrayList(VibrationEffectSegment.class.getClassLoader()), in.readInt());
}
Composed(@NonNull VibrationEffectSegment segment) {
@@ -866,7 +866,7 @@ public abstract class VibrationEffect implements Parcelable {
Preconditions.checkArgumentNonnegative(delay);
if (delay > 0) {
// Created a segment sustaining the zero amplitude to represent the delay.
- addSegment(new StepSegment(/* amplitude= */ 0, /* frequency= */ 0,
+ addSegment(new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0,
/* duration= */ delay));
}
return addSegments(effect);
@@ -1033,26 +1033,27 @@ public abstract class VibrationEffect implements Parcelable {
@NonNull
public WaveformBuilder addStep(@FloatRange(from = 0f, to = 1f) float amplitude,
@IntRange(from = 0) int duration) {
- return addStep(amplitude, getPreviousFrequency(), duration);
+ mSegments.add(new StepSegment(amplitude, getPreviousFrequencyHz(), duration));
+ return this;
}
/**
- * Vibrate with given amplitude for the given duration, in millis, keeping the previous
- * vibration frequency the same.
+ * Vibrate with given amplitude and frequency for the given duration, in millis.
*
* <p>If the duration is zero the vibrator will jump to new amplitude.
*
* @param amplitude The amplitude for this step
- * @param frequency The frequency for this step
+ * @param frequencyHz The frequency for this step, in hertz
* @param duration The duration of this step in milliseconds
* @return The {@link WaveformBuilder} object to enable adding multiple steps in chain.
*/
@SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public WaveformBuilder addStep(@FloatRange(from = 0f, to = 1f) float amplitude,
- @FloatRange(from = -1f, to = 1f) float frequency,
+ @FloatRange(from = 1f) float frequencyHz,
@IntRange(from = 0) int duration) {
- mSegments.add(new StepSegment(amplitude, frequency, duration));
+ Preconditions.checkArgument(frequencyHz >= 1, "Frequency must be >= 1");
+ mSegments.add(new StepSegment(amplitude, frequencyHz, duration));
return this;
}
@@ -1070,7 +1071,9 @@ public abstract class VibrationEffect implements Parcelable {
@NonNull
public WaveformBuilder addRamp(@FloatRange(from = 0f, to = 1f) float amplitude,
@IntRange(from = 0) int duration) {
- return addRamp(amplitude, getPreviousFrequency(), duration);
+ mSegments.add(new RampSegment(getPreviousAmplitude(), amplitude,
+ getPreviousFrequencyHz(), getPreviousFrequencyHz(), duration));
+ return this;
}
/**
@@ -1080,22 +1083,23 @@ public abstract class VibrationEffect implements Parcelable {
* <p>If the duration is zero the vibrator will jump to new amplitude and frequency.
*
* @param amplitude The final amplitude this ramp should reach
- * @param frequency The final frequency this ramp should reach
+ * @param frequencyHz The final frequency this ramp should reach, in hertz
* @param duration The duration of this ramp in milliseconds
* @return The {@link WaveformBuilder} object to enable adding multiple steps in chain.
*/
@SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public WaveformBuilder addRamp(@FloatRange(from = 0f, to = 1f) float amplitude,
- @FloatRange(from = -1f, to = 1f) float frequency,
+ @FloatRange(from = 1f) float frequencyHz,
@IntRange(from = 0) int duration) {
- mSegments.add(new RampSegment(getPreviousAmplitude(), amplitude, getPreviousFrequency(),
- frequency, duration));
+ Preconditions.checkArgument(frequencyHz >= 1, "Frequency must be >= 1");
+ mSegments.add(new RampSegment(getPreviousAmplitude(), amplitude,
+ getPreviousFrequencyHz(), frequencyHz, duration));
return this;
}
/**
- * Compose all of the steps together into a single {@link VibrationEffect}.
+ * Compose all the steps together into a single {@link VibrationEffect}.
*
* The {@link WaveformBuilder} object is still valid after this call, so you can
* continue adding more primitives to it and generating more {@link VibrationEffect}s by
@@ -1109,7 +1113,7 @@ public abstract class VibrationEffect implements Parcelable {
}
/**
- * Compose all of the steps together into a single {@link VibrationEffect}.
+ * Compose all the steps together into a single {@link VibrationEffect}.
*
* <p>To cause the pattern to repeat, pass the index at which to start the repetition
* (starting at 0), or -1 to disable repeating.
@@ -1131,13 +1135,13 @@ public abstract class VibrationEffect implements Parcelable {
return effect;
}
- private float getPreviousFrequency() {
+ private float getPreviousFrequencyHz() {
if (!mSegments.isEmpty()) {
VibrationEffectSegment segment = mSegments.get(mSegments.size() - 1);
if (segment instanceof StepSegment) {
- return ((StepSegment) segment).getFrequency();
+ return ((StepSegment) segment).getFrequencyHz();
} else if (segment instanceof RampSegment) {
- return ((RampSegment) segment).getEndFrequency();
+ return ((RampSegment) segment).getEndFrequencyHz();
}
}
return 0;
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index c67c82e37cd2..eba9ff1bb4f8 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -17,20 +17,21 @@
package android.os;
import android.annotation.CallbackExecutor;
-import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.res.Resources;
import android.hardware.vibrator.IVibrator;
import android.media.AudioAttributes;
+import android.os.vibrator.VibrationConfig;
import android.util.Log;
-import android.util.Range;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -51,6 +52,7 @@ public abstract class Vibrator {
*
* @hide
*/
+ @TestApi
public static final int VIBRATION_INTENSITY_OFF = 0;
/**
@@ -58,6 +60,7 @@ public abstract class Vibrator {
*
* @hide
*/
+ @TestApi
public static final int VIBRATION_INTENSITY_LOW = 1;
/**
@@ -65,6 +68,7 @@ public abstract class Vibrator {
*
* @hide
*/
+ @TestApi
public static final int VIBRATION_INTENSITY_MEDIUM = 2;
/**
@@ -72,6 +76,7 @@ public abstract class Vibrator {
*
* @hide
*/
+ @TestApi
public static final int VIBRATION_INTENSITY_HIGH = 3;
/**
@@ -117,16 +122,12 @@ public abstract class Vibrator {
}
private final String mPackageName;
- // The default vibration intensity level for haptic feedback.
- @VibrationIntensity
- private int mDefaultHapticFeedbackIntensity;
- // The default vibration intensity level for notifications.
- @VibrationIntensity
- private int mDefaultNotificationVibrationIntensity;
- // The default vibration intensity level for ringtones.
- @VibrationIntensity
- private int mDefaultRingVibrationIntensity;
- private float mHapticChannelMaxVibrationAmplitude;
+ @Nullable
+ private final Resources mResources;
+
+ // This is lazily loaded only for the few clients that need this (e. Settings app).
+ @Nullable
+ private volatile VibrationConfig mVibrationConfig;
/**
* @hide to prevent subclassing from outside of the framework
@@ -134,8 +135,7 @@ public abstract class Vibrator {
@UnsupportedAppUsage
public Vibrator() {
mPackageName = ActivityThread.currentPackageName();
- final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
- loadVibrationConfig(ctx);
+ mResources = null;
}
/**
@@ -143,26 +143,7 @@ public abstract class Vibrator {
*/
protected Vibrator(Context context) {
mPackageName = context.getOpPackageName();
- loadVibrationConfig(context);
- }
-
- private void loadVibrationConfig(Context context) {
- mDefaultHapticFeedbackIntensity = loadDefaultIntensity(context,
- com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
- mDefaultNotificationVibrationIntensity = loadDefaultIntensity(context,
- com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
- mDefaultRingVibrationIntensity = loadDefaultIntensity(context,
- com.android.internal.R.integer.config_defaultRingVibrationIntensity);
- mHapticChannelMaxVibrationAmplitude = loadFloat(context,
- com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude, 0);
- }
-
- private int loadDefaultIntensity(Context ctx, int resId) {
- return ctx != null ? ctx.getResources().getInteger(resId) : VIBRATION_INTENSITY_MEDIUM;
- }
-
- private float loadFloat(Context ctx, int resId, float defaultValue) {
- return ctx != null ? ctx.getResources().getFloat(resId) : defaultValue;
+ mResources = context.getResources();
}
/**
@@ -174,31 +155,30 @@ public abstract class Vibrator {
return VibratorInfo.EMPTY_VIBRATOR_INFO;
}
- /**
- * Get the default vibration intensity for haptic feedback.
- *
- * @hide
- */
- public int getDefaultHapticFeedbackIntensity() {
- return mDefaultHapticFeedbackIntensity;
- }
-
- /**
- * Get the default vibration intensity for notifications.
- *
- * @hide
- */
- public int getDefaultNotificationVibrationIntensity() {
- return mDefaultNotificationVibrationIntensity;
+ /** Get the static vibrator configuration from config.xml. */
+ private VibrationConfig getConfig() {
+ if (mVibrationConfig == null) {
+ Resources resources = mResources;
+ if (resources == null) {
+ final Context ctx = ActivityThread.currentActivityThread().getSystemContext();
+ resources = ctx != null ? ctx.getResources() : null;
+ }
+ // This might be constructed more than once, but it only loads static config data from a
+ // xml file, so it would be ok.
+ mVibrationConfig = new VibrationConfig(resources);
+ }
+ return mVibrationConfig;
}
/**
- * Get the default vibration intensity for ringtones.
+ * Get the default vibration intensity for given usage.
*
* @hide
*/
- public int getDefaultRingVibrationIntensity() {
- return mDefaultRingVibrationIntensity;
+ @TestApi
+ @VibrationIntensity
+ public int getDefaultVibrationIntensity(@VibrationAttributes.Usage int usage) {
+ return getConfig().getDefaultVibrationIntensity(usage);
}
/**
@@ -271,43 +251,6 @@ public abstract class Vibrator {
}
/**
- * Return a range of relative frequency values supported by the vibrator.
- *
- * <p>These values can be used to create waveforms that controls the vibration frequency via
- * {@link VibrationEffect.WaveformBuilder}.
- *
- * @return A range of relative frequency values supported. The range will always contain the
- * value 0, representing the device resonant frequency. Devices without frequency control will
- * return the range [0,0]. Devices with frequency control will always return a range containing
- * the safe range [-1, 1].
- * @hide
- */
- public Range<Float> getRelativeFrequencyRange() {
- return getInfo().getFrequencyRange();
- }
-
- /**
- * Return the maximum amplitude the vibrator can play at given relative frequency.
- *
- * <p>Devices without frequency control will return 1 for the input zero (resonant frequency),
- * and 0 to any other input.
- *
- * <p>Devices with frequency control will return the supported value, for input in
- * {@link #getRelativeFrequencyRange()}, and 0 for any other input.
- *
- * <p>These values can be used to create waveforms that plays vibrations outside the resonant
- * frequency via {@link VibrationEffect.WaveformBuilder}.
- *
- * @return a value in [0,1] representing the maximum amplitude the device can play at given
- * relative frequency.
- * @hide
- */
- @FloatRange(from = 0, to = 1)
- public float getMaximumAmplitude(float relativeFrequency) {
- return getInfo().getMaxAmplitude(relativeFrequency);
- }
-
- /**
* Return the maximum amplitude the vibrator can play using the audio haptic channels.
*
* <p>This is a positive value, or {@link Float#NaN NaN} if it's unknown. If this returns a
@@ -319,10 +262,7 @@ public abstract class Vibrator {
* @hide
*/
public float getHapticChannelMaximumAmplitude() {
- if (mHapticChannelMaxVibrationAmplitude <= 0) {
- return Float.NaN;
- }
- return mHapticChannelMaxVibrationAmplitude;
+ return getConfig().getHapticChannelMaximumAmplitude();
}
/**
diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java
index 0a0e3c82f4ad..189e454f1488 100644
--- a/core/java/android/os/VibratorInfo.java
+++ b/core/java/android/os/VibratorInfo.java
@@ -21,7 +21,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.vibrator.Braking;
import android.hardware.vibrator.IVibrator;
-import android.util.Log;
import android.util.MathUtils;
import android.util.Range;
import android.util.SparseBooleanArray;
@@ -70,7 +69,7 @@ public class VibratorInfo implements Parcelable {
mPwlePrimitiveDurationMax = in.readInt();
mPwleSizeMax = in.readInt();
mQFactor = in.readFloat();
- mFrequencyMapping = in.readParcelable(VibratorInfo.class.getClassLoader(), android.os.VibratorInfo.FrequencyMapping.class);
+ mFrequencyMapping = in.readParcelable(VibratorInfo.class.getClassLoader());
}
/**
@@ -345,49 +344,31 @@ public class VibratorInfo implements Parcelable {
}
/**
- * Return a range of relative frequency values supported by the vibrator.
+ * Return a range of frequency values supported by the vibrator.
*
- * @return A range of relative frequency values supported. The range will always contain the
- * value 0, representing the device resonant frequency. Devices without frequency control will
- * return the range [0,0]. Devices with frequency control will always return a range containing
- * the safe range [-1, 1].
+ * @return A range of frequency values supported, in hertz. The range will always contain the
+ * device resonant frequency. Devices without frequency control will return null.
* @hide
*/
- public Range<Float> getFrequencyRange() {
- return mFrequencyMapping.mRelativeFrequencyRange;
+ @Nullable
+ public Range<Float> getFrequencyRangeHz() {
+ return mFrequencyMapping.mFrequencyRangeHz;
}
/**
- * Return the maximum amplitude the vibrator can play at given relative frequency.
+ * Return the maximum amplitude the vibrator can play at given frequency.
*
+ * @param frequencyHz The frequency, in hertz, for query.
+
* @return a value in [0,1] representing the maximum amplitude the device can play at given
- * relative frequency. Devices without frequency control will return 1 for the input zero
- * (resonant frequency), and 0 to any other input. Devices with frequency control will return
- * the supported value, for input in {@code #getFrequencyRange()}, and 0 for any other input.
+ * frequency. Devices without frequency control will return 0 to any input. Devices with
+ * frequency control will return the supported value, for input in
+ * {@link #getFrequencyRangeHz()}, and 0 for any other input.
* @hide
*/
@FloatRange(from = 0, to = 1)
- public float getMaxAmplitude(float relativeFrequency) {
- if (mFrequencyMapping.isEmpty()) {
- // The vibrator has not provided values for frequency mapping.
- // Return the expected behavior for devices without frequency control.
- return Float.compare(relativeFrequency, 0) == 0 ? 1 : 0;
- }
- return mFrequencyMapping.getMaxAmplitude(relativeFrequency);
- }
-
- /**
- * Return absolute frequency value for this vibrator, in hertz, that corresponds to given
- * relative frequency.
- *
- * @retur a value in hertz that corresponds to given relative frequency. Input values outside
- * {@link #getFrequencyRange()} will return {@link Float#NaN}. Devices without frequency control
- * will return {@link Float#NaN} for any input.
- * @hide
- */
- @FloatRange(from = 0)
- public float getAbsoluteFrequency(float relativeFrequency) {
- return mFrequencyMapping.toHertz(relativeFrequency);
+ public float getMaxAmplitude(float frequencyHz) {
+ return mFrequencyMapping.getMaxAmplitude(frequencyHz);
}
protected long getCapabilities() {
@@ -468,134 +449,96 @@ public class VibratorInfo implements Parcelable {
}
/**
- * Describes how frequency should be mapped to absolute values for a specific {@link Vibrator}.
+ * Describes the maximum relative output acceleration that can be achieved for each supported
+ * frequency in a specific vibrator.
*
* <p>This mapping is defined by the following parameters:
*
* <ol>
- * <li>{@code minFrequency}, {@code resonantFrequency} and {@code frequencyResolution}, in
- * hertz, provided by the vibrator.
+ * <li>{@code minFrequencyHz}, {@code resonantFrequencyHz} and {@code frequencyResolutionHz}
+ * provided by the vibrator in hertz.
* <li>{@code maxAmplitudes} a list of values in [0,1] provided by the vibrator, where
* {@code maxAmplitudes[i]} represents max supported amplitude at frequency
- * {@code minFrequency + frequencyResolution * i}.
- * <li>{@code maxFrequency = minFrequency + frequencyResolution * (maxAmplitudes.length-1)}
- * <li>{@code suggestedSafeRangeHz} is the suggested frequency range in hertz that should be
- * mapped to relative values -1 and 1, where 0 maps to {@code resonantFrequency}.
- * </ol>
- *
- * <p>The mapping is defined linearly by the following points:
- *
- * <ol>
- * <li>{@code toHertz(relativeMinFrequency) = minFrequency}
- * <li>{@code toHertz(-1) = resonantFrequency - safeRange / 2}
- * <li>{@code toHertz(0) = resonantFrequency}
- * <li>{@code toHertz(1) = resonantFrequency + safeRange / 2}
- * <li>{@code toHertz(relativeMaxFrequency) = maxFrequency}
+ * {@code minFrequencyHz + frequencyResolutionHz * i}.
+ * <li>{@code maxFrequencyHz = minFrequencyHz
+ * + frequencyResolutionHz * (maxAmplitudes.length-1)}
* </ol>
*
* @hide
*/
public static final class FrequencyMapping implements Parcelable {
+ @Nullable
+ private final Range<Float> mFrequencyRangeHz;
private final float mMinFrequencyHz;
private final float mResonantFrequencyHz;
private final float mFrequencyResolutionHz;
- private final float mSuggestedSafeRangeHz;
private final float[] mMaxAmplitudes;
- // Relative fields calculated from input values:
- private final Range<Float> mRelativeFrequencyRange;
-
FrequencyMapping(Parcel in) {
- this(in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat(),
- in.createFloatArray());
+ this(in.readFloat(), in.readFloat(), in.readFloat(), in.createFloatArray());
}
/**
* Default constructor.
*
- * @param minFrequencyHz Minimum supported frequency, in hertz.
* @param resonantFrequencyHz The vibrator resonant frequency, in hertz.
+ * @param minFrequencyHz Minimum supported frequency, in hertz.
* @param frequencyResolutionHz The frequency resolution, in hertz, used by the max
* amplitudes mapping.
- * @param suggestedSafeRangeHz The suggested range, in hertz, for the safe relative
- * frequency range represented by [-1, 1].
* @param maxAmplitudes The max amplitude supported by each supported frequency,
* starting at minimum frequency with jumps of frequency
* resolution.
* @hide
*/
- public FrequencyMapping(float minFrequencyHz, float resonantFrequencyHz,
- float frequencyResolutionHz, float suggestedSafeRangeHz, float[] maxAmplitudes) {
+ public FrequencyMapping(float resonantFrequencyHz, float minFrequencyHz,
+ float frequencyResolutionHz, float[] maxAmplitudes) {
mMinFrequencyHz = minFrequencyHz;
mResonantFrequencyHz = resonantFrequencyHz;
mFrequencyResolutionHz = frequencyResolutionHz;
- mSuggestedSafeRangeHz = suggestedSafeRangeHz;
mMaxAmplitudes = new float[maxAmplitudes == null ? 0 : maxAmplitudes.length];
if (maxAmplitudes != null) {
System.arraycopy(maxAmplitudes, 0, mMaxAmplitudes, 0, maxAmplitudes.length);
}
- float maxFrequencyHz =
- minFrequencyHz + frequencyResolutionHz * (mMaxAmplitudes.length - 1);
- if (Float.isNaN(resonantFrequencyHz) || Float.isNaN(minFrequencyHz)
- || Float.isNaN(frequencyResolutionHz) || Float.isNaN(suggestedSafeRangeHz)
- || resonantFrequencyHz < minFrequencyHz
- || resonantFrequencyHz > maxFrequencyHz) {
- // Some required fields are undefined or have bad values.
- // Leave this mapping empty.
- mRelativeFrequencyRange = Range.create(0f, 0f);
- return;
- }
+ // If any required field is undefined then leave this mapping empty.
+ boolean isValid = !Float.isNaN(resonantFrequencyHz)
+ && !Float.isNaN(minFrequencyHz)
+ && !Float.isNaN(frequencyResolutionHz)
+ && (mMaxAmplitudes.length > 0);
- // Calculate actual safe range, limiting the suggested one by the device supported range
- float safeDelta = MathUtils.min(
- suggestedSafeRangeHz / 2,
- resonantFrequencyHz - minFrequencyHz,
- maxFrequencyHz - resonantFrequencyHz);
- mRelativeFrequencyRange = Range.create(
- (minFrequencyHz - resonantFrequencyHz) / safeDelta,
- (maxFrequencyHz - resonantFrequencyHz) / safeDelta);
- }
+ float maxFrequencyHz = isValid
+ ? minFrequencyHz + frequencyResolutionHz * (mMaxAmplitudes.length - 1)
+ : Float.NaN;
- /**
- * Returns true if this frequency mapping is empty, i.e. the only supported relative
- * frequency is 0 (resonant frequency).
- */
- public boolean isEmpty() {
- return Float.compare(mRelativeFrequencyRange.getLower(),
- mRelativeFrequencyRange.getUpper()) == 0;
+ // If the non-empty mapping does not have min < resonant < max frequency respected
+ // then leave this mapping empty.
+ isValid &= !Float.isNaN(maxFrequencyHz)
+ && (resonantFrequencyHz >= minFrequencyHz)
+ && (resonantFrequencyHz <= maxFrequencyHz)
+ && (minFrequencyHz < maxFrequencyHz);
+
+ mFrequencyRangeHz = isValid ? Range.create(minFrequencyHz, maxFrequencyHz) : null;
}
/**
- * Returns the frequency value in hertz that is mapped to the given relative frequency.
- *
- * @return The mapped frequency, in hertz, or {@link Float#NaN} is value outside the device
- * supported range.
+ * Returns true if this frequency mapping is empty, i.e. the only supported is the resonant
+ * frequency.
*/
- public float toHertz(float relativeFrequency) {
- if (!mRelativeFrequencyRange.contains(relativeFrequency)) {
- return Float.NaN;
- }
- float relativeMinFrequency = mRelativeFrequencyRange.getLower();
- if (Float.compare(relativeMinFrequency, 0) == 0) {
- // relative supported range is [0,0], so toHertz(0) should be the resonant frequency
- return mResonantFrequencyHz;
- }
- float shift = (mMinFrequencyHz - mResonantFrequencyHz) / relativeMinFrequency;
- return mResonantFrequencyHz + relativeFrequency * shift;
+ public boolean isEmpty() {
+ return mFrequencyRangeHz == null;
}
/**
- * Returns the maximum amplitude the vibrator can reach while playing at given relative
- * frequency.
+ * Returns the maximum relative amplitude the vibrator can reach while playing at the
+ * given frequency.
*
- * @return A value in [0,1] representing the max amplitude supported at given relative
- * frequency. This will return 0 if frequency is outside supported range, or if max
- * amplitude mapping is empty.
+ * @param frequencyHz frequency, in hertz, for query.
+ * @return A value in [0,1] representing the max relative amplitude supported at the given
+ * frequency. This will return 0 if the frequency is outside the supported range, or if the
+ * mapping is empty.
*/
- public float getMaxAmplitude(float relativeFrequency) {
- float frequencyHz = toHertz(relativeFrequency);
- if (Float.isNaN(frequencyHz)) {
+ public float getMaxAmplitude(float frequencyHz) {
+ if (isEmpty() || Float.isNaN(frequencyHz)) {
// Unsupported frequency requested, vibrator cannot play at this frequency.
return 0;
}
@@ -603,13 +546,6 @@ public class VibratorInfo implements Parcelable {
int floorIndex = (int) Math.floor(position);
int ceilIndex = (int) Math.ceil(position);
if (floorIndex < 0 || floorIndex >= mMaxAmplitudes.length) {
- if (mMaxAmplitudes.length > 0) {
- // This should never happen if the setup of relative frequencies was correct.
- Log.w(TAG, "Max amplitudes has " + mMaxAmplitudes.length
- + " entries and was expected to cover the frequency " + frequencyHz
- + " Hz when starting at min frequency of " + mMinFrequencyHz
- + " Hz with resolution of " + mFrequencyResolutionHz + " Hz.");
- }
return 0;
}
if (floorIndex != ceilIndex && ceilIndex < mMaxAmplitudes.length) {
@@ -621,10 +557,9 @@ public class VibratorInfo implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeFloat(mMinFrequencyHz);
dest.writeFloat(mResonantFrequencyHz);
+ dest.writeFloat(mMinFrequencyHz);
dest.writeFloat(mFrequencyResolutionHz);
- dest.writeFloat(mSuggestedSafeRangeHz);
dest.writeFloatArray(mMaxAmplitudes);
}
@@ -645,14 +580,13 @@ public class VibratorInfo implements Parcelable {
return Float.compare(mMinFrequencyHz, that.mMinFrequencyHz) == 0
&& Float.compare(mResonantFrequencyHz, that.mResonantFrequencyHz) == 0
&& Float.compare(mFrequencyResolutionHz, that.mFrequencyResolutionHz) == 0
- && Float.compare(mSuggestedSafeRangeHz, that.mSuggestedSafeRangeHz) == 0
&& Arrays.equals(mMaxAmplitudes, that.mMaxAmplitudes);
}
@Override
public int hashCode() {
int hashCode = Objects.hash(mMinFrequencyHz, mFrequencyResolutionHz,
- mFrequencyResolutionHz, mSuggestedSafeRangeHz);
+ mFrequencyResolutionHz);
hashCode = 31 * hashCode + Arrays.hashCode(mMaxAmplitudes);
return hashCode;
}
@@ -660,13 +594,10 @@ public class VibratorInfo implements Parcelable {
@Override
public String toString() {
return "FrequencyMapping{"
- + "mRelativeFrequencyRange=" + mRelativeFrequencyRange
+ + "mFrequencyRange=" + mFrequencyRangeHz
+ ", mMinFrequency=" + mMinFrequencyHz
+ ", mResonantFrequency=" + mResonantFrequencyHz
- + ", mMaxFrequency="
- + (mMinFrequencyHz + mFrequencyResolutionHz * (mMaxAmplitudes.length - 1))
+ ", mFrequencyResolution=" + mFrequencyResolutionHz
- + ", mSuggestedSafeRange=" + mSuggestedSafeRangeHz
+ ", mMaxAmplitudes count=" + mMaxAmplitudes.length
+ '}';
}
@@ -699,7 +630,7 @@ public class VibratorInfo implements Parcelable {
private int mPwleSizeMax;
private float mQFactor = Float.NaN;
private FrequencyMapping mFrequencyMapping =
- new FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, Float.NaN, null);
+ new FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, null);
/** A builder class for a {@link VibratorInfo}. */
public Builder(int id) {
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index e899f7729efa..6588b5748d09 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -130,7 +130,7 @@ public class WorkSource implements Parcelable {
int numChains = in.readInt();
if (numChains > 0) {
mChains = new ArrayList<>(numChains);
- in.readParcelableList(mChains, WorkChain.class.getClassLoader(), android.os.WorkSource.WorkChain.class);
+ in.readParcelableList(mChains, WorkChain.class.getClassLoader());
} else {
mChains = null;
}
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 8ee52c21e869..b78bb253bcf7 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -168,7 +168,7 @@ public final class StorageVolume implements Parcelable {
mExternallyManaged = in.readInt() != 0;
mAllowMassStorage = in.readInt() != 0;
mMaxFileSize = in.readLong();
- mOwner = in.readParcelable(null, android.os.UserHandle.class);
+ mOwner = in.readParcelable(null);
if (in.readInt() != 0) {
mUuid = StorageManager.convert(in.readString8());
} else {
diff --git a/core/java/android/os/vibrator/RampSegment.java b/core/java/android/os/vibrator/RampSegment.java
index 3ec56366d921..9e1f6360b090 100644
--- a/core/java/android/os/vibrator/RampSegment.java
+++ b/core/java/android/os/vibrator/RampSegment.java
@@ -29,14 +29,20 @@ import java.util.Objects;
* Representation of {@link VibrationEffectSegment} that ramps vibration amplitude and/or frequency
* for a specified duration.
*
+ * <p>The amplitudes are expressed by float values in the range [0, 1], representing the relative
+ * output acceleration for the vibrator. The frequencies are expressed in hertz by positive finite
+ * float values. The special value zero is used here for an unspecified frequency, and will be
+ * automatically mapped to the device's default vibration frequency (usually the resonant
+ * frequency).
+ *
* @hide
*/
@TestApi
public final class RampSegment extends VibrationEffectSegment {
private final float mStartAmplitude;
- private final float mStartFrequency;
+ private final float mStartFrequencyHz;
private final float mEndAmplitude;
- private final float mEndFrequency;
+ private final float mEndFrequencyHz;
private final int mDuration;
RampSegment(@NonNull Parcel in) {
@@ -44,12 +50,12 @@ public final class RampSegment extends VibrationEffectSegment {
}
/** @hide */
- public RampSegment(float startAmplitude, float endAmplitude, float startFrequency,
- float endFrequency, int duration) {
+ public RampSegment(float startAmplitude, float endAmplitude, float startFrequencyHz,
+ float endFrequencyHz, int duration) {
mStartAmplitude = startAmplitude;
mEndAmplitude = endAmplitude;
- mStartFrequency = startFrequency;
- mEndFrequency = endFrequency;
+ mStartFrequencyHz = startFrequencyHz;
+ mEndFrequencyHz = endFrequencyHz;
mDuration = duration;
}
@@ -61,8 +67,8 @@ public final class RampSegment extends VibrationEffectSegment {
RampSegment other = (RampSegment) o;
return Float.compare(mStartAmplitude, other.mStartAmplitude) == 0
&& Float.compare(mEndAmplitude, other.mEndAmplitude) == 0
- && Float.compare(mStartFrequency, other.mStartFrequency) == 0
- && Float.compare(mEndFrequency, other.mEndFrequency) == 0
+ && Float.compare(mStartFrequencyHz, other.mStartFrequencyHz) == 0
+ && Float.compare(mEndFrequencyHz, other.mEndFrequencyHz) == 0
&& mDuration == other.mDuration;
}
@@ -74,12 +80,12 @@ public final class RampSegment extends VibrationEffectSegment {
return mEndAmplitude;
}
- public float getStartFrequency() {
- return mStartFrequency;
+ public float getStartFrequencyHz() {
+ return mStartFrequencyHz;
}
- public float getEndFrequency() {
- return mEndFrequency;
+ public float getEndFrequencyHz() {
+ return mEndFrequencyHz;
}
@Override
@@ -102,6 +108,12 @@ public final class RampSegment extends VibrationEffectSegment {
/** @hide */
@Override
public void validate() {
+ Preconditions.checkArgumentNonNegative(mStartFrequencyHz,
+ "Frequencies must all be >= 0, got start frequency of " + mStartFrequencyHz);
+ Preconditions.checkArgumentFinite(mStartFrequencyHz, "startFrequencyHz");
+ Preconditions.checkArgumentNonNegative(mEndFrequencyHz,
+ "Frequencies must all be >= 0, got end frequency of " + mEndFrequencyHz);
+ Preconditions.checkArgumentFinite(mEndFrequencyHz, "endFrequencyHz");
Preconditions.checkArgumentNonnegative(mDuration,
"Durations must all be >= 0, got " + mDuration);
Preconditions.checkArgumentInRange(mStartAmplitude, 0f, 1f, "startAmplitude");
@@ -126,7 +138,8 @@ public final class RampSegment extends VibrationEffectSegment {
&& Float.compare(mEndAmplitude, newEndAmplitude) == 0) {
return this;
}
- return new RampSegment(newStartAmplitude, newEndAmplitude, mStartFrequency, mEndFrequency,
+ return new RampSegment(newStartAmplitude, newEndAmplitude, mStartFrequencyHz,
+ mEndFrequencyHz,
mDuration);
}
@@ -139,7 +152,7 @@ public final class RampSegment extends VibrationEffectSegment {
@Override
public int hashCode() {
- return Objects.hash(mStartAmplitude, mEndAmplitude, mStartFrequency, mEndFrequency,
+ return Objects.hash(mStartAmplitude, mEndAmplitude, mStartFrequencyHz, mEndFrequencyHz,
mDuration);
}
@@ -147,8 +160,8 @@ public final class RampSegment extends VibrationEffectSegment {
public String toString() {
return "Ramp{startAmplitude=" + mStartAmplitude
+ ", endAmplitude=" + mEndAmplitude
- + ", startFrequency=" + mStartFrequency
- + ", endFrequency=" + mEndFrequency
+ + ", startFrequencyHz=" + mStartFrequencyHz
+ + ", endFrequencyHz=" + mEndFrequencyHz
+ ", duration=" + mDuration
+ "}";
}
@@ -163,8 +176,8 @@ public final class RampSegment extends VibrationEffectSegment {
out.writeInt(PARCEL_TOKEN_RAMP);
out.writeFloat(mStartAmplitude);
out.writeFloat(mEndAmplitude);
- out.writeFloat(mStartFrequency);
- out.writeFloat(mEndFrequency);
+ out.writeFloat(mStartFrequencyHz);
+ out.writeFloat(mEndFrequencyHz);
out.writeInt(mDuration);
}
diff --git a/core/java/android/os/vibrator/StepSegment.java b/core/java/android/os/vibrator/StepSegment.java
index 69a381f5c558..c6795111d496 100644
--- a/core/java/android/os/vibrator/StepSegment.java
+++ b/core/java/android/os/vibrator/StepSegment.java
@@ -30,12 +30,18 @@ import java.util.Objects;
* Representation of {@link VibrationEffectSegment} that holds a fixed vibration amplitude and
* frequency for a specified duration.
*
+ * <p>The amplitude is expressed by a float value in the range [0, 1], representing the relative
+ * output acceleration for the vibrator. The frequency is expressed in hertz by a positive finite
+ * float value. The special value zero is used here for an unspecified frequency, and will be
+ * automatically mapped to the device's default vibration frequency (usually the resonant
+ * frequency).
+ *
* @hide
*/
@TestApi
public final class StepSegment extends VibrationEffectSegment {
private final float mAmplitude;
- private final float mFrequency;
+ private final float mFrequencyHz;
private final int mDuration;
StepSegment(@NonNull Parcel in) {
@@ -43,9 +49,9 @@ public final class StepSegment extends VibrationEffectSegment {
}
/** @hide */
- public StepSegment(float amplitude, float frequency, int duration) {
+ public StepSegment(float amplitude, float frequencyHz, int duration) {
mAmplitude = amplitude;
- mFrequency = frequency;
+ mFrequencyHz = frequencyHz;
mDuration = duration;
}
@@ -56,7 +62,7 @@ public final class StepSegment extends VibrationEffectSegment {
}
StepSegment other = (StepSegment) o;
return Float.compare(mAmplitude, other.mAmplitude) == 0
- && Float.compare(mFrequency, other.mFrequency) == 0
+ && Float.compare(mFrequencyHz, other.mFrequencyHz) == 0
&& mDuration == other.mDuration;
}
@@ -64,8 +70,8 @@ public final class StepSegment extends VibrationEffectSegment {
return mAmplitude;
}
- public float getFrequency() {
- return mFrequency;
+ public float getFrequencyHz() {
+ return mFrequencyHz;
}
@Override
@@ -89,6 +95,9 @@ public final class StepSegment extends VibrationEffectSegment {
/** @hide */
@Override
public void validate() {
+ Preconditions.checkArgumentNonNegative(mFrequencyHz,
+ "Frequencies must all be >= 0, got " + mFrequencyHz);
+ Preconditions.checkArgumentFinite(mFrequencyHz, "frequencyHz");
Preconditions.checkArgumentNonnegative(mDuration,
"Durations must all be >= 0, got " + mDuration);
if (Float.compare(mAmplitude, VibrationEffect.DEFAULT_AMPLITUDE) != 0) {
@@ -108,7 +117,8 @@ public final class StepSegment extends VibrationEffectSegment {
if (Float.compare(mAmplitude, VibrationEffect.DEFAULT_AMPLITUDE) != 0) {
return this;
}
- return new StepSegment((float) defaultAmplitude / VibrationEffect.MAX_AMPLITUDE, mFrequency,
+ return new StepSegment((float) defaultAmplitude / VibrationEffect.MAX_AMPLITUDE,
+ mFrequencyHz,
mDuration);
}
@@ -119,7 +129,7 @@ public final class StepSegment extends VibrationEffectSegment {
if (Float.compare(mAmplitude, VibrationEffect.DEFAULT_AMPLITUDE) == 0) {
return this;
}
- return new StepSegment(VibrationEffect.scale(mAmplitude, scaleFactor), mFrequency,
+ return new StepSegment(VibrationEffect.scale(mAmplitude, scaleFactor), mFrequencyHz,
mDuration);
}
@@ -132,13 +142,13 @@ public final class StepSegment extends VibrationEffectSegment {
@Override
public int hashCode() {
- return Objects.hash(mAmplitude, mFrequency, mDuration);
+ return Objects.hash(mAmplitude, mFrequencyHz, mDuration);
}
@Override
public String toString() {
return "Step{amplitude=" + mAmplitude
- + ", frequency=" + mFrequency
+ + ", frequencyHz=" + mFrequencyHz
+ ", duration=" + mDuration
+ "}";
}
@@ -152,7 +162,7 @@ public final class StepSegment extends VibrationEffectSegment {
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeInt(PARCEL_TOKEN_STEP);
out.writeFloat(mAmplitude);
- out.writeFloat(mFrequency);
+ out.writeFloat(mFrequencyHz);
out.writeInt(mDuration);
}
diff --git a/core/java/android/os/vibrator/VibrationConfig.java b/core/java/android/os/vibrator/VibrationConfig.java
new file mode 100644
index 000000000000..4a61472e6205
--- /dev/null
+++ b/core/java/android/os/vibrator/VibrationConfig.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.vibrator;
+
+import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY;
+import static android.os.VibrationAttributes.USAGE_ALARM;
+import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
+import static android.os.VibrationAttributes.USAGE_MEDIA;
+import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
+import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION;
+import static android.os.VibrationAttributes.USAGE_RINGTONE;
+import static android.os.VibrationAttributes.USAGE_TOUCH;
+import static android.os.VibrationAttributes.USAGE_UNKNOWN;
+
+import android.annotation.Nullable;
+import android.content.res.Resources;
+import android.os.VibrationAttributes;
+import android.os.Vibrator;
+import android.os.Vibrator.VibrationIntensity;
+
+/**
+ * List of device-specific internal vibration configuration loaded from platform config.xml.
+ *
+ * <p>This should not be public, but some individual values are exposed by {@link Vibrator} by
+ * hidden methods, made available to Settings, SysUI and other platform client code. They can also
+ * be individually exposed with the necessary permissions by the {@link Vibrator} service.
+ *
+ * @hide
+ */
+public class VibrationConfig {
+
+ // TODO(b/191150049): move these to vibrator static config file
+ private final float mHapticChannelMaxVibrationAmplitude;
+ private final int mRampStepDurationMs;
+ private final int mRampDownDurationMs;
+
+ @VibrationIntensity
+ private final int mDefaultAlarmVibrationIntensity;
+ @VibrationIntensity
+ private final int mDefaultHapticFeedbackIntensity;
+ @VibrationIntensity
+ private final int mDefaultMediaVibrationIntensity;
+ @VibrationIntensity
+ private final int mDefaultNotificationVibrationIntensity;
+ @VibrationIntensity
+ private final int mDefaultRingVibrationIntensity;
+
+ /** @hide */
+ public VibrationConfig(@Nullable Resources resources) {
+ mHapticChannelMaxVibrationAmplitude = loadFloat(resources,
+ com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude, 0);
+ mRampDownDurationMs = loadInteger(resources,
+ com.android.internal.R.integer.config_vibrationWaveformRampDownDuration, 0);
+ mRampStepDurationMs = loadInteger(resources,
+ com.android.internal.R.integer.config_vibrationWaveformRampStepDuration, 0);
+
+ mDefaultAlarmVibrationIntensity = loadDefaultIntensity(resources,
+ com.android.internal.R.integer.config_defaultAlarmVibrationIntensity);
+ mDefaultHapticFeedbackIntensity = loadDefaultIntensity(resources,
+ com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
+ mDefaultMediaVibrationIntensity = loadDefaultIntensity(resources,
+ com.android.internal.R.integer.config_defaultMediaVibrationIntensity);
+ mDefaultNotificationVibrationIntensity = loadDefaultIntensity(resources,
+ com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
+ mDefaultRingVibrationIntensity = loadDefaultIntensity(resources,
+ com.android.internal.R.integer.config_defaultRingVibrationIntensity);
+ }
+
+ @VibrationIntensity
+ private static int loadDefaultIntensity(@Nullable Resources res, int resId) {
+ int defaultIntensity = Vibrator.VIBRATION_INTENSITY_MEDIUM;
+ int value = loadInteger(res, resId, defaultIntensity);
+ if (value < Vibrator.VIBRATION_INTENSITY_OFF || value > Vibrator.VIBRATION_INTENSITY_HIGH) {
+ return defaultIntensity;
+ }
+ return value;
+ }
+
+ private static float loadFloat(@Nullable Resources res, int resId, float defaultValue) {
+ return res != null ? res.getFloat(resId) : defaultValue;
+ }
+
+ private static int loadInteger(@Nullable Resources res, int resId, int defaultValue) {
+ return res != null ? res.getInteger(resId) : defaultValue;
+ }
+
+ /**
+ * Return the maximum amplitude the vibrator can play using the audio haptic channels.
+ *
+ * @return a positive value representing the maximum absolute value the device can play signals
+ * from audio haptic channels, or {@link Float#NaN NaN} if it's unknown.
+ */
+ public float getHapticChannelMaximumAmplitude() {
+ if (mHapticChannelMaxVibrationAmplitude <= 0) {
+ return Float.NaN;
+ }
+ return mHapticChannelMaxVibrationAmplitude;
+ }
+
+ /**
+ * The duration, in milliseconds, that should be applied to the ramp to turn off the vibrator
+ * when a vibration is cancelled or finished at non-zero amplitude.
+ */
+ public int getRampDownDurationMs() {
+ if (mRampDownDurationMs < 0) {
+ return 0;
+ }
+ return mRampDownDurationMs;
+ }
+
+ /**
+ * The duration, in milliseconds, that should be applied to convert vibration effect's
+ * {@link android.os.vibrator.RampSegment} to a {@link android.os.vibrator.StepSegment} on
+ * devices without PWLE support.
+ */
+ public int getRampStepDurationMs() {
+ if (mRampStepDurationMs < 0) {
+ return 0;
+ }
+ return mRampStepDurationMs;
+ }
+
+ /** Get the default vibration intensity for given usage. */
+ @VibrationIntensity
+ public int getDefaultVibrationIntensity(@VibrationAttributes.Usage int usage) {
+ switch (usage) {
+ case USAGE_ALARM:
+ return mDefaultAlarmVibrationIntensity;
+ case USAGE_NOTIFICATION:
+ case USAGE_COMMUNICATION_REQUEST:
+ return mDefaultNotificationVibrationIntensity;
+ case USAGE_RINGTONE:
+ return mDefaultRingVibrationIntensity;
+ case USAGE_TOUCH:
+ case USAGE_HARDWARE_FEEDBACK:
+ case USAGE_PHYSICAL_EMULATION:
+ case USAGE_ACCESSIBILITY:
+ return mDefaultHapticFeedbackIntensity;
+ case USAGE_MEDIA:
+ case USAGE_UNKNOWN:
+ // fall through
+ default:
+ return mDefaultMediaVibrationIntensity;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "VibrationConfig{"
+ + "mHapticChannelMaxVibrationAmplitude=" + mHapticChannelMaxVibrationAmplitude
+ + ", mRampStepDurationMs=" + mRampStepDurationMs
+ + ", mRampDownDurationMs=" + mRampDownDurationMs
+ + ", mDefaultAlarmIntensity=" + mDefaultAlarmVibrationIntensity
+ + ", mDefaultHapticFeedbackIntensity=" + mDefaultHapticFeedbackIntensity
+ + ", mDefaultMediaIntensity=" + mDefaultMediaVibrationIntensity
+ + ", mDefaultNotificationIntensity=" + mDefaultNotificationVibrationIntensity
+ + ", mDefaultRingIntensity=" + mDefaultRingVibrationIntensity
+ + "}";
+ }
+}
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index 0e32a78411dd..5814bac06f59 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -56,4 +56,6 @@ oneway interface IPermissionController {
in AndroidFuture<String> callback);
void getUnusedAppCount(
in AndroidFuture callback);
+ void selfRevokePermissions(in String packageName, in List<String> permissions,
+ in AndroidFuture callback);
}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 4a94c32501a1..8e5581b1b80e 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -67,6 +67,8 @@ interface IPermissionManager {
void revokeRuntimePermission(String packageName, String permissionName, int userId,
String reason);
+ void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId);
+
boolean shouldShowRequestPermissionRationale(String packageName, String permissionName,
int userId);
@@ -74,6 +76,8 @@ interface IPermissionManager {
List<SplitPermissionInfoParcelable> getSplitPermissions();
+ void selfRevokePermissions(String packageName, in List<String> permissions);
+
void startOneTimePermissionSession(String packageName, int userId, long timeout,
int importanceToResetTimer, int importanceToKeepSessionAlive);
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index a0788e70b247..47cd10765da0 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -817,4 +817,40 @@ public final class PermissionControllerManager {
}
});
}
+
+ /**
+ * Triggers the revocation of one or more permissions for a package, under the following
+ * conditions:
+ * <ul>
+ * <li>The package {@code packageName} must be under the same UID as the calling process
+ * (typically, the target package is the calling package).
+ * <li>Each permission in {@code permissions} must be granted to the package
+ * {@code packageName}.
+ * <li>Each permission in {@code permissions} must be a runtime permission.
+ * </ul>
+ * <p>
+ * For every permission in {@code permissions}, the entire permission group it belongs to will
+ * be revoked. This revocation happens asynchronously and kills all processes running in the
+ * same UID as {@code packageName}. It will be triggered once it is safe to do so.
+ *
+ * @param packageName The name of the package for which the permissions will be revoked.
+ * @param permissions List of permissions to be revoked.
+ *
+ * @see Context#selfRevokePermissions(Collection)
+ *
+ * @hide
+ */
+ public void selfRevokePermissions(@NonNull String packageName,
+ @NonNull List<String> permissions) {
+ mRemoteService.postAsync(service -> {
+ AndroidFuture<Void> future = new AndroidFuture<>();
+ service.selfRevokePermissions(packageName, permissions, future);
+ return future;
+ }).whenComplete((result, err) -> {
+ if (err != null) {
+ Log.e(TAG, "Failed to self revoke " + String.join(",", permissions)
+ + " for package " + packageName, err);
+ }
+ });
+ }
}
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index c9793032c7eb..dcbab62530b1 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -324,6 +324,27 @@ public abstract class PermissionControllerService extends Service {
@NonNull Consumer<String> callback) {
throw new AbstractMethodError("Must be overridden in implementing class");
}
+
+ /**
+ * Triggers the revocation of one or more permissions for a package. This should only be called
+ * at the request of {@code packageName}.
+ * <p>
+ * For every permission in {@code permissions}, the entire permission group it belongs to will
+ * be revoked. This revocation happens asynchronously and kills all processes running in the
+ * same UID as {@code packageName}. It will be triggered once it is safe to do so.
+ *
+ * @param packageName The name of the package for which the permissions will be revoked.
+ * @param permissions List of permissions to be revoked.
+ * @param callback Callback waiting for operation to be complete.
+ *
+ * @see PermissionManager#selfRevokePermissions(java.util.Collection)
+ */
+ @BinderThread
+ public void onSelfRevokePermissions(@NonNull String packageName,
+ @NonNull List<String> permissions, @NonNull Runnable callback) {
+ throw new AbstractMethodError("Must be overridden in implementing class");
+ }
+
/**
* Get a user-readable sentence, describing the set of privileges that are to be granted to a
* companion app managing a device of the given profile.
@@ -646,6 +667,20 @@ public abstract class PermissionControllerService extends Service {
callback.completeExceptionally(t);
}
}
+
+ @Override
+ public void selfRevokePermissions(@NonNull String packageName,
+ @NonNull List<String> permissions, @NonNull AndroidFuture callback) {
+ try {
+ enforceSomePermissionsGrantedToCaller(
+ Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
+ Objects.requireNonNull(callback);
+ onSelfRevokePermissions(packageName, permissions,
+ () -> callback.complete(null));
+ } catch (Throwable t) {
+ callback.completeExceptionally(t);
+ }
+ }
};
}
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 3ea50e98879b..13941dc5ef82 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -68,6 +68,7 @@ import com.android.internal.annotations.Immutable;
import com.android.internal.util.CollectionUtils;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -561,6 +562,19 @@ public final class PermissionManager {
}
/**
+ * @see Context#selfRevokePermissions(Collection)
+ * @hide
+ */
+ public void selfRevokePermissions(@NonNull Collection<String> permissions) {
+ try {
+ mPermissionManager.selfRevokePermissions(mContext.getPackageName(),
+ new ArrayList<String>(permissions));
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets the state flags associated with a permission.
*
* @param packageName the package name for which to get the flags
@@ -1362,6 +1376,26 @@ public final class PermissionManager {
return false;
}
+ /**
+ * Revoke the POST_NOTIFICATIONS permission, without killing the app. This method must ONLY BE
+ * USED in CTS or local tests.
+ *
+ * @param packageName The package to be revoked
+ * @param userId The user for which to revoke
+ *
+ * @hide
+ */
+ @TestApi
+ public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String packageName,
+ int userId) {
+ try {
+ mPermissionManager.revokePostNotificationPermissionWithoutKillForTest(packageName,
+ userId);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
/* @hide */
private static int checkPermissionUncached(@Nullable String permission, int pid, int uid) {
final IActivityManager am = ActivityManager.getService();
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 9bdfd8e69c00..67249be2b806 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -231,24 +231,24 @@ public final class PrintJobInfo implements Parcelable {
}
private PrintJobInfo(@NonNull Parcel parcel) {
- mId = parcel.readParcelable(null, android.print.PrintJobId.class);
+ mId = parcel.readParcelable(null);
mLabel = parcel.readString();
- mPrinterId = parcel.readParcelable(null, android.print.PrinterId.class);
+ mPrinterId = parcel.readParcelable(null);
mPrinterName = parcel.readString();
mState = parcel.readInt();
mAppId = parcel.readInt();
mTag = parcel.readString();
mCreationTime = parcel.readLong();
mCopies = parcel.readInt();
- Parcelable[] parcelables = parcel.readParcelableArray(null);
+ Parcelable[] parcelables = parcel.readParcelableArray(null, PageRange.class);
if (parcelables != null) {
mPageRanges = new PageRange[parcelables.length];
for (int i = 0; i < parcelables.length; i++) {
mPageRanges[i] = (PageRange) parcelables[i];
}
}
- mAttributes = (PrintAttributes) parcel.readParcelable(null, android.print.PrintAttributes.class);
- mDocumentInfo = (PrintDocumentInfo) parcel.readParcelable(null, android.print.PrintDocumentInfo.class);
+ mAttributes = (PrintAttributes) parcel.readParcelable(null);
+ mDocumentInfo = (PrintDocumentInfo) parcel.readParcelable(null);
mProgress = parcel.readFloat();
mStatus = parcel.readCharSequence();
mStatusRes = parcel.readInt();
diff --git a/core/java/android/print/PrinterId.java b/core/java/android/print/PrinterId.java
index 284e122fc103..25260c473709 100644
--- a/core/java/android/print/PrinterId.java
+++ b/core/java/android/print/PrinterId.java
@@ -48,7 +48,7 @@ public final class PrinterId implements Parcelable {
}
private PrinterId(@NonNull Parcel parcel) {
- mServiceName = Preconditions.checkNotNull((ComponentName) parcel.readParcelable(null, android.content.ComponentName.class));
+ mServiceName = Preconditions.checkNotNull((ComponentName) parcel.readParcelable(null));
mLocalId = Preconditions.checkNotNull(parcel.readString());
}
diff --git a/core/java/android/print/PrinterInfo.java b/core/java/android/print/PrinterInfo.java
index 2f93e404a211..8e03e3eb3f22 100644
--- a/core/java/android/print/PrinterInfo.java
+++ b/core/java/android/print/PrinterInfo.java
@@ -270,15 +270,15 @@ public final class PrinterInfo implements Parcelable {
private PrinterInfo(Parcel parcel) {
// mName can be null due to unchecked set in Builder.setName and status can be invalid
// due to unchecked set in Builder.setStatus, hence we can only check mId for a valid state
- mId = checkPrinterId((PrinterId) parcel.readParcelable(null, android.print.PrinterId.class));
+ mId = checkPrinterId((PrinterId) parcel.readParcelable(null));
mName = checkName(parcel.readString());
mStatus = checkStatus(parcel.readInt());
mDescription = parcel.readString();
- mCapabilities = parcel.readParcelable(null, android.print.PrinterCapabilitiesInfo.class);
+ mCapabilities = parcel.readParcelable(null);
mIconResourceId = parcel.readInt();
mHasCustomPrinterIcon = parcel.readByte() != 0;
mCustomPrinterIconGen = parcel.readInt();
- mInfoIntent = parcel.readParcelable(null, android.app.PendingIntent.class);
+ mInfoIntent = parcel.readParcelable(null);
}
@Override
diff --git a/core/java/android/printservice/PrintServiceInfo.java b/core/java/android/printservice/PrintServiceInfo.java
index 347955718f78..0c1b61d583b3 100644
--- a/core/java/android/printservice/PrintServiceInfo.java
+++ b/core/java/android/printservice/PrintServiceInfo.java
@@ -76,7 +76,7 @@ public final class PrintServiceInfo implements Parcelable {
public PrintServiceInfo(Parcel parcel) {
mId = parcel.readString();
mIsEnabled = parcel.readByte() != 0;
- mResolveInfo = parcel.readParcelable(null, android.content.pm.ResolveInfo.class);
+ mResolveInfo = parcel.readParcelable(null);
mSettingsActivityName = parcel.readString();
mAddPrintersActivityName = parcel.readString();
mAdvancedPrintOptionsActivityName = parcel.readString();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a97d4609539b..72e28630da40 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4603,6 +4603,43 @@ public final class Settings {
public static final String VIBRATE_INPUT_DEVICES = "vibrate_input_devices";
/**
+ * The intensity of alarm vibrations, if configurable.
+ *
+ * Not all devices are capable of changing their vibration intensity; on these devices
+ * there will likely be no difference between the various vibration intensities except for
+ * intensity 0 (off) and the rest.
+ *
+ * <b>Values:</b><br/>
+ * 0 - Vibration is disabled<br/>
+ * 1 - Weak vibrations<br/>
+ * 2 - Medium vibrations<br/>
+ * 3 - Strong vibrations
+ * @hide
+ */
+ public static final String ALARM_VIBRATION_INTENSITY =
+ "alarm_vibration_intensity";
+
+ /**
+ * The intensity of media vibrations, if configurable.
+ *
+ * This includes any vibration that is part of media, such as music, movie, soundtrack,
+ * game or animations.
+ *
+ * Not all devices are capable of changing their vibration intensity; on these devices
+ * there will likely be no difference between the various vibration intensities except for
+ * intensity 0 (off) and the rest.
+ *
+ * <b>Values:</b><br/>
+ * 0 - Vibration is disabled<br/>
+ * 1 - Weak vibrations<br/>
+ * 2 - Medium vibrations<br/>
+ * 3 - Strong vibrations
+ * @hide
+ */
+ public static final String MEDIA_VIBRATION_INTENSITY =
+ "media_vibration_intensity";
+
+ /**
* The intensity of notification vibrations, if configurable.
*
* Not all devices are capable of changing their vibration intensity; on these devices
@@ -4619,6 +4656,7 @@ public final class Settings {
@Readable
public static final String NOTIFICATION_VIBRATION_INTENSITY =
"notification_vibration_intensity";
+
/**
* The intensity of ringtone vibrations, if configurable.
*
@@ -4670,7 +4708,6 @@ public final class Settings {
* 3 - Strong vibrations
* @hide
*/
- @Readable
public static final String HARDWARE_HAPTIC_FEEDBACK_INTENSITY =
"hardware_haptic_feedback_intensity";
@@ -9949,6 +9986,7 @@ public final class Settings {
*
* @hide
*/
+ @Readable
public static final String NOTIFICATION_PERMISSION_ENABLED =
"notification_permission_enabled";
diff --git a/core/java/android/service/autofill/BatchUpdates.java b/core/java/android/service/autofill/BatchUpdates.java
index c996cc088d66..8eeecc293104 100644
--- a/core/java/android/service/autofill/BatchUpdates.java
+++ b/core/java/android/service/autofill/BatchUpdates.java
@@ -205,7 +205,7 @@ public final class BatchUpdates implements Parcelable {
builder.transformChild(ids[i], values[i]);
}
}
- final RemoteViews updates = parcel.readParcelable(null, android.widget.RemoteViews.class);
+ final RemoteViews updates = parcel.readParcelable(null);
if (updates != null) {
builder.updateTemplate(updates);
}
diff --git a/core/java/android/service/autofill/CompositeUserData.java b/core/java/android/service/autofill/CompositeUserData.java
index 55ac5a5e92f0..92952cb7dc24 100644
--- a/core/java/android/service/autofill/CompositeUserData.java
+++ b/core/java/android/service/autofill/CompositeUserData.java
@@ -197,8 +197,8 @@ public final class CompositeUserData implements FieldClassificationUserData, Par
// Always go through the builder to ensure the data ingested by
// the system obeys the contract of the builder to avoid attacks
// using specially crafted parcels.
- final UserData genericUserData = parcel.readParcelable(null, android.service.autofill.UserData.class);
- final UserData packageUserData = parcel.readParcelable(null, android.service.autofill.UserData.class);
+ final UserData genericUserData = parcel.readParcelable(null);
+ final UserData packageUserData = parcel.readParcelable(null);
return new CompositeUserData(genericUserData, packageUserData);
}
diff --git a/core/java/android/service/autofill/CustomDescription.java b/core/java/android/service/autofill/CustomDescription.java
index 690cd0691631..f3f912bb3a5b 100644
--- a/core/java/android/service/autofill/CustomDescription.java
+++ b/core/java/android/service/autofill/CustomDescription.java
@@ -437,7 +437,7 @@ public final class CustomDescription implements Parcelable {
// Always go through the builder to ensure the data ingested by
// the system obeys the contract of the builder to avoid attacks
// using specially crafted parcels.
- final RemoteViews parentPresentation = parcel.readParcelable(null, android.widget.RemoteViews.class);
+ final RemoteViews parentPresentation = parcel.readParcelable(null);
if (parentPresentation == null) return null;
final Builder builder = new Builder(parentPresentation);
diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java
index 86341a908ad7..8539bf58da27 100644
--- a/core/java/android/service/autofill/Dataset.java
+++ b/core/java/android/service/autofill/Dataset.java
@@ -913,10 +913,10 @@ public final class Dataset implements Parcelable {
public static final @NonNull Creator<Dataset> CREATOR = new Creator<Dataset>() {
@Override
public Dataset createFromParcel(Parcel parcel) {
- final RemoteViews presentation = parcel.readParcelable(null, android.widget.RemoteViews.class);
- final InlinePresentation inlinePresentation = parcel.readParcelable(null, android.service.autofill.InlinePresentation.class);
+ final RemoteViews presentation = parcel.readParcelable(null);
+ final InlinePresentation inlinePresentation = parcel.readParcelable(null);
final InlinePresentation inlineTooltipPresentation =
- parcel.readParcelable(null, android.service.autofill.InlinePresentation.class);
+ parcel.readParcelable(null);
final ArrayList<AutofillId> ids =
parcel.createTypedArrayList(AutofillId.CREATOR);
final ArrayList<AutofillValue> values =
@@ -929,8 +929,8 @@ public final class Dataset implements Parcelable {
parcel.createTypedArrayList(InlinePresentation.CREATOR);
final ArrayList<DatasetFieldFilter> filters =
parcel.createTypedArrayList(DatasetFieldFilter.CREATOR);
- final ClipData fieldContent = parcel.readParcelable(null, android.content.ClipData.class);
- final IntentSender authentication = parcel.readParcelable(null, android.content.IntentSender.class);
+ final ClipData fieldContent = parcel.readParcelable(null);
+ final IntentSender authentication = parcel.readParcelable(null);
final String datasetId = parcel.readString();
// Always go through the builder to ensure the data ingested by
@@ -1014,7 +1014,7 @@ public final class Dataset implements Parcelable {
@Override
public DatasetFieldFilter createFromParcel(Parcel parcel) {
- return new DatasetFieldFilter((Pattern) parcel.readSerializable(java.util.regex.Pattern.class.getClassLoader(), java.util.regex.Pattern.class));
+ return new DatasetFieldFilter((Pattern) parcel.readSerializable());
}
@Override
diff --git a/core/java/android/service/autofill/DateTransformation.java b/core/java/android/service/autofill/DateTransformation.java
index df5ed4dace55..734085737159 100644
--- a/core/java/android/service/autofill/DateTransformation.java
+++ b/core/java/android/service/autofill/DateTransformation.java
@@ -114,8 +114,8 @@ public final class DateTransformation extends InternalTransformation implements
new Parcelable.Creator<DateTransformation>() {
@Override
public DateTransformation createFromParcel(Parcel parcel) {
- return new DateTransformation(parcel.readParcelable(null, android.view.autofill.AutofillId.class),
- (DateFormat) parcel.readSerializable(android.icu.text.DateFormat.class.getClassLoader(), android.icu.text.DateFormat.class));
+ return new DateTransformation(parcel.readParcelable(null),
+ (DateFormat) parcel.readSerializable());
}
@Override
diff --git a/core/java/android/service/autofill/DateValueSanitizer.java b/core/java/android/service/autofill/DateValueSanitizer.java
index c7d5b79ae484..6f7808ee181a 100644
--- a/core/java/android/service/autofill/DateValueSanitizer.java
+++ b/core/java/android/service/autofill/DateValueSanitizer.java
@@ -111,7 +111,7 @@ public final class DateValueSanitizer extends InternalSanitizer implements Sanit
new Parcelable.Creator<DateValueSanitizer>() {
@Override
public DateValueSanitizer createFromParcel(Parcel parcel) {
- return new DateValueSanitizer((DateFormat) parcel.readSerializable(android.icu.text.DateFormat.class.getClassLoader(), android.icu.text.DateFormat.class));
+ return new DateValueSanitizer((DateFormat) parcel.readSerializable());
}
@Override
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 43bd4102ffb5..af846b62ae2c 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -384,7 +384,7 @@ public final class FillRequest implements Parcelable {
byte flg = in.readByte();
int id = in.readInt();
List<FillContext> fillContexts = new ArrayList<>();
- in.readParcelableList(fillContexts, FillContext.class.getClassLoader(), android.service.autofill.FillContext.class);
+ in.readParcelableList(fillContexts, FillContext.class.getClassLoader());
Bundle clientState = (flg & 0x4) == 0 ? null : in.readBundle();
int flags = in.readInt();
InlineSuggestionsRequest inlineSuggestionsRequest = (flg & 0x10) == 0 ? null : (InlineSuggestionsRequest) in.readTypedObject(InlineSuggestionsRequest.CREATOR);
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index d94988ebea66..970cb1888317 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -834,35 +834,35 @@ public final class FillResponse implements Parcelable {
// the system obeys the contract of the builder to avoid attacks
// using specially crafted parcels.
final Builder builder = new Builder();
- final ParceledListSlice<Dataset> datasetSlice = parcel.readParcelable(null, android.content.pm.ParceledListSlice.class);
+ final ParceledListSlice<Dataset> datasetSlice = parcel.readParcelable(null);
final List<Dataset> datasets = (datasetSlice != null) ? datasetSlice.getList() : null;
final int datasetCount = (datasets != null) ? datasets.size() : 0;
for (int i = 0; i < datasetCount; i++) {
builder.addDataset(datasets.get(i));
}
- builder.setSaveInfo(parcel.readParcelable(null, android.service.autofill.SaveInfo.class));
- builder.setClientState(parcel.readParcelable(null, android.os.Bundle.class));
+ builder.setSaveInfo(parcel.readParcelable(null));
+ builder.setClientState(parcel.readParcelable(null));
// Sets authentication state.
final AutofillId[] authenticationIds = parcel.readParcelableArray(null,
AutofillId.class);
- final IntentSender authentication = parcel.readParcelable(null, android.content.IntentSender.class);
- final RemoteViews presentation = parcel.readParcelable(null, android.widget.RemoteViews.class);
- final InlinePresentation inlinePresentation = parcel.readParcelable(null, android.service.autofill.InlinePresentation.class);
- final InlinePresentation inlineTooltipPresentation = parcel.readParcelable(null, android.service.autofill.InlinePresentation.class);
+ final IntentSender authentication = parcel.readParcelable(null);
+ final RemoteViews presentation = parcel.readParcelable(null);
+ final InlinePresentation inlinePresentation = parcel.readParcelable(null);
+ final InlinePresentation inlineTooltipPresentation = parcel.readParcelable(null);
if (authenticationIds != null) {
builder.setAuthentication(authenticationIds, authentication, presentation,
inlinePresentation, inlineTooltipPresentation);
}
- final RemoteViews header = parcel.readParcelable(null, android.widget.RemoteViews.class);
+ final RemoteViews header = parcel.readParcelable(null);
if (header != null) {
builder.setHeader(header);
}
- final RemoteViews footer = parcel.readParcelable(null, android.widget.RemoteViews.class);
+ final RemoteViews footer = parcel.readParcelable(null);
if (footer != null) {
builder.setFooter(footer);
}
- final UserData userData = parcel.readParcelable(null, android.service.autofill.UserData.class);
+ final UserData userData = parcel.readParcelable(null);
if (userData != null) {
builder.setUserData(userData);
}
diff --git a/core/java/android/service/autofill/ImageTransformation.java b/core/java/android/service/autofill/ImageTransformation.java
index af82205b77b9..e3171594c39e 100644
--- a/core/java/android/service/autofill/ImageTransformation.java
+++ b/core/java/android/service/autofill/ImageTransformation.java
@@ -247,7 +247,7 @@ public final class ImageTransformation extends InternalTransformation implements
new Parcelable.Creator<ImageTransformation>() {
@Override
public ImageTransformation createFromParcel(Parcel parcel) {
- final AutofillId id = parcel.readParcelable(null, android.view.autofill.AutofillId.class);
+ final AutofillId id = parcel.readParcelable(null);
final Pattern[] regexs = (Pattern[]) parcel.readSerializable();
final int[] resIds = parcel.createIntArray();
diff --git a/core/java/android/service/autofill/NegationValidator.java b/core/java/android/service/autofill/NegationValidator.java
index 85cd981e3152..d626845b3b3e 100644
--- a/core/java/android/service/autofill/NegationValidator.java
+++ b/core/java/android/service/autofill/NegationValidator.java
@@ -68,7 +68,7 @@ final class NegationValidator extends InternalValidator {
new Parcelable.Creator<NegationValidator>() {
@Override
public NegationValidator createFromParcel(Parcel parcel) {
- return new NegationValidator(parcel.readParcelable(null, android.service.autofill.InternalValidator.class));
+ return new NegationValidator(parcel.readParcelable(null));
}
@Override
diff --git a/core/java/android/service/autofill/RegexValidator.java b/core/java/android/service/autofill/RegexValidator.java
index 4c58590ab7cf..00c43473ce7f 100644
--- a/core/java/android/service/autofill/RegexValidator.java
+++ b/core/java/android/service/autofill/RegexValidator.java
@@ -96,8 +96,8 @@ public final class RegexValidator extends InternalValidator implements Validator
new Parcelable.Creator<RegexValidator>() {
@Override
public RegexValidator createFromParcel(Parcel parcel) {
- return new RegexValidator(parcel.readParcelable(null, android.view.autofill.AutofillId.class),
- (Pattern) parcel.readSerializable(java.util.regex.Pattern.class.getClassLoader(), java.util.regex.Pattern.class));
+ return new RegexValidator(parcel.readParcelable(null),
+ (Pattern) parcel.readSerializable());
}
@Override
diff --git a/core/java/android/service/autofill/SaveInfo.java b/core/java/android/service/autofill/SaveInfo.java
index 5fe1d4f5ca5f..8edfde8c3914 100644
--- a/core/java/android/service/autofill/SaveInfo.java
+++ b/core/java/android/service/autofill/SaveInfo.java
@@ -888,14 +888,14 @@ public final class SaveInfo implements Parcelable {
builder.setOptionalIds(optionalIds);
}
- builder.setNegativeAction(parcel.readInt(), parcel.readParcelable(null, android.content.IntentSender.class));
+ builder.setNegativeAction(parcel.readInt(), parcel.readParcelable(null));
builder.setPositiveAction(parcel.readInt());
builder.setDescription(parcel.readCharSequence());
- final CustomDescription customDescripton = parcel.readParcelable(null, android.service.autofill.CustomDescription.class);
+ final CustomDescription customDescripton = parcel.readParcelable(null);
if (customDescripton != null) {
builder.setCustomDescription(customDescripton);
}
- final InternalValidator validator = parcel.readParcelable(null, android.service.autofill.InternalValidator.class);
+ final InternalValidator validator = parcel.readParcelable(null);
if (validator != null) {
builder.setValidator(validator);
}
@@ -909,7 +909,7 @@ public final class SaveInfo implements Parcelable {
builder.addSanitizer(sanitizers[i], autofillIds);
}
}
- final AutofillId triggerId = parcel.readParcelable(null, android.view.autofill.AutofillId.class);
+ final AutofillId triggerId = parcel.readParcelable(null);
if (triggerId != null) {
builder.setTriggerId(triggerId);
}
diff --git a/core/java/android/service/autofill/TextValueSanitizer.java b/core/java/android/service/autofill/TextValueSanitizer.java
index 46c18b23a74d..5bafa7a1ff54 100644
--- a/core/java/android/service/autofill/TextValueSanitizer.java
+++ b/core/java/android/service/autofill/TextValueSanitizer.java
@@ -119,7 +119,7 @@ public final class TextValueSanitizer extends InternalSanitizer implements
new Parcelable.Creator<TextValueSanitizer>() {
@Override
public TextValueSanitizer createFromParcel(Parcel parcel) {
- return new TextValueSanitizer((Pattern) parcel.readSerializable(java.util.regex.Pattern.class.getClassLoader(), java.util.regex.Pattern.class), parcel.readString());
+ return new TextValueSanitizer((Pattern) parcel.readSerializable(), parcel.readString());
}
@Override
diff --git a/core/java/android/service/contentcapture/ActivityEvent.java b/core/java/android/service/contentcapture/ActivityEvent.java
index d286942c74fa..74a735518120 100644
--- a/core/java/android/service/contentcapture/ActivityEvent.java
+++ b/core/java/android/service/contentcapture/ActivityEvent.java
@@ -149,7 +149,7 @@ public final class ActivityEvent implements Parcelable {
@Override
@NonNull
public ActivityEvent createFromParcel(@NonNull Parcel parcel) {
- final ComponentName componentName = parcel.readParcelable(null, android.content.ComponentName.class);
+ final ComponentName componentName = parcel.readParcelable(null);
final int eventType = parcel.readInt();
return new ActivityEvent(componentName, eventType);
}
diff --git a/core/java/android/service/contentcapture/SnapshotData.java b/core/java/android/service/contentcapture/SnapshotData.java
index f72624d00061..bf469b4b3ad8 100644
--- a/core/java/android/service/contentcapture/SnapshotData.java
+++ b/core/java/android/service/contentcapture/SnapshotData.java
@@ -51,8 +51,8 @@ public final class SnapshotData implements Parcelable {
SnapshotData(@NonNull Parcel parcel) {
mAssistData = parcel.readBundle();
- mAssistStructure = parcel.readParcelable(null, android.app.assist.AssistStructure.class);
- mAssistContent = parcel.readParcelable(null, android.app.assist.AssistContent.class);
+ mAssistStructure = parcel.readParcelable(null);
+ mAssistContent = parcel.readParcelable(null);
}
/**
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 50f9d8ac2958..163d6ed4b18b 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -35,6 +35,7 @@ import android.view.WindowManager;
public abstract class DreamOverlayService extends Service {
private static final String TAG = "DreamOverlayService";
private static final boolean DEBUG = false;
+ private boolean mShowComplications;
private IDreamOverlay mDreamOverlay = new IDreamOverlay.Stub() {
@Override
@@ -53,6 +54,8 @@ public abstract class DreamOverlayService extends Service {
@Nullable
@Override
public final IBinder onBind(@NonNull Intent intent) {
+ mShowComplications = intent.getBooleanExtra(DreamService.EXTRA_SHOW_COMPLICATIONS,
+ DreamService.DEFAULT_SHOW_COMPLICATIONS);
return mDreamOverlay.asBinder();
}
@@ -74,4 +77,11 @@ public abstract class DreamOverlayService extends Service {
Log.e(TAG, "Could not request exit:" + e);
}
}
+
+ /**
+ * Returns whether to show complications on the dream overlay.
+ */
+ public final boolean shouldShowComplications() {
+ return mShowComplications;
+ }
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 4ae3d7de26c2..133e384dfa8f 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -189,6 +189,19 @@ public class DreamService extends Service implements Window.Callback {
*/
public static final String DREAM_META_DATA = "android.service.dream";
+ /**
+ * Extra containing a boolean for whether to show complications on the overlay.
+ * @hide
+ */
+ public static final String EXTRA_SHOW_COMPLICATIONS =
+ "android.service.dreams.SHOW_COMPLICATIONS";
+
+ /**
+ * The default value for whether to show complications on the overlay.
+ * @hide
+ */
+ public static final boolean DEFAULT_SHOW_COMPLICATIONS = true;
+
private final IDreamManager mDreamManager;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private IBinder mDreamToken;
diff --git a/core/java/android/service/games/GameService.java b/core/java/android/service/games/GameService.java
index b79c0553460f..105c2aa53374 100644
--- a/core/java/android/service/games/GameService.java
+++ b/core/java/android/service/games/GameService.java
@@ -38,10 +38,23 @@ import java.util.Objects;
* when a game session should begin. It is always kept running by the system.
* Because of this it should be kept as lightweight as possible.
*
- * Heavy weight operations (such as showing UI) should be implemented in the
+ * <p>Heavyweight operations (such as showing UI) should be implemented in the
* associated {@link GameSessionService} when a game session is taking place. Its
* implementation should run in a separate process from the {@link GameService}.
*
+ * <p>To extend this class, you must declare the service in your manifest file with
+ * the {@link android.Manifest.permission#BIND_GAME_SERVICE} permission
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:
+ * <pre>
+ * &lt;service android:name=".GameService"
+ * android:label="&#64;string/service_name"
+ * android:permission="android.permission.BIND_GAME_SERVICE">
+ * &lt;intent-filter>
+ * &lt;action android:name="android.service.games.GameService" />
+ * &lt;/intent-filter>
+ * &lt;/service>
+ * </pre>
+ *
* @hide
*/
@SystemApi
@@ -90,7 +103,7 @@ public class GameService extends Service {
@Override
@Nullable
- public IBinder onBind(@Nullable Intent intent) {
+ public final IBinder onBind(@Nullable Intent intent) {
if (ACTION_GAME_SERVICE.equals(intent.getAction())) {
return mInterface.asBinder();
}
diff --git a/core/java/android/service/games/GameSessionService.java b/core/java/android/service/games/GameSessionService.java
index a2c88709b62d..c1a3eb5286c4 100644
--- a/core/java/android/service/games/GameSessionService.java
+++ b/core/java/android/service/games/GameSessionService.java
@@ -73,7 +73,7 @@ public abstract class GameSessionService extends Service {
@Override
@Nullable
- public IBinder onBind(@Nullable Intent intent) {
+ public final IBinder onBind(@Nullable Intent intent) {
if (intent == null) {
return null;
}
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
index 267b2ff818a6..4f324f9e35bf 100644
--- a/core/java/android/service/notification/Condition.java
+++ b/core/java/android/service/notification/Condition.java
@@ -114,7 +114,7 @@ public final class Condition implements Parcelable {
}
public Condition(Parcel source) {
- this((Uri)source.readParcelable(Condition.class.getClassLoader(), android.net.Uri.class),
+ this((Uri)source.readParcelable(Condition.class.getClassLoader()),
source.readString(),
source.readString(),
source.readString(),
diff --git a/core/java/android/service/notification/ConversationChannelWrapper.java b/core/java/android/service/notification/ConversationChannelWrapper.java
index 35b6bad4e40b..3d0984ca80ee 100644
--- a/core/java/android/service/notification/ConversationChannelWrapper.java
+++ b/core/java/android/service/notification/ConversationChannelWrapper.java
@@ -40,10 +40,10 @@ public final class ConversationChannelWrapper implements Parcelable {
public ConversationChannelWrapper() {}
protected ConversationChannelWrapper(Parcel in) {
- mNotificationChannel = in.readParcelable(NotificationChannel.class.getClassLoader(), android.app.NotificationChannel.class);
+ mNotificationChannel = in.readParcelable(NotificationChannel.class.getClassLoader());
mGroupLabel = in.readCharSequence();
mParentChannelLabel = in.readCharSequence();
- mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader(), android.content.pm.ShortcutInfo.class);
+ mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
mPkg = in.readStringNoHelper();
mUid = in.readInt();
}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index ae39d3d3c2da..c94595468aec 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1763,7 +1763,7 @@ public abstract class NotificationListenerService extends Service {
mImportanceExplanation = in.readCharSequence(); // may be null
mRankingScore = in.readFloat();
mOverrideGroupKey = in.readString(); // may be null
- mChannel = in.readParcelable(cl, android.app.NotificationChannel.class); // may be null
+ mChannel = in.readParcelable(cl); // may be null
mOverridePeople = in.createStringArrayList();
mSnoozeCriteria = in.createTypedArrayList(SnoozeCriterion.CREATOR);
mShowBadge = in.readBoolean();
@@ -1776,7 +1776,7 @@ public abstract class NotificationListenerService extends Service {
mCanBubble = in.readBoolean();
mIsTextChanged = in.readBoolean();
mIsConversation = in.readBoolean();
- mShortcutInfo = in.readParcelable(cl, android.content.pm.ShortcutInfo.class);
+ mShortcutInfo = in.readParcelable(cl);
mRankingAdjustment = in.readInt();
mIsBubble = in.readBoolean();
}
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index a853714c0e9d..c64f4c46a769 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -30,7 +30,7 @@ public class NotificationRankingUpdate implements Parcelable {
}
public NotificationRankingUpdate(Parcel in) {
- mRankingMap = in.readParcelable(getClass().getClassLoader(), android.service.notification.NotificationListenerService.RankingMap.class);
+ mRankingMap = in.readParcelable(getClass().getClassLoader());
}
public NotificationListenerService.RankingMap getRankingMap() {
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 8834ceea7453..c1d5a28aa349 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -211,7 +211,7 @@ public class ZenModeConfig implements Parcelable {
allowCallsFrom = source.readInt();
allowMessagesFrom = source.readInt();
user = source.readInt();
- manualRule = source.readParcelable(null, android.service.notification.ZenModeConfig.ZenRule.class);
+ manualRule = source.readParcelable(null);
final int len = source.readInt();
if (len > 0) {
final String[] ids = new String[len];
@@ -1800,10 +1800,10 @@ public class ZenModeConfig implements Parcelable {
name = source.readString();
}
zenMode = source.readInt();
- conditionId = source.readParcelable(null, android.net.Uri.class);
- condition = source.readParcelable(null, android.service.notification.Condition.class);
- component = source.readParcelable(null, android.content.ComponentName.class);
- configurationActivity = source.readParcelable(null, android.content.ComponentName.class);
+ conditionId = source.readParcelable(null);
+ condition = source.readParcelable(null);
+ component = source.readParcelable(null);
+ configurationActivity = source.readParcelable(null);
if (source.readInt() == 1) {
id = source.readString();
}
@@ -1811,7 +1811,7 @@ public class ZenModeConfig implements Parcelable {
if (source.readInt() == 1) {
enabler = source.readString();
}
- zenPolicy = source.readParcelable(null, android.service.notification.ZenPolicy.class);
+ zenPolicy = source.readParcelable(null);
modified = source.readInt() == 1;
pkg = source.readString();
}
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index a04f07380ce8..ed3a9ac33738 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -804,8 +804,8 @@ public final class ZenPolicy implements Parcelable {
@Override
public ZenPolicy createFromParcel(Parcel source) {
ZenPolicy policy = new ZenPolicy();
- policy.mPriorityCategories = source.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class);
- policy.mVisualEffects = source.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class);
+ policy.mPriorityCategories = source.readArrayList(Integer.class.getClassLoader());
+ policy.mVisualEffects = source.readArrayList(Integer.class.getClassLoader());
policy.mPriorityCalls = source.readInt();
policy.mPriorityMessages = source.readInt();
policy.mConversationSenders = source.readInt();
diff --git a/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.java b/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.java
index 7471a4f399a5..0551e2709de6 100644
--- a/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.java
+++ b/core/java/android/service/quickaccesswallet/GetWalletCardsResponse.java
@@ -63,7 +63,7 @@ public final class GetWalletCardsResponse implements Parcelable {
private static GetWalletCardsResponse readFromParcel(Parcel source) {
int size = source.readInt();
List<WalletCard> walletCards =
- source.readParcelableList(new ArrayList<>(size), WalletCard.class.getClassLoader(), android.service.quickaccesswallet.WalletCard.class);
+ source.readParcelableList(new ArrayList<>(size), WalletCard.class.getClassLoader());
int selectedIndex = source.readInt();
return new GetWalletCardsResponse(walletCards, selectedIndex);
}
diff --git a/core/java/android/service/settings/suggestions/Suggestion.java b/core/java/android/service/settings/suggestions/Suggestion.java
index 16622d70065f..3e63efbda9c0 100644
--- a/core/java/android/service/settings/suggestions/Suggestion.java
+++ b/core/java/android/service/settings/suggestions/Suggestion.java
@@ -120,9 +120,9 @@ public final class Suggestion implements Parcelable {
mId = in.readString();
mTitle = in.readCharSequence();
mSummary = in.readCharSequence();
- mIcon = in.readParcelable(Icon.class.getClassLoader(), android.graphics.drawable.Icon.class);
+ mIcon = in.readParcelable(Icon.class.getClassLoader());
mFlags = in.readInt();
- mPendingIntent = in.readParcelable(PendingIntent.class.getClassLoader(), android.app.PendingIntent.class);
+ mPendingIntent = in.readParcelable(PendingIntent.class.getClassLoader());
}
public static final @android.annotation.NonNull Creator<Suggestion> CREATOR = new Creator<Suggestion>() {
diff --git a/core/java/android/service/timezone/TimeZoneProviderEvent.java b/core/java/android/service/timezone/TimeZoneProviderEvent.java
index f6433b7f371e..700528116a8f 100644
--- a/core/java/android/service/timezone/TimeZoneProviderEvent.java
+++ b/core/java/android/service/timezone/TimeZoneProviderEvent.java
@@ -141,7 +141,7 @@ public final class TimeZoneProviderEvent implements Parcelable {
int type = in.readInt();
long creationElapsedMillis = in.readLong();
TimeZoneProviderSuggestion suggestion =
- in.readParcelable(getClass().getClassLoader(), android.service.timezone.TimeZoneProviderSuggestion.class);
+ in.readParcelable(getClass().getClassLoader());
String failureCause = in.readString8();
return new TimeZoneProviderEvent(
type, creationElapsedMillis, suggestion, failureCause);
diff --git a/core/java/android/service/timezone/TimeZoneProviderSuggestion.java b/core/java/android/service/timezone/TimeZoneProviderSuggestion.java
index 4841ac189034..229fa268a47c 100644
--- a/core/java/android/service/timezone/TimeZoneProviderSuggestion.java
+++ b/core/java/android/service/timezone/TimeZoneProviderSuggestion.java
@@ -100,7 +100,7 @@ public final class TimeZoneProviderSuggestion implements Parcelable {
public TimeZoneProviderSuggestion createFromParcel(Parcel in) {
@SuppressWarnings("unchecked")
ArrayList<String> timeZoneIds =
- (ArrayList<String>) in.readArrayList(null /* classLoader */, java.lang.String.class);
+ (ArrayList<String>) in.readArrayList(null /* classLoader */);
long elapsedRealtimeMillis = in.readLong();
return new TimeZoneProviderSuggestion(timeZoneIds, elapsedRealtimeMillis);
}
diff --git a/core/java/android/speech/tts/Voice.java b/core/java/android/speech/tts/Voice.java
index 0d98a6ca5f14..7ffe5eb7893d 100644
--- a/core/java/android/speech/tts/Voice.java
+++ b/core/java/android/speech/tts/Voice.java
@@ -84,7 +84,7 @@ public class Voice implements Parcelable {
private Voice(Parcel in) {
this.mName = in.readString();
- this.mLocale = (Locale)in.readSerializable(java.util.Locale.class.getClassLoader(), java.util.Locale.class);
+ this.mLocale = (Locale)in.readSerializable();
this.mQuality = in.readInt();
this.mLatency = in.readInt();
this.mRequiresNetworkConnection = (in.readByte() == 1);
diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java
index fb2d7714d402..d5ac4368aa97 100644
--- a/core/java/android/telephony/SubscriptionPlan.java
+++ b/core/java/android/telephony/SubscriptionPlan.java
@@ -99,7 +99,7 @@ public final class SubscriptionPlan implements Parcelable {
}
private SubscriptionPlan(Parcel source) {
- cycleRule = source.readParcelable(null, android.util.RecurrenceRule.class);
+ cycleRule = source.readParcelable(null);
title = source.readCharSequence();
summary = source.readCharSequence();
dataLimitBytes = source.readLong();
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 9eaaa91532d0..542de3fad8b0 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -131,6 +131,7 @@ public class TelephonyRegistryManager {
mContext.getAttributionTag(), callback);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -152,6 +153,7 @@ public class TelephonyRegistryManager {
mSubscriptionChangedListenerMap.remove(listener);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -194,6 +196,7 @@ public class TelephonyRegistryManager {
mContext.getAttributionTag(), callback);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -216,6 +219,7 @@ public class TelephonyRegistryManager {
mOpportunisticSubscriptionChangedListenerMap.remove(listener);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -304,6 +308,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyCarrierNetworkChange(active);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -329,6 +334,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyCarrierNetworkChangeWithSubId(subscriptionId, active);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -347,6 +353,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -364,6 +371,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyCallStateForAllSubs(state, incomingNumber);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -376,6 +384,7 @@ public class TelephonyRegistryManager {
sRegistry.notifySubscriptionInfoChanged();
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -388,6 +397,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyOpportunisticSubscriptionInfoChanged();
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -404,6 +414,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyServiceStateForPhoneId(slotIndex, subId, state);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -421,6 +432,7 @@ public class TelephonyRegistryManager {
sRegistry.notifySignalStrengthForPhoneId(slotIndex, subId, signalStrength);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -439,6 +451,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyMessageWaitingChangedForPhoneId(slotIndex, subId, msgWaitingInd);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -454,6 +467,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyCallForwardingChangedForSubscriber(subId, callForwardInd);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -469,6 +483,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyDataActivityForSubscriber(subId, dataActivityType);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -490,6 +505,7 @@ public class TelephonyRegistryManager {
slotIndex, subId, preciseState);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -508,6 +524,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyCallQualityChanged(callQuality, slotIndex, subId, networkType);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -523,6 +540,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyEmergencyNumberList(slotIndex, subId);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -538,6 +556,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyOutgoingEmergencyCall(phoneId, subId, emergencyNumber);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -553,6 +572,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyOutgoingEmergencySms(phoneId, subId, emergencyNumber);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -570,6 +590,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyRadioPowerStateChanged(slotIndex, subId, radioPowerState);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -583,6 +604,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyPhoneCapabilityChanged(phoneCapability);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -615,6 +637,7 @@ public class TelephonyRegistryManager {
SIM_ACTIVATION_TYPE_DATA, activationState);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -634,6 +657,7 @@ public class TelephonyRegistryManager {
SIM_ACTIVATION_TYPE_VOICE, activationState);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -651,6 +675,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyUserMobileDataStateChangedForPhoneId(slotIndex, subId, state);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -669,6 +694,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyDisplayInfoChanged(slotIndex, subscriptionId, telephonyDisplayInfo);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -683,6 +709,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyImsDisconnectCause(subId, imsReasonInfo);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -698,6 +725,7 @@ public class TelephonyRegistryManager {
sRegistry.notifySrvccStateChanged(subId, state);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -721,6 +749,7 @@ public class TelephonyRegistryManager {
foregroundCallPreciseState, backgroundCallPreciseState);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -741,6 +770,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyDisconnectCause(slotIndex, subId, cause, preciseCause);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -755,6 +785,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyCellLocationForSubscriber(subId, cellLocation);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -769,7 +800,7 @@ public class TelephonyRegistryManager {
try {
sRegistry.notifyCellInfoForSubscriber(subId, cellInfo);
} catch (RemoteException ex) {
-
+ throw ex.rethrowFromSystemServer();
}
}
@@ -781,7 +812,7 @@ public class TelephonyRegistryManager {
try {
sRegistry.notifyActiveDataSubIdChanged(activeDataSubId);
} catch (RemoteException ex) {
-
+ throw ex.rethrowFromSystemServer();
}
}
@@ -814,6 +845,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyRegistrationFailed(slotIndex, subId, cellIdentity,
chosenPlmn, domain, causeCode, additionalCauseCode);
} catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
}
}
@@ -830,6 +862,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyBarringInfoChanged(slotIndex, subId, barringInfo);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -846,6 +879,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyPhysicalChannelConfigForSubscriber(slotIndex, subId, configs);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -862,6 +896,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyDataEnabled(slotIndex, subId, enabled, reason);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
@@ -880,6 +915,7 @@ public class TelephonyRegistryManager {
allowedNetworkType);
} catch (RemoteException ex) {
// system process is dead
+ throw ex.rethrowFromSystemServer();
}
}
@@ -895,6 +931,7 @@ public class TelephonyRegistryManager {
sRegistry.notifyLinkCapacityEstimateChanged(slotIndex, subId, linkCapacityEstimateList);
} catch (RemoteException ex) {
// system server crash
+ throw ex.rethrowFromSystemServer();
}
}
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 4ee02f01f330..fee23f4b0be7 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -107,6 +107,10 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
* @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
* {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
* not used, {@code outerWidth} is used instead
+ * @param useFallbackLineSpacing True for adjusting the line spacing based on fallback fonts.
+ * False for keeping the first font's line height. If some glyphs
+ * requires larger vertical spaces, by passing true to this
+ * argument, the layout increase the line height to fit all glyphs.
*/
public static @NonNull BoringLayout make(
@NonNull CharSequence source, @NonNull TextPaint paint,
@@ -168,7 +172,11 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
* requested width
* @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
* {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
- * not used, {@code outerwidth} is used instead
+ * not used, {@code outerWidth} is used instead
+ * @param useFallbackLineSpacing True for adjusting the line spacing based on fallback fonts.
+ * False for keeping the first font's line height. If some glyphs
+ * requires larger vertical spaces, by passing true to this
+ * argument, the layout increase the line height to fit all glyphs.
*/
public @NonNull BoringLayout replaceOrMake(@NonNull CharSequence source,
@NonNull TextPaint paint, @IntRange(from = 0) int outerWidth,
@@ -216,7 +224,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
* requested width
* @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
* {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
- * not used, {@code outerwidth} is used instead
+ * not used, {@code outerWidth} is used instead
*/
public BoringLayout replaceOrMake(CharSequence source, TextPaint paint, int outerWidth,
Alignment align, float spacingMult, float spacingAdd, BoringLayout.Metrics metrics,
@@ -261,10 +269,10 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
* @param includePad set whether to include extra space beyond font ascent and descent which is
* needed to avoid clipping in some scripts
* @param ellipsize whether to ellipsize the text if width of the text is longer than the
- * requested {@code outerwidth}
+ * requested {@code outerWidth}
* @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
* {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
- * not used, {@code outerwidth} is used instead
+ * not used, {@code outerWidth} is used instead
*/
public BoringLayout(CharSequence source, TextPaint paint, int outerWidth, Alignment align,
float spacingMult, float spacingAdd, BoringLayout.Metrics metrics, boolean includePad,
@@ -286,10 +294,14 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
* @param includePad set whether to include extra space beyond font ascent and descent which is
* needed to avoid clipping in some scripts
* @param ellipsize whether to ellipsize the text if width of the text is longer than the
- * requested {@code outerwidth}
+ * requested {@code outerWidth}
* @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
* {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
- * not used, {@code outerwidth} is used instead
+ * not used, {@code outerWidth} is used instead
+ * @param useFallbackLineSpacing True for adjusting the line spacing based on fallback fonts.
+ * False for keeping the first font's line height. If some glyphs
+ * requires larger vertical spaces, by passing true to this
+ * argument, the layout increase the line height to fit all glyphs.
*/
public BoringLayout(
@NonNull CharSequence source, @NonNull TextPaint paint,
@@ -443,7 +455,10 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
* @param text a text to be calculated text layout.
* @param paint a paint object used for styling.
* @param textDir a text direction.
- * @param useFallbackLineSpacing true if use fallback line spacing, otherwise false.
+ * @param useFallbackLineSpacing True for adjusting the line spacing based on fallback fonts.
+ * False for keeping the first font's line height. If some glyphs
+ * requires larger vertical spaces, by passing true to this
+ * argument, the layout increase the line height to fit all glyphs.
* @param metrics the out metrics.
* @return metrics on success. null if text cannot be rendered by BoringLayout.
*/
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 32b3bc62a8cd..2f7fb2f0ab9d 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -143,9 +143,9 @@ public final class FontConfig implements Parcelable {
@Override
public FontConfig createFromParcel(Parcel source) {
List<FontFamily> families = source.readParcelableList(new ArrayList<>(),
- FontFamily.class.getClassLoader(), android.text.FontConfig.FontFamily.class);
+ FontFamily.class.getClassLoader());
List<Alias> aliases = source.readParcelableList(new ArrayList<>(),
- Alias.class.getClassLoader(), android.text.FontConfig.Alias.class);
+ Alias.class.getClassLoader());
long lastModifiedDate = source.readLong();
int configVersion = source.readInt();
return new FontConfig(families, aliases, lastModifiedDate, configVersion);
@@ -617,7 +617,7 @@ public final class FontConfig implements Parcelable {
@Override
public FontFamily createFromParcel(Parcel source) {
List<Font> fonts = source.readParcelableList(
- new ArrayList<>(), Font.class.getClassLoader(), android.text.FontConfig.Font.class);
+ new ArrayList<>(), Font.class.getClassLoader());
String name = source.readString8();
String langTags = source.readString8();
int variant = source.readInt();
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 2b396612cf3c..49e21110d679 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -860,15 +860,14 @@ public class TextLine {
final int previousBottom = fmi.bottom;
final int previousLeading = fmi.leading;
+ int count = end - start;
+ int contextCount = contextEnd - contextStart;
if (mCharsValid) {
- int count = end - start;
- int contextCount = contextEnd - contextStart;
wp.getFontMetricsInt(mChars, start, count, contextStart, contextCount, runIsRtl,
fmi);
} else {
- int delta = mStart;
- wp.getFontMetricsInt(mText, delta + start, delta + end,
- delta + contextStart, delta + contextEnd, runIsRtl, fmi);
+ wp.getFontMetricsInt(mText, mStart + start, count, mStart + contextStart, contextCount,
+ runIsRtl, fmi);
}
updateMetrics(fmi, previousTop, previousAscent, previousDescent, previousBottom,
diff --git a/core/java/android/text/style/EasyEditSpan.java b/core/java/android/text/style/EasyEditSpan.java
index 3da83332d62e..ccccdcf88b69 100644
--- a/core/java/android/text/style/EasyEditSpan.java
+++ b/core/java/android/text/style/EasyEditSpan.java
@@ -82,7 +82,7 @@ public class EasyEditSpan implements ParcelableSpan {
* Constructor called from {@link TextUtils} to restore the span.
*/
public EasyEditSpan(@NonNull Parcel source) {
- mPendingIntent = source.readParcelable(null, android.app.PendingIntent.class);
+ mPendingIntent = source.readParcelable(null);
mDeleteEnabled = (source.readByte() == 1);
}
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index adb379a397b7..23557694a48d 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -249,7 +249,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl
mTypeface = LeakyTypefaceStorage.readTypefaceFromParcel(src);
mTextFontWeight = src.readInt();
- mTextLocales = src.readParcelable(LocaleList.class.getClassLoader(), android.os.LocaleList.class);
+ mTextLocales = src.readParcelable(LocaleList.class.getClassLoader());
mShadowRadius = src.readFloat();
mShadowDx = src.readFloat();
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index 5cbbbef2cf88..42181c3c1722 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -80,7 +80,7 @@ public final class MemoryIntArray implements Parcelable, Closeable {
private MemoryIntArray(Parcel parcel) throws IOException {
mIsOwner = false;
- ParcelFileDescriptor pfd = parcel.readParcelable(null, android.os.ParcelFileDescriptor.class);
+ ParcelFileDescriptor pfd = parcel.readParcelable(null);
if (pfd == null) {
throw new IOException("No backing file descriptor");
}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 678c80a2094b..b8614ccde6fd 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -449,8 +449,8 @@ public final class DisplayInfo implements Parcelable {
type = source.readInt();
displayId = source.readInt();
displayGroupId = source.readInt();
- address = source.readParcelable(null, android.view.DisplayAddress.class);
- deviceProductInfo = source.readParcelable(null, android.hardware.display.DeviceProductInfo.class);
+ address = source.readParcelable(null);
+ deviceProductInfo = source.readParcelable(null);
name = source.readString8();
appWidth = source.readInt();
appHeight = source.readInt();
@@ -475,7 +475,7 @@ public final class DisplayInfo implements Parcelable {
for (int i = 0; i < nColorModes; i++) {
supportedColorModes[i] = source.readInt();
}
- hdrCapabilities = source.readParcelable(null, android.view.Display.HdrCapabilities.class);
+ hdrCapabilities = source.readParcelable(null);
minimalPostProcessingSupported = source.readBoolean();
logicalDensityDpi = source.readInt();
physicalXDpi = source.readFloat();
diff --git a/core/java/android/view/KeyboardShortcutInfo.java b/core/java/android/view/KeyboardShortcutInfo.java
index 118b03ce5504..2660e74dcb20 100644
--- a/core/java/android/view/KeyboardShortcutInfo.java
+++ b/core/java/android/view/KeyboardShortcutInfo.java
@@ -91,7 +91,7 @@ public final class KeyboardShortcutInfo implements Parcelable {
private KeyboardShortcutInfo(Parcel source) {
mLabel = source.readCharSequence();
- mIcon = source.readParcelable(null, android.graphics.drawable.Icon.class);
+ mIcon = source.readParcelable(null);
mBaseCharacter = (char) source.readInt();
mKeycode = source.readInt();
mModifiers = source.readInt();
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 2b5e286e89e4..d160be59cca3 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -29,6 +29,13 @@ per-file KeyEvent.java = file:/services/core/java/com/android/server/input/OWNER
per-file MotionEvent.java = file:/services/core/java/com/android/server/input/OWNERS
per-file PointerIcon.java = file:/services/core/java/com/android/server/input/OWNERS
per-file SimulatedDpad.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file BatchedInputEventReceiver.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file DragEvent.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file DragEvent.aidl = file:/services/core/java/com/android/server/input/OWNERS
+per-file GestureDetector.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file ScaleGestureDetector.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file KeyboardShortcut*.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file KeyCharacterMap.java = file:/services/core/java/com/android/server/input/OWNERS
# InputWindowHandle
per-file InputWindowHandle.java = file:/services/core/java/com/android/server/input/OWNERS
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 258359e98264..2307a039bfa5 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -15012,8 +15012,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* @return true if this view and all ancestors are visible as of the last
* {@link #onVisibilityAggregated(boolean)} call.
+ *
+ * @hide
*/
- boolean isAggregatedVisible() {
+ public boolean isAggregatedVisible() {
return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
}
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 07d5fc533a3a..25e0eca12bf3 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -1896,7 +1896,7 @@ public class ViewDebug {
private Canvas mCanvas;
private Bitmap mBitmap;
- private boolean mEnabledHwBitmapsInSwMode;
+ private boolean mEnabledHwFeaturesInSwMode;
@Override
public Canvas getCanvas(View view, int width, int height) {
@@ -1913,7 +1913,7 @@ public class ViewDebug {
if (mCanvas == null) {
mCanvas = new Canvas();
}
- mEnabledHwBitmapsInSwMode = mCanvas.isHwBitmapsInSwModeEnabled();
+ mEnabledHwFeaturesInSwMode = mCanvas.isHwFeaturesInSwModeEnabled();
mCanvas.setBitmap(mBitmap);
return mCanvas;
}
@@ -1921,7 +1921,7 @@ public class ViewDebug {
@Override
public Bitmap createBitmap() {
mCanvas.setBitmap(null);
- mCanvas.setHwBitmapsInSwModeEnabled(mEnabledHwBitmapsInSwMode);
+ mCanvas.setHwFeaturesInSwModeEnabled(mEnabledHwFeaturesInSwMode);
return mBitmap;
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index a427ab8fe837..6ad2d9a7adb1 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -1315,7 +1315,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
record.mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
record.mBeforeText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
record.mParcelableData = parcel.readParcelable(null);
- parcel.readList(record.mText, null, java.lang.CharSequence.class);
+ parcel.readList(record.mText, null);
record.mSourceWindowId = parcel.readInt();
record.mSourceNodeId = parcel.readLong();
record.mSourceDisplayId = parcel.readInt();
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index 36e779a44e70..67e6d3f2aec3 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -84,6 +84,12 @@ public final class AccessibilityWindowInfo implements Parcelable {
*/
public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5;
+ /**
+ * Window type: A system window used to show the UI for the interaction with
+ * window-based magnification, which includes the magnified content and the option menu.
+ */
+ public static final int TYPE_MAGNIFICATION_OVERLAY = 6;
+
/* Special values for window IDs */
/** @hide */
public static final int ACTIVE_WINDOW_ID = Integer.MAX_VALUE;
@@ -801,6 +807,9 @@ public final class AccessibilityWindowInfo implements Parcelable {
case TYPE_SPLIT_SCREEN_DIVIDER: {
return "TYPE_SPLIT_SCREEN_DIVIDER";
}
+ case TYPE_MAGNIFICATION_OVERLAY: {
+ return "TYPE_MAGNIFICATION_OVERLAY";
+ }
default:
return "<UNKNOWN:" + type + ">";
}
@@ -908,7 +917,7 @@ public final class AccessibilityWindowInfo implements Parcelable {
final int count = source.readInt();
for (int i = 0; i < count; i++) {
List<AccessibilityWindowInfo> windows = new ArrayList<>();
- source.readParcelableList(windows, loader, android.view.accessibility.AccessibilityWindowInfo.class);
+ source.readParcelableList(windows, loader);
array.put(source.readInt(), windows);
}
return array;
diff --git a/core/java/android/view/autofill/ParcelableMap.java b/core/java/android/view/autofill/ParcelableMap.java
index 3fa7734e56fc..d8459aa22fa1 100644
--- a/core/java/android/view/autofill/ParcelableMap.java
+++ b/core/java/android/view/autofill/ParcelableMap.java
@@ -56,8 +56,8 @@ class ParcelableMap extends HashMap<AutofillId, AutofillValue> implements Parcel
ParcelableMap map = new ParcelableMap(size);
for (int i = 0; i < size; i++) {
- AutofillId key = source.readParcelable(null, android.view.autofill.AutofillId.class);
- AutofillValue value = source.readParcelable(null, android.view.autofill.AutofillValue.class);
+ AutofillId key = source.readParcelable(null);
+ AutofillValue value = source.readParcelable(null);
map.put(key, value);
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureCondition.java b/core/java/android/view/contentcapture/ContentCaptureCondition.java
index 685ea1aeaba8..027c8d20ccc6 100644
--- a/core/java/android/view/contentcapture/ContentCaptureCondition.java
+++ b/core/java/android/view/contentcapture/ContentCaptureCondition.java
@@ -133,7 +133,7 @@ public final class ContentCaptureCondition implements Parcelable {
@Override
public ContentCaptureCondition createFromParcel(@NonNull Parcel parcel) {
- return new ContentCaptureCondition(parcel.readParcelable(null, android.content.LocusId.class),
+ return new ContentCaptureCondition(parcel.readParcelable(null),
parcel.readInt());
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 59b5286f6fc5..3bc9a967ea20 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -419,7 +419,7 @@ public final class ContentCaptureContext implements Parcelable {
final ContentCaptureContext clientContext;
if (hasClientContext) {
// Must reconstruct the client context using the Builder API
- final LocusId id = parcel.readParcelable(null, android.content.LocusId.class);
+ final LocusId id = parcel.readParcelable(null);
final Bundle extras = parcel.readBundle();
final Builder builder = new Builder(id);
if (extras != null) builder.setExtras(extras);
@@ -427,7 +427,7 @@ public final class ContentCaptureContext implements Parcelable {
} else {
clientContext = null;
}
- final ComponentName componentName = parcel.readParcelable(null, android.content.ComponentName.class);
+ final ComponentName componentName = parcel.readParcelable(null);
if (componentName == null) {
// Client-state only
return clientContext;
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index ba4176faa283..0f4bc191fe4e 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -620,7 +620,7 @@ public final class ContentCaptureEvent implements Parcelable {
final int type = parcel.readInt();
final long eventTime = parcel.readLong();
final ContentCaptureEvent event = new ContentCaptureEvent(sessionId, type, eventTime);
- final AutofillId id = parcel.readParcelable(null, android.view.autofill.AutofillId.class);
+ final AutofillId id = parcel.readParcelable(null);
if (id != null) {
event.setAutofillId(id);
}
@@ -637,13 +637,13 @@ public final class ContentCaptureEvent implements Parcelable {
event.setParentSessionId(parcel.readInt());
}
if (type == TYPE_SESSION_STARTED || type == TYPE_CONTEXT_UPDATED) {
- event.setClientContext(parcel.readParcelable(null, android.view.contentcapture.ContentCaptureContext.class));
+ event.setClientContext(parcel.readParcelable(null));
}
if (type == TYPE_VIEW_INSETS_CHANGED) {
- event.setInsets(parcel.readParcelable(null, android.graphics.Insets.class));
+ event.setInsets(parcel.readParcelable(null));
}
if (type == TYPE_WINDOW_BOUNDS_CHANGED) {
- event.setBounds(parcel.readParcelable(null, android.graphics.Rect.class));
+ event.setBounds(parcel.readParcelable(null));
}
if (type == TYPE_VIEW_TEXT_CHANGED) {
event.setComposingIndex(parcel.readInt(), parcel.readInt());
diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java
index 1762a5817aaf..1b4a00f81e44 100644
--- a/core/java/android/view/contentcapture/ViewNode.java
+++ b/core/java/android/view/contentcapture/ViewNode.java
@@ -124,10 +124,10 @@ public final class ViewNode extends AssistStructure.ViewNode {
mFlags = nodeFlags;
if ((nodeFlags & FLAGS_HAS_AUTOFILL_ID) != 0) {
- mAutofillId = parcel.readParcelable(null, android.view.autofill.AutofillId.class);
+ mAutofillId = parcel.readParcelable(null);
}
if ((nodeFlags & FLAGS_HAS_AUTOFILL_PARENT_ID) != 0) {
- mParentAutofillId = parcel.readParcelable(null, android.view.autofill.AutofillId.class);
+ mParentAutofillId = parcel.readParcelable(null);
}
if ((nodeFlags & FLAGS_HAS_TEXT) != 0) {
mText = new ViewNodeText(parcel, (nodeFlags & FLAGS_HAS_COMPLEX_TEXT) == 0);
@@ -169,7 +169,7 @@ public final class ViewNode extends AssistStructure.ViewNode {
mExtras = parcel.readBundle();
}
if ((nodeFlags & FLAGS_HAS_LOCALE_LIST) != 0) {
- mLocaleList = parcel.readParcelable(null, android.os.LocaleList.class);
+ mLocaleList = parcel.readParcelable(null);
}
if ((nodeFlags & FLAGS_HAS_MIME_TYPES) != 0) {
mReceiveContentMimeTypes = parcel.readStringArray();
@@ -196,7 +196,7 @@ public final class ViewNode extends AssistStructure.ViewNode {
mAutofillHints = parcel.readStringArray();
}
if ((nodeFlags & FLAGS_HAS_AUTOFILL_VALUE) != 0) {
- mAutofillValue = parcel.readParcelable(null, android.view.autofill.AutofillValue.class);
+ mAutofillValue = parcel.readParcelable(null);
}
if ((nodeFlags & FLAGS_HAS_AUTOFILL_OPTIONS) != 0) {
mAutofillOptions = parcel.readCharSequenceArray();
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfo.java b/core/java/android/view/inputmethod/CursorAnchorInfo.java
index 437e54f635ee..fbc947071c99 100644
--- a/core/java/android/view/inputmethod/CursorAnchorInfo.java
+++ b/core/java/android/view/inputmethod/CursorAnchorInfo.java
@@ -140,7 +140,7 @@ public final class CursorAnchorInfo implements Parcelable {
mInsertionMarkerTop = source.readFloat();
mInsertionMarkerBaseline = source.readFloat();
mInsertionMarkerBottom = source.readFloat();
- mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader(), android.view.inputmethod.SparseRectFArray.class);
+ mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
mMatrixValues = source.createFloatArray();
}
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 09a14484095e..4cbd477d807a 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -1067,7 +1067,7 @@ public class EditorInfo implements InputType, Parcelable {
res.hintText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
res.label = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
res.packageName = source.readString();
- res.autofillId = source.readParcelable(AutofillId.class.getClassLoader(), android.view.autofill.AutofillId.class);
+ res.autofillId = source.readParcelable(AutofillId.class.getClassLoader());
res.fieldId = source.readInt();
res.fieldName = source.readString();
res.extras = source.readBundle();
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
index 70279cc8e845..e1e175512edc 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsRequest.java
@@ -490,7 +490,7 @@ public final class InlineSuggestionsRequest implements Parcelable {
boolean clientSupported = (flg & 0x200) != 0;
int maxSuggestionCount = in.readInt();
List<InlinePresentationSpec> inlinePresentationSpecs = new ArrayList<>();
- in.readParcelableList(inlinePresentationSpecs, InlinePresentationSpec.class.getClassLoader(), android.widget.inline.InlinePresentationSpec.class);
+ in.readParcelableList(inlinePresentationSpecs, InlinePresentationSpec.class.getClassLoader());
String hostPackageName = in.readString();
LocaleList supportedLocales = (LocaleList) in.readTypedObject(LocaleList.CREATOR);
Bundle extras = in.readBundle();
diff --git a/core/java/android/view/inputmethod/InlineSuggestionsResponse.java b/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
index 532fc85dcc44..b393c67d7876 100644
--- a/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
+++ b/core/java/android/view/inputmethod/InlineSuggestionsResponse.java
@@ -170,7 +170,7 @@ public final class InlineSuggestionsResponse implements Parcelable {
// static FieldType unparcelFieldName(Parcel in) { ... }
List<InlineSuggestion> inlineSuggestions = new ArrayList<>();
- in.readParcelableList(inlineSuggestions, InlineSuggestion.class.getClassLoader(), android.view.inputmethod.InlineSuggestion.class);
+ in.readParcelableList(inlineSuggestions, InlineSuggestion.class.getClassLoader());
this.mInlineSuggestions = inlineSuggestions;
com.android.internal.util.AnnotationValidations.validate(
diff --git a/core/java/android/view/textclassifier/ConversationAction.java b/core/java/android/view/textclassifier/ConversationAction.java
index a4a5a1ed0ac9..bf0409dfc919 100644
--- a/core/java/android/view/textclassifier/ConversationAction.java
+++ b/core/java/android/view/textclassifier/ConversationAction.java
@@ -141,7 +141,7 @@ public final class ConversationAction implements Parcelable {
private ConversationAction(Parcel in) {
mType = in.readString();
- mAction = in.readParcelable(null, android.app.RemoteAction.class);
+ mAction = in.readParcelable(null);
mTextReply = in.readCharSequence();
mScore = in.readFloat();
mExtras = in.readBundle();
diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java
index 7a6a3cd026fd..6ad5cb913553 100644
--- a/core/java/android/view/textclassifier/ConversationActions.java
+++ b/core/java/android/view/textclassifier/ConversationActions.java
@@ -149,7 +149,7 @@ public final class ConversationActions implements Parcelable {
}
private Message(Parcel in) {
- mAuthor = in.readParcelable(null, android.app.Person.class);
+ mAuthor = in.readParcelable(null);
mReferenceTime =
in.readInt() == 0
? null
@@ -331,13 +331,13 @@ public final class ConversationActions implements Parcelable {
private static Request readFromParcel(Parcel in) {
List<Message> conversation = new ArrayList<>();
- in.readParcelableList(conversation, null, android.view.textclassifier.ConversationActions.Message.class);
- TextClassifier.EntityConfig typeConfig = in.readParcelable(null, android.view.textclassifier.TextClassifier.EntityConfig.class);
+ in.readParcelableList(conversation, null);
+ TextClassifier.EntityConfig typeConfig = in.readParcelable(null);
int maxSuggestions = in.readInt();
List<String> hints = new ArrayList<>();
in.readStringList(hints);
Bundle extras = in.readBundle();
- SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null, android.view.textclassifier.SystemTextClassifierMetadata.class);
+ SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null);
Request request = new Request(
conversation,
diff --git a/core/java/android/view/textclassifier/SelectionEvent.java b/core/java/android/view/textclassifier/SelectionEvent.java
index b34701082b80..858825b1d5ac 100644
--- a/core/java/android/view/textclassifier/SelectionEvent.java
+++ b/core/java/android/view/textclassifier/SelectionEvent.java
@@ -172,7 +172,7 @@ public final class SelectionEvent implements Parcelable {
mEnd = in.readInt();
mSmartStart = in.readInt();
mSmartEnd = in.readInt();
- mSystemTcMetadata = in.readParcelable(null, android.view.textclassifier.SystemTextClassifierMetadata.class);
+ mSystemTcMetadata = in.readParcelable(null);
}
@Override
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 8b04d35734ec..7db35d4bf8b5 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -713,12 +713,12 @@ public final class TextClassification implements Parcelable {
final CharSequence text = in.readCharSequence();
final int startIndex = in.readInt();
final int endIndex = in.readInt();
- final LocaleList defaultLocales = in.readParcelable(null, android.os.LocaleList.class);
+ final LocaleList defaultLocales = in.readParcelable(null);
final String referenceTimeString = in.readString();
final ZonedDateTime referenceTime = referenceTimeString == null
? null : ZonedDateTime.parse(referenceTimeString);
final Bundle extras = in.readBundle();
- final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null, android.view.textclassifier.SystemTextClassifierMetadata.class);
+ final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null);
final Request request = new Request(text, startIndex, endIndex,
defaultLocales, referenceTime, extras);
diff --git a/core/java/android/view/textclassifier/TextClassificationContext.java b/core/java/android/view/textclassifier/TextClassificationContext.java
index 3a50809ea8b4..5d5683f7110e 100644
--- a/core/java/android/view/textclassifier/TextClassificationContext.java
+++ b/core/java/android/view/textclassifier/TextClassificationContext.java
@@ -159,7 +159,7 @@ public final class TextClassificationContext implements Parcelable {
mPackageName = in.readString();
mWidgetType = in.readString();
mWidgetVersion = in.readString();
- mSystemTcMetadata = in.readParcelable(null, android.view.textclassifier.SystemTextClassifierMetadata.class);
+ mSystemTcMetadata = in.readParcelable(null);
}
public static final @android.annotation.NonNull Parcelable.Creator<TextClassificationContext> CREATOR =
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index 195565c5bc09..90667cf54f93 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -189,7 +189,7 @@ public abstract class TextClassifierEvent implements Parcelable {
mEventCategory = in.readInt();
mEventType = in.readInt();
mEntityTypes = in.readStringArray();
- mEventContext = in.readParcelable(null, android.view.textclassifier.TextClassificationContext.class);
+ mEventContext = in.readParcelable(null);
mResultId = in.readString();
mEventIndex = in.readInt();
int scoresLength = in.readInt();
diff --git a/core/java/android/view/textclassifier/TextLanguage.java b/core/java/android/view/textclassifier/TextLanguage.java
index 67167c6d3e65..604979b1ac78 100644
--- a/core/java/android/view/textclassifier/TextLanguage.java
+++ b/core/java/android/view/textclassifier/TextLanguage.java
@@ -295,7 +295,7 @@ public final class TextLanguage implements Parcelable {
private static Request readFromParcel(Parcel in) {
final CharSequence text = in.readCharSequence();
final Bundle extra = in.readBundle();
- final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null, android.view.textclassifier.SystemTextClassifierMetadata.class);
+ final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null);
final Request request = new Request(text, extra);
request.setSystemTextClassifierMetadata(systemTcMetadata);
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index 445e9ecff54f..dea3a9010b18 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -558,13 +558,13 @@ public final class TextLinks implements Parcelable {
private static Request readFromParcel(Parcel in) {
final String text = in.readString();
- final LocaleList defaultLocales = in.readParcelable(null, android.os.LocaleList.class);
- final EntityConfig entityConfig = in.readParcelable(null, android.view.textclassifier.TextClassifier.EntityConfig.class);
+ final LocaleList defaultLocales = in.readParcelable(null);
+ final EntityConfig entityConfig = in.readParcelable(null);
final Bundle extras = in.readBundle();
final String referenceTimeString = in.readString();
final ZonedDateTime referenceTime = referenceTimeString == null
? null : ZonedDateTime.parse(referenceTimeString);
- final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null, android.view.textclassifier.SystemTextClassifierMetadata.class);
+ final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null);
final Request request = new Request(text, defaultLocales, entityConfig,
/* legacyFallback= */ true, referenceTime, extras);
diff --git a/core/java/android/view/textclassifier/TextSelection.java b/core/java/android/view/textclassifier/TextSelection.java
index dda0fcdd44fd..c1913f69546c 100644
--- a/core/java/android/view/textclassifier/TextSelection.java
+++ b/core/java/android/view/textclassifier/TextSelection.java
@@ -489,9 +489,9 @@ public final class TextSelection implements Parcelable {
final CharSequence text = in.readCharSequence();
final int startIndex = in.readInt();
final int endIndex = in.readInt();
- final LocaleList defaultLocales = in.readParcelable(null, android.os.LocaleList.class);
+ final LocaleList defaultLocales = in.readParcelable(null);
final Bundle extras = in.readBundle();
- final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null, android.view.textclassifier.SystemTextClassifierMetadata.class);
+ final SystemTextClassifierMetadata systemTcMetadata = in.readParcelable(null);
final boolean includeTextClassification = in.readBoolean();
final Request request = new Request(text, startIndex, endIndex, defaultLocales,
@@ -548,6 +548,6 @@ public final class TextSelection implements Parcelable {
mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
mId = in.readString();
mExtras = in.readBundle();
- mTextClassification = in.readParcelable(TextClassification.class.getClassLoader(), android.view.textclassifier.TextClassification.class);
+ mTextClassification = in.readParcelable(TextClassification.class.getClassLoader());
}
}
diff --git a/core/java/android/view/translation/TranslationRequest.java b/core/java/android/view/translation/TranslationRequest.java
index 027edc21389f..0d41851ca704 100644
--- a/core/java/android/view/translation/TranslationRequest.java
+++ b/core/java/android/view/translation/TranslationRequest.java
@@ -255,9 +255,9 @@ public final class TranslationRequest implements Parcelable {
int flags = in.readInt();
List<TranslationRequestValue> translationRequestValues = new ArrayList<>();
- in.readParcelableList(translationRequestValues, TranslationRequestValue.class.getClassLoader(), android.view.translation.TranslationRequestValue.class);
+ in.readParcelableList(translationRequestValues, TranslationRequestValue.class.getClassLoader());
List<ViewTranslationRequest> viewTranslationRequests = new ArrayList<>();
- in.readParcelableList(viewTranslationRequests, ViewTranslationRequest.class.getClassLoader(), android.view.translation.ViewTranslationRequest.class);
+ in.readParcelableList(viewTranslationRequests, ViewTranslationRequest.class.getClassLoader());
this.mFlags = flags;
diff --git a/core/java/android/view/translation/TranslationSpec.java b/core/java/android/view/translation/TranslationSpec.java
index 76dda5fbe83b..efc3d8ba8096 100644
--- a/core/java/android/view/translation/TranslationSpec.java
+++ b/core/java/android/view/translation/TranslationSpec.java
@@ -64,7 +64,7 @@ public final class TranslationSpec implements Parcelable {
}
static ULocale unparcelLocale(Parcel in) {
- return (ULocale) in.readSerializable(android.icu.util.ULocale.class.getClassLoader(), android.icu.util.ULocale.class);
+ return (ULocale) in.readSerializable();
}
/**
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index e243aae81da4..51869d4e04d5 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -1309,7 +1309,7 @@ public class ExpandableListView extends ListView {
private SavedState(Parcel in) {
super(in);
expandedGroupMetadataList = new ArrayList<ExpandableListConnector.GroupMetadata>();
- in.readList(expandedGroupMetadataList, ExpandableListConnector.class.getClassLoader(), android.widget.ExpandableListConnector.GroupMetadata.class);
+ in.readList(expandedGroupMetadataList, ExpandableListConnector.class.getClassLoader());
}
@Override
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 6d58ee22b159..e60f9a648730 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1489,7 +1489,7 @@ public class RemoteViews implements Parcelable, Filter {
SetRippleDrawableColor(Parcel parcel) {
viewId = parcel.readInt();
- mColorStateList = parcel.readParcelable(null, android.content.res.ColorStateList.class);
+ mColorStateList = parcel.readParcelable(null);
}
public void writeToParcel(Parcel dest, int flags) {
@@ -6628,6 +6628,7 @@ public class RemoteViews implements Parcelable, Filter {
opts = ActivityOptions.makeBasic();
opts.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
+ opts.setLaunchDisplayId(view.getDisplay().getDisplayId());
return Pair.create(intent, opts);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7327214c5389..1a808b2e7c24 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10689,8 +10689,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return;
}
- if ((mMarquee == null || mMarquee.isStopped()) && (isFocused() || isSelected())
- && getLineCount() == 1 && canMarquee()) {
+ if ((mMarquee == null || mMarquee.isStopped()) && isAggregatedVisible()
+ && (isFocused() || isSelected()) && getLineCount() == 1 && canMarquee()) {
if (mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_FADE;
@@ -11149,6 +11149,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ @Override
+ public void onVisibilityAggregated(boolean isVisible) {
+ super.onVisibilityAggregated(isVisible);
+ startStopMarquee(isVisible);
+ }
+
/**
* Use {@link BaseInputConnection#removeComposingSpans
* BaseInputConnection.removeComposingSpans()} to remove any IME composing
@@ -13802,7 +13808,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mChoreographer.removeFrameCallback(mTickCallback);
final TextView textView = mView.get();
- if (textView != null && (textView.isFocused() || textView.isSelected())) {
+ if (textView != null && textView.isAggregatedVisible()
+ && (textView.isFocused() || textView.isSelected())) {
long currentMs = mChoreographer.getFrameTime();
long deltaMs = currentMs - mLastAnimationMs;
mLastAnimationMs = currentMs;
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java
index 974a1dd50cf5..88ece5c536f6 100644
--- a/core/java/android/window/DisplayAreaOrganizer.java
+++ b/core/java/android/window/DisplayAreaOrganizer.java
@@ -101,14 +101,6 @@ public class DisplayAreaOrganizer extends WindowOrganizer {
public static final int FEATURE_IME_PLACEHOLDER = FEATURE_SYSTEM_FIRST + 7;
/**
- * Display area for one handed background layer, which preventing when user
- * turning the Dark theme on, they can not clearly identify the screen has entered
- * one handed mode.
- * @hide
- */
- public static final int FEATURE_ONE_HANDED_BACKGROUND_PANEL = FEATURE_SYSTEM_FIRST + 8;
-
- /**
* Display area hosting IME window tokens (@see ImeContainer). By default, IMEs are parented
* to FEATURE_IME_PLACEHOLDER but can be reparented under other RootDisplayArea.
*
@@ -118,7 +110,7 @@ public class DisplayAreaOrganizer extends WindowOrganizer {
* app on another screen).
* @hide
*/
- public static final int FEATURE_IME = FEATURE_SYSTEM_FIRST + 9;
+ public static final int FEATURE_IME = FEATURE_SYSTEM_FIRST + 8;
/**
* The last boundary of display area for system features
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
index d709acfc2872..6f83bf3224a8 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsCapInfo.java
@@ -89,6 +89,6 @@ public class OptionsCapInfo implements Parcelable {
public void readFromParcel(Parcel source) {
mSdp = source.readString();
- mCapInfo = source.readParcelable(CapInfo.class.getClassLoader(), com.android.ims.internal.uce.common.CapInfo.class);
+ mCapInfo = source.readParcelable(CapInfo.class.getClassLoader());
}
} \ No newline at end of file
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
index 559d61b20d8c..461f8bfb48c8 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsCmdStatus.java
@@ -147,8 +147,8 @@ public class OptionsCmdStatus implements Parcelable {
/** @hide */
public void readFromParcel(Parcel source) {
mUserData = source.readInt();
- mCmdId = source.readParcelable(OptionsCmdId.class.getClassLoader(), com.android.ims.internal.uce.options.OptionsCmdId.class);
- mStatus = source.readParcelable(StatusCode.class.getClassLoader(), com.android.ims.internal.uce.common.StatusCode.class);
- mCapInfo = source.readParcelable(CapInfo.class.getClassLoader(), com.android.ims.internal.uce.common.CapInfo.class);
+ mCmdId = source.readParcelable(OptionsCmdId.class.getClassLoader());
+ mStatus = source.readParcelable(StatusCode.class.getClassLoader());
+ mCapInfo = source.readParcelable(CapInfo.class.getClassLoader());
}
} \ No newline at end of file
diff --git a/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
index 160f9ebaebc8..32420816f5ab 100644
--- a/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
+++ b/core/java/com/android/ims/internal/uce/options/OptionsSipResponse.java
@@ -180,7 +180,7 @@ public class OptionsSipResponse implements Parcelable {
mRequestId = source.readInt();
mSipResponseCode = source.readInt();
mReasonPhrase = source.readString();
- mCmdId = source.readParcelable(OptionsCmdId.class.getClassLoader(), com.android.ims.internal.uce.options.OptionsCmdId.class);
+ mCmdId = source.readParcelable(OptionsCmdId.class.getClassLoader());
mRetryAfter = source.readInt();
mReasonHeader = source.readString();
}
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
index f0ee5f3bb77d..ec8b6bfa4ef3 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresCapInfo.java
@@ -105,6 +105,6 @@ public class PresCapInfo implements Parcelable {
/** @hide */
public void readFromParcel(Parcel source) {
mContactUri = source.readString();
- mCapInfo = source.readParcelable(CapInfo.class.getClassLoader(), com.android.ims.internal.uce.common.CapInfo.class);
+ mCapInfo = source.readParcelable(CapInfo.class.getClassLoader());
}
}
diff --git a/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
index 8fbb000c20f5..7e22106f3be3 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresCmdStatus.java
@@ -146,8 +146,8 @@ public class PresCmdStatus implements Parcelable{
public void readFromParcel(Parcel source) {
mUserData = source.readInt();
mRequestId = source.readInt();
- mCmdId = source.readParcelable(PresCmdId.class.getClassLoader(), com.android.ims.internal.uce.presence.PresCmdId.class);
- mStatus = source.readParcelable(StatusCode.class.getClassLoader(), com.android.ims.internal.uce.common.StatusCode.class);
+ mCmdId = source.readParcelable(PresCmdId.class.getClassLoader());
+ mStatus = source.readParcelable(StatusCode.class.getClassLoader());
}
} \ No newline at end of file
diff --git a/core/java/com/android/ims/internal/uce/presence/PresResInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
index 954c2b61c286..2f797b41b14f 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresResInfo.java
@@ -122,6 +122,6 @@ public class PresResInfo implements Parcelable {
public void readFromParcel(Parcel source) {
mResUri = source.readString();
mDisplayName = source.readString();
- mInstanceInfo = source.readParcelable(PresResInstanceInfo.class.getClassLoader(), com.android.ims.internal.uce.presence.PresResInstanceInfo.class);
+ mInstanceInfo = source.readParcelable(PresResInstanceInfo.class.getClassLoader());
}
} \ No newline at end of file
diff --git a/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
index 733c0afff367..0130ef47010a 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresResInstanceInfo.java
@@ -190,7 +190,7 @@ public class PresResInstanceInfo implements Parcelable{
mResInstanceState = source.readInt();
mPresentityUri = source.readString();
Parcelable[] tempParcelableArray = source.readParcelableArray(
- PresTupleInfo.class.getClassLoader());
+ PresTupleInfo.class.getClassLoader(), PresTupleInfo.class);
mTupleInfoArray = new PresTupleInfo[] {};
if(tempParcelableArray != null) {
mTupleInfoArray = Arrays.copyOf(tempParcelableArray, tempParcelableArray.length,
diff --git a/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
index 63247dbd8172..e33aa1303886 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresRlmiInfo.java
@@ -236,7 +236,7 @@ public class PresRlmiInfo implements Parcelable {
mListName = source.readString();
mRequestId = source.readInt();
mPresSubscriptionState = source.readParcelable(
- PresSubscriptionState.class.getClassLoader(), com.android.ims.internal.uce.presence.PresSubscriptionState.class);
+ PresSubscriptionState.class.getClassLoader());
mSubscriptionExpireTime = source.readInt();
mSubscriptionTerminatedReason = source.readString();
}
diff --git a/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
index 8097a3797556..5e394efed294 100644
--- a/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
+++ b/core/java/com/android/ims/internal/uce/presence/PresSipResponse.java
@@ -185,7 +185,7 @@ public class PresSipResponse implements Parcelable {
mRequestId = source.readInt();
mSipResponseCode = source.readInt();
mReasonPhrase = source.readString();
- mCmdId = source.readParcelable(PresCmdId.class.getClassLoader(), com.android.ims.internal.uce.presence.PresCmdId.class);
+ mCmdId = source.readParcelable(PresCmdId.class.getClassLoader());
mRetryAfter = source.readInt();
mReasonHeader = source.readString();
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 025f7118334c..be7388bfca13 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -759,11 +759,11 @@ public class ChooserActivity extends ResolverActivity implements
}
try {
- IBinder permissionToken = ActivityTaskManager.getService()
- .requestStartActivityPermissionToken(getActivityToken());
Intent delegationIntent = new Intent();
final ComponentName delegateActivity = ComponentName.unflattenFromString(
Resources.getSystem().getString(R.string.config_chooserActivity));
+ IBinder permissionToken = ActivityTaskManager.getService()
+ .requestStartActivityPermissionToken(delegateActivity);
delegationIntent.setComponent(delegateActivity);
delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent());
delegationIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index b273f6ded8d0..f9a8c7b58897 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -1437,11 +1437,11 @@ public class ResolverActivity extends Activity implements
try {
// TODO: Once this is a small springboard activity, it can move off the UI process
// and we can move the request method to ActivityManagerInternal.
- IBinder permissionToken = ActivityTaskManager.getService()
- .requestStartActivityPermissionToken(getActivityToken());
final Intent chooserIntent = new Intent();
final ComponentName delegateActivity = ComponentName.unflattenFromString(
Resources.getSystem().getString(R.string.config_chooserActivity));
+ IBinder permissionToken = ActivityTaskManager.getService()
+ .requestStartActivityPermissionToken(delegateActivity);
chooserIntent.setClassName(delegateActivity.getPackageName(),
delegateActivity.getClassName());
chooserIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken);
diff --git a/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java b/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java
index 289daee26f52..9c3c22451c5a 100644
--- a/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java
+++ b/core/java/com/android/internal/app/chooser/DisplayResolveInfo.java
@@ -237,11 +237,12 @@ public class DisplayResolveInfo implements TargetInfo, Parcelable {
private DisplayResolveInfo(Parcel in) {
mDisplayLabel = in.readCharSequence();
mExtendedInfo = in.readCharSequence();
- mResolvedIntent = in.readParcelable(null /* ClassLoader */, android.content.Intent.class);
+ mResolvedIntent = in.readParcelable(null /* ClassLoader */);
mSourceIntents.addAll(
- Arrays.asList((Intent[]) in.readParcelableArray(null /* ClassLoader */)));
+ Arrays.asList((Intent[]) in.readParcelableArray(null /* ClassLoader */,
+ Intent.class)));
mIsSuspended = in.readBoolean();
mPinned = in.readBoolean();
- mResolveInfo = in.readParcelable(null /* ClassLoader */, android.content.pm.ResolveInfo.class);
+ mResolveInfo = in.readParcelable(null /* ClassLoader */);
}
}
diff --git a/core/java/com/android/internal/infra/AndroidFuture.java b/core/java/com/android/internal/infra/AndroidFuture.java
index 84391c169941..0443ad03b6ea 100644
--- a/core/java/com/android/internal/infra/AndroidFuture.java
+++ b/core/java/com/android/internal/infra/AndroidFuture.java
@@ -24,7 +24,6 @@ import android.os.Looper;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
-import android.util.EventLog;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -585,6 +584,7 @@ public class AndroidFuture<T> extends CompletableFuture<T> implements Parcelable
/**
* @see #writeThrowable
*/
+ @SuppressWarnings("UnsafeParcelApi")
private static @Nullable Throwable readThrowable(@NonNull Parcel parcel) {
final boolean hasThrowable = parcel.readBoolean();
if (!hasThrowable) {
diff --git a/core/java/com/android/internal/net/LegacyVpnInfo.java b/core/java/com/android/internal/net/LegacyVpnInfo.java
index b3bc93a058cf..43984b59378c 100644
--- a/core/java/com/android/internal/net/LegacyVpnInfo.java
+++ b/core/java/com/android/internal/net/LegacyVpnInfo.java
@@ -69,7 +69,7 @@ public class LegacyVpnInfo implements Parcelable {
LegacyVpnInfo info = new LegacyVpnInfo();
info.key = in.readString();
info.state = in.readInt();
- info.intent = in.readParcelable(null, android.app.PendingIntent.class);
+ info.intent = in.readParcelable(null);
return info;
}
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 2a203acebc72..2ae56f808972 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -34,8 +34,6 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
-import java.net.Inet4Address;
-import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -93,8 +91,8 @@ public class VpnConfig implements Parcelable {
public String interfaze;
public String session;
public int mtu = -1;
- public List<LinkAddress> addresses = new ArrayList<LinkAddress>();
- public List<RouteInfo> routes = new ArrayList<RouteInfo>();
+ public List<LinkAddress> addresses = new ArrayList<>();
+ public List<RouteInfo> routes = new ArrayList<>();
public List<String> dnsServers;
public List<String> searchDomains;
public List<String> allowedApplications;
@@ -114,12 +112,32 @@ public class VpnConfig implements Parcelable {
public VpnConfig() {
}
- public void updateAllowedFamilies(InetAddress address) {
- if (address instanceof Inet4Address) {
- allowIPv4 = true;
- } else {
- allowIPv6 = true;
- }
+ public VpnConfig(VpnConfig other) {
+ user = other.user;
+ interfaze = other.interfaze;
+ session = other.session;
+ mtu = other.mtu;
+ addresses = copyOf(other.addresses);
+ routes = copyOf(other.routes);
+ dnsServers = copyOf(other.dnsServers);
+ searchDomains = copyOf(other.searchDomains);
+ allowedApplications = copyOf(other.allowedApplications);
+ disallowedApplications = copyOf(other.disallowedApplications);
+ configureIntent = other.configureIntent;
+ startTime = other.startTime;
+ legacy = other.legacy;
+ blocking = other.blocking;
+ allowBypass = other.allowBypass;
+ allowIPv4 = other.allowIPv4;
+ allowIPv6 = other.allowIPv6;
+ isMetered = other.isMetered;
+ underlyingNetworks = other.underlyingNetworks != null ? Arrays.copyOf(
+ other.underlyingNetworks, other.underlyingNetworks.length) : null;
+ proxyInfo = other.proxyInfo;
+ }
+
+ private static <T> List<T> copyOf(List<T> list) {
+ return list != null ? new ArrayList<>(list) : null;
}
public void addLegacyRoutes(String routesStr) {
@@ -131,7 +149,6 @@ public class VpnConfig implements Parcelable {
//each route is ip/prefix
RouteInfo info = new RouteInfo(new IpPrefix(route), null, null, RouteInfo.RTN_UNICAST);
this.routes.add(info);
- updateAllowedFamilies(info.getDestination().getAddress());
}
}
@@ -144,7 +161,6 @@ public class VpnConfig implements Parcelable {
//each address is ip/prefix
LinkAddress addr = new LinkAddress(address);
this.addresses.add(addr);
- updateAllowedFamilies(addr.getAddress());
}
}
@@ -192,7 +208,7 @@ public class VpnConfig implements Parcelable {
config.searchDomains = in.createStringArrayList();
config.allowedApplications = in.createStringArrayList();
config.disallowedApplications = in.createStringArrayList();
- config.configureIntent = in.readParcelable(null, android.app.PendingIntent.class);
+ config.configureIntent = in.readParcelable(null);
config.startTime = in.readLong();
config.legacy = in.readInt() != 0;
config.blocking = in.readInt() != 0;
@@ -201,7 +217,7 @@ public class VpnConfig implements Parcelable {
config.allowIPv6 = in.readInt() != 0;
config.isMetered = in.readInt() != 0;
config.underlyingNetworks = in.createTypedArray(Network.CREATOR);
- config.proxyInfo = in.readParcelable(null, android.net.ProxyInfo.class);
+ config.proxyInfo = in.readParcelable(null);
return config;
}
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index 519faa8456cc..d8dc1436128e 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -182,9 +182,9 @@ public final class VpnProfile implements Cloneable, Parcelable {
ipsecCaCert = in.readString();
ipsecServerCert = in.readString();
saveLogin = in.readInt() != 0;
- proxy = in.readParcelable(null, android.net.ProxyInfo.class);
+ proxy = in.readParcelable(null);
mAllowedAlgorithms = new ArrayList<>();
- in.readList(mAllowedAlgorithms, null, java.lang.String.class);
+ in.readList(mAllowedAlgorithms, null);
isBypassable = in.readBoolean();
isMetered = in.readBoolean();
maxMtu = in.readInt();
diff --git a/core/java/com/android/internal/os/AppFuseMount.java b/core/java/com/android/internal/os/AppFuseMount.java
index 5404fea68672..04d72117d28a 100644
--- a/core/java/com/android/internal/os/AppFuseMount.java
+++ b/core/java/com/android/internal/os/AppFuseMount.java
@@ -57,7 +57,7 @@ public class AppFuseMount implements Parcelable {
new Parcelable.Creator<AppFuseMount>() {
@Override
public AppFuseMount createFromParcel(Parcel in) {
- return new AppFuseMount(in.readInt(), in.readParcelable(null, android.os.ParcelFileDescriptor.class));
+ return new AppFuseMount(in.readInt(), in.readParcelable(null));
}
@Override
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 21f719c74aa8..9429c79697bf 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -26,6 +26,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
+import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.UidTraffic;
import android.compat.annotation.UnsupportedAppUsage;
@@ -37,7 +38,6 @@ import android.content.IntentFilter;
import android.database.ContentObserver;
import android.hardware.usb.UsbManager;
import android.location.GnssSignalQuality;
-import android.net.INetworkStatsService;
import android.net.NetworkStats;
import android.net.Uri;
import android.net.wifi.WifiManager;
@@ -137,7 +137,9 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Queue;
+import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
@@ -12534,19 +12536,11 @@ public class BatteryStatsImpl extends BatteryStats {
private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
@VisibleForTesting
- protected NetworkStats readNetworkStatsLocked(String[] ifaces) {
- try {
- if (!ArrayUtils.isEmpty(ifaces)) {
- INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
- if (statsService != null) {
- return statsService.getDetailedUidStats(ifaces);
- } else {
- Slog.e(TAG, "Failed to get networkStatsService ");
- }
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e);
+ protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager,
+ String[] ifaces) {
+ Objects.requireNonNull(networkStatsManager);
+ if (!ArrayUtils.isEmpty(ifaces)) {
+ return networkStatsManager.getDetailedUidStats(Set.of(ifaces));
}
return null;
}
@@ -12557,7 +12551,8 @@ public class BatteryStatsImpl extends BatteryStats {
*/
@GuardedBy("this")
public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
- final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
+ final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
+ @NonNull NetworkStatsManager networkStatsManager) {
if (DEBUG_ENERGY) {
synchronized (mWifiNetworkLock) {
Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
@@ -12567,7 +12562,8 @@ public class BatteryStatsImpl extends BatteryStats {
// Grab a separate lock to acquire the network stats, which may do I/O.
NetworkStats delta = null;
synchronized (mWifiNetworkLock) {
- final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
+ final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager,
+ mWifiIfaces);
if (latestStats != null) {
delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
mNetworkStatsPool.acquire());
@@ -12920,7 +12916,8 @@ public class BatteryStatsImpl extends BatteryStats {
* Distribute Cell radio energy info and network traffic to apps.
*/
public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo,
- final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) {
+ final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
+ @NonNull NetworkStatsManager networkStatsManager) {
if (DEBUG_ENERGY) {
Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
}
@@ -12934,7 +12931,8 @@ public class BatteryStatsImpl extends BatteryStats {
// Grab a separate lock to acquire the network stats, which may do I/O.
NetworkStats delta = null;
synchronized (mModemNetworkLock) {
- final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
+ final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager,
+ mModemIfaces);
if (latestStats != null) {
delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
mNetworkStatsPool.acquire());
diff --git a/core/java/com/android/internal/statusbar/StatusBarIcon.java b/core/java/com/android/internal/statusbar/StatusBarIcon.java
index 4f80afaab696..1d626235c4d2 100644
--- a/core/java/com/android/internal/statusbar/StatusBarIcon.java
+++ b/core/java/com/android/internal/statusbar/StatusBarIcon.java
@@ -81,9 +81,9 @@ public class StatusBarIcon implements Parcelable {
}
public void readFromParcel(Parcel in) {
- this.icon = (Icon) in.readParcelable(null, android.graphics.drawable.Icon.class);
+ this.icon = (Icon) in.readParcelable(null);
this.pkg = in.readString();
- this.user = (UserHandle) in.readParcelable(null, android.os.UserHandle.class);
+ this.user = (UserHandle) in.readParcelable(null);
this.iconLevel = in.readInt();
this.visible = in.readInt() != 0;
this.number = in.readInt();
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index d3c3917cd791..f46223ac8769 100644
--- a/core/java/com/android/internal/util/ScreenshotHelper.java
+++ b/core/java/com/android/internal/util/ScreenshotHelper.java
@@ -71,11 +71,11 @@ public class ScreenshotHelper {
if (in.readInt() == 1) {
mBitmapBundle = in.readBundle(getClass().getClassLoader());
- mBoundsInScreen = in.readParcelable(Rect.class.getClassLoader(), android.graphics.Rect.class);
- mInsets = in.readParcelable(Insets.class.getClassLoader(), android.graphics.Insets.class);
+ mBoundsInScreen = in.readParcelable(Rect.class.getClassLoader());
+ mInsets = in.readParcelable(Insets.class.getClassLoader());
mTaskId = in.readInt();
mUserId = in.readInt();
- mTopComponent = in.readParcelable(ComponentName.class.getClassLoader(), android.content.ComponentName.class);
+ mTopComponent = in.readParcelable(ComponentName.class.getClassLoader());
}
}
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 627381c620c1..09ff4e0aa076 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -37,6 +37,7 @@ import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.MotionEvent.PointerCoords;
+import android.view.RoundedCorner;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
@@ -229,13 +230,29 @@ public class PointerLocationView extends View implements InputDeviceListener,
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ int headerPaddingTop = 0;
+ Insets waterfallInsets = Insets.NONE;
+
+ final RoundedCorner topLeftRounded =
+ insets.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT);
+ if (topLeftRounded != null) {
+ headerPaddingTop = topLeftRounded.getRadius();
+ }
+
+ final RoundedCorner topRightRounded =
+ insets.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT);
+ if (topRightRounded != null) {
+ headerPaddingTop = Math.max(headerPaddingTop, topRightRounded.getRadius());
+ }
+
if (insets.getDisplayCutout() != null) {
- mHeaderPaddingTop = insets.getDisplayCutout().getSafeInsetTop();
- mWaterfallInsets = insets.getDisplayCutout().getWaterfallInsets();
- } else {
- mHeaderPaddingTop = 0;
- mWaterfallInsets = Insets.NONE;
+ headerPaddingTop =
+ Math.max(headerPaddingTop, insets.getDisplayCutout().getSafeInsetTop());
+ waterfallInsets = insets.getDisplayCutout().getWaterfallInsets();
}
+
+ mHeaderPaddingTop = headerPaddingTop;
+ mWaterfallInsets = waterfallInsets;
return super.onApplyWindowInsets(insets);
}
diff --git a/core/jni/android_text_Hyphenator.cpp b/core/jni/android_text_Hyphenator.cpp
index 011e0514b82f..3651dbdb3fa3 100644
--- a/core/jni/android_text_Hyphenator.cpp
+++ b/core/jni/android_text_Hyphenator.cpp
@@ -130,6 +130,7 @@ static void init() {
addHyphenator("sk", 2, 2); // Slovak
addHyphenator("sl", 2, 2); // Slovenian
addHyphenator("sq", 2, 2); // Albanian
+ addHyphenator("sv", 1, 2); // Swedish
addHyphenator("ta", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX); // Tamil
addHyphenator("te", INDIC_MIN_PREFIX, INDIC_MIN_SUFFIX); // Telugu
addHyphenator("tk", 2, 2); // Turkmen
diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto
index 73d6a17799d9..e56d55e940e4 100644
--- a/core/proto/android/providers/settings/system.proto
+++ b/core/proto/android/providers/settings/system.proto
@@ -212,6 +212,12 @@ message SystemSettingsProto {
// DatabaseHelper.
optional SettingProto in_silent = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
optional SettingProto when_ringing = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
+ optional SettingProto alarm_intensity = 5 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto media_intensity = 6 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto ring_intensity = 7 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ // notification_intensity is already logged at Notification.vibration_intensity
+ // haptic_feedback_intensity is already logged at HapticFeedback.intensity
}
optional Vibrate vibrate = 32;
diff --git a/core/proto/android/server/vibrator/OWNERS b/core/proto/android/server/vibrator/OWNERS
new file mode 100644
index 000000000000..b54d6bf07818
--- /dev/null
+++ b/core/proto/android/server/vibrator/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS \ No newline at end of file
diff --git a/core/proto/android/server/vibrator/vibratormanagerservice.proto b/core/proto/android/server/vibrator/vibratormanagerservice.proto
index 7b97524d0510..fbe2170ea51c 100644
--- a/core/proto/android/server/vibrator/vibratormanagerservice.proto
+++ b/core/proto/android/server/vibrator/vibratormanagerservice.proto
@@ -97,7 +97,7 @@ message VibrationProto {
optional int32 status = 6;
}
-// Next id: 18
+// Next id: 24
message VibratorManagerServiceDumpProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
repeated int32 vibrator_ids = 1;
@@ -106,8 +106,14 @@ message VibratorManagerServiceDumpProto {
optional VibrationProto current_external_vibration = 4;
optional bool vibrator_under_external_control = 5;
optional bool low_power_mode = 6;
+ optional int32 alarm_intensity = 18;
+ optional int32 alarm_default_intensity = 19;
optional int32 haptic_feedback_intensity = 7;
optional int32 haptic_feedback_default_intensity = 8;
+ optional int32 hardware_feedback_intensity = 22;
+ optional int32 hardware_feedback_default_intensity = 23;
+ optional int32 media_intensity = 20;
+ optional int32 media_default_intensity = 21;
optional int32 notification_intensity = 9;
optional int32 notification_default_intensity = 10;
optional int32 ring_intensity = 11;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a005eb0d5f03..ae5414d4fa47 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4438,6 +4438,12 @@
<permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS"
android:protectionLevel="signature|installer|verifier" />
+ <!-- @TestApi Allows an application to revoke the POST_NOTIFICATIONS permission from an app
+ without killing the app. Only granted to the shell.
+ @hide -->
+ <permission android:name="android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows the system to read runtime permission state.
@hide -->
<permission android:name="android.permission.GET_RUNTIME_PERMISSIONS"
@@ -5580,13 +5586,6 @@
<permission android:name="android.permission.WRITE_COMMUNAL_STATE"
android:protectionLevel="signature" />
- <!-- Allows an application to view information from the currently active
- {@link com.android.server.communal.CommunalManagerService}.
- @hide
- @SystemApi -->
- <permission android:name="android.permission.READ_COMMUNAL_STATE"
- android:protectionLevel="signature|privileged"/>
-
<!-- Allows the holder to manage whether the system can bind to services
provided by instant apps. This permission is intended to protect
test/development fucntionality and should be used only in such cases.
@@ -6101,7 +6100,7 @@
@hide -->
<permission android:name="android.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES"
android:protectionLevel="signature|role" />
-
+
<!-- @SystemApi Allows an app to read whether SafetyCenter is enabled/disabled.
<p>Protection level: signature|privileged
@hide
@@ -6109,6 +6108,14 @@
<permission android:name="android.permission.READ_SAFETY_CENTER_STATUS"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Required to access the safety center internal APIs using the
+ {@link android.safetycenter.SafetyCenterManager}.
+ <p>Protection level: internal|installer|role
+ @hide
+ -->
+ <permission android:name="android.permission.MANAGE_SAFETY_CENTER"
+ android:protectionLevel="internal|installer|role" />
+
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
@@ -6603,6 +6610,10 @@
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
+ <service android:name="com.android.server.companion.AssociationCleanUpService"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+
<service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader"
android:exported="false">
<intent-filter>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 1705371a7f4a..86c83c590b77 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8442,6 +8442,9 @@
<attr name="settingsActivity" />
<!-- A preview, in a drawable resource id, of what the Dream will look like. -->
<attr name="previewImage" format="reference" />
+ <!-- Whether to show clock and other complications such as weather in the overlay. Default
+ to true. Note that the overlay on dreams is currently only supported on tablets. -->
+ <attr name="showClockAndComplications" format="boolean" />
</declare-styleable>
<!-- Use <code>trust-agent</code> as the root tag of the XML resource that
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7d8bceaf89e9..2836c9816886 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1179,10 +1179,18 @@
<string-array translatable="false" name="config_ringtoneEffectUris">
</string-array>
+ <!-- The default intensity level for alarm vibrations. See
+ Settings.System.ALARM_VIBRATION_INTENSITY more details on the constant values and
+ meanings. -->
+ <integer name="config_defaultAlarmVibrationIntensity">2</integer>
<!-- The default intensity level for haptic feedback. See
Settings.System.HAPTIC_FEEDBACK_INTENSITY more details on the constant values and
meanings. -->
<integer name="config_defaultHapticFeedbackIntensity">2</integer>
+ <!-- The default intensity level for media vibrations. See
+ Settings.System.MEDIA_VIBRATION_INTENSITY more details on the constant values and
+ meanings. -->
+ <integer name="config_defaultMediaVibrationIntensity">2</integer>
<!-- The default intensity level for notification vibrations. See
Settings.System.NOTIFICATION_VIBRATION_INTENSITY more details on the constant values and
meanings. -->
@@ -2125,6 +2133,8 @@
<string name="config_deviceManager" translatable="false"></string>
<!-- The name of the package that will hold the app protection service role. -->
<string name="config_systemAppProtectionService" translatable="false"></string>
+ <!-- The name of the package that will hold the system calendar sync manager role. -->
+ <string name="config_systemAutomotiveCalendarSyncManager" translatable="false"></string>
<!-- The name of the package that will be allowed to change its components' label/icon. -->
<string name="config_overrideComponentUiPackage" translatable="false">com.android.stk</string>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9449f606b3aa..5fa7409150ab 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3250,6 +3250,7 @@
<public name="supportedTypes" />
<public name="resetEnabledSettingsOnAppDataCleared" />
<public name="supportsStylusHandwriting" />
+ <public name="showClockAndComplications" />
<!-- @hide @SystemApi -->
<public name="gameSessionService" />
</staging-public-group>
@@ -3273,6 +3274,8 @@
<public name="config_deviceManager" />
<!-- @hide @SystemApi -->
<public name="config_systemAppProtectionService" />
+ <!-- @hide @SystemApi @TestApi -->
+ <public name="config_systemAutomotiveCalendarSyncManager" />
</staging-public-group>
<staging-public-group type="dimen" first-id="0x01db0000">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ba4aa81766e0..a4b5d3caaabf 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3867,7 +3867,9 @@
<java-symbol type="drawable" name="ic_arrow_forward" />
<java-symbol type="drawable" name="ic_permission" />
+ <java-symbol type="integer" name="config_defaultAlarmVibrationIntensity" />
<java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" />
+ <java-symbol type="integer" name="config_defaultMediaVibrationIntensity" />
<java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" />
<java-symbol type="integer" name="config_defaultRingVibrationIntensity" />
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
index 47b14bbaa8fa..4f8b85554f5c 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -16,6 +16,7 @@
package android.content.res;
+import android.platform.test.annotations.Presubmit;
import android.test.ActivityInstrumentationTestCase2;
import android.util.TypedValue;
@@ -25,6 +26,7 @@ import com.android.frameworks.coretests.R;
import java.lang.reflect.InvocationTargetException;
+@Presubmit
public class ConfigurationBoundResourceCacheTest
extends ActivityInstrumentationTestCase2<ResourceCacheActivity> {
diff --git a/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java b/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
index 57f01e988440..9aef2ca104bd 100644
--- a/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
+++ b/core/tests/coretests/src/android/content/res/FontResourcesParserTest.java
@@ -27,6 +27,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import android.app.Instrumentation;
+import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -45,6 +46,7 @@ import java.util.List;
/**
* Tests for {@link FontResourcesParser}.
*/
+@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class FontResourcesParserTest {
diff --git a/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java b/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java
index c4df88b49935..f7f9569c413e 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.graphics.drawable.ColorStateListDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
+import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -34,6 +35,7 @@ import com.android.frameworks.coretests.R;
import org.junit.Test;
import org.junit.runner.RunWith;
+@Presubmit
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ResourcesDrawableTest {
diff --git a/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java b/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java
index aa1a5341de57..25c3db5c6910 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesLocaleTest.java
@@ -18,6 +18,7 @@ package android.content.res;
import android.os.FileUtils;
import android.os.LocaleList;
+import android.platform.test.annotations.Presubmit;
import android.test.AndroidTestCase;
import android.util.DisplayMetrics;
@@ -30,6 +31,7 @@ import java.io.InputStream;
import java.util.Arrays;
import java.util.Locale;
+@Presubmit
public class ResourcesLocaleTest extends AndroidTestCase {
private String extractApkAndGetPath(int id) throws Exception {
diff --git a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
index e7ee9dcf7557..34a8bdea5e8a 100644
--- a/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
+++ b/core/tests/coretests/src/android/content/res/ResourcesManagerTest.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.app.ResourcesManager;
import android.os.Binder;
import android.os.LocaleList;
+import android.platform.test.annotations.Postsubmit;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Display;
@@ -32,6 +33,7 @@ import junit.framework.TestCase;
import java.util.HashMap;
import java.util.Map;
+@Postsubmit
public class ResourcesManagerTest extends TestCase {
private static final int SECONDARY_DISPLAY_ID = 1;
private static final String APP_ONE_RES_DIR = "app_one.apk";
diff --git a/core/tests/coretests/src/android/content/res/TEST_MAPPING b/core/tests/coretests/src/android/content/res/TEST_MAPPING
new file mode 100644
index 000000000000..4ea6e40a7225
--- /dev/null
+++ b/core/tests/coretests/src/android/content/res/TEST_MAPPING
@@ -0,0 +1,43 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.content.res."
+ },
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "android.platform.test.annotations.Postsubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ }
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.content.res."
+ },
+ {
+ "include-annotation": "android.platform.test.annotations.Postsubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/tests/coretests/src/android/os/OWNERS b/core/tests/coretests/src/android/os/OWNERS
index a42285eedbf4..f2d6ff87f7f2 100644
--- a/core/tests/coretests/src/android/os/OWNERS
+++ b/core/tests/coretests/src/android/os/OWNERS
@@ -2,11 +2,7 @@
per-file BrightnessLimit.java = michaelwr@google.com, santoscordon@google.com
# Haptics
-per-file CombinedVibrationEffectTest.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file ExternalVibrationTest.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file VibrationEffectTest.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file VibratorInfoTest.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file VibratorTest.java = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file *Vibrat*.java = file:/services/core/java/com/android/server/vibrator/OWNERS
# Power
per-file PowerManager*.java = michaelwr@google.com, santoscordon@google.com \ No newline at end of file
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index 781564b7be35..10cec8243b8e 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -125,8 +125,8 @@ public class VibrationEffectTest {
VibrationEffect.startWaveform()
.addStep(/* amplitude= */ 1, /* duration= */ 10)
.addRamp(/* amplitude= */ 0, /* duration= */ 20)
- .addStep(/* amplitude= */ 1, /* frequency*/ 1, /* duration= */ 100)
- .addRamp(/* amplitude= */ 0.5f, /* frequency*/ -1, /* duration= */ 50)
+ .addStep(/* amplitude= */ 1, /* frequencyHz= */ 1, /* duration= */ 100)
+ .addRamp(/* amplitude= */ 0.5f, /* frequencyHz= */ 100, /* duration= */ 50)
.build()
.validate();
@@ -150,10 +150,22 @@ public class VibrationEffectTest {
.addStep(/* amplitude= */ -2, 10).build().validate());
assertThrows(IllegalArgumentException.class,
() -> VibrationEffect.startWaveform()
+ .addStep(1, /* frequencyHz= */ -1f, 10).build().validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> VibrationEffect.startWaveform()
.addStep(1, /* duration= */ -1).build().validate());
assertThrows(IllegalArgumentException.class,
() -> VibrationEffect.startWaveform()
- .addStep(1, 0, /* duration= */ -1).build().validate());
+ .addStep(1, 100f, /* duration= */ -1).build().validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> VibrationEffect.startWaveform()
+ .addRamp(/* amplitude= */ -3, 10).build().validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> VibrationEffect.startWaveform()
+ .addRamp(1, /* frequencyHz= */ 0, 10).build().validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> VibrationEffect.startWaveform()
+ .addRamp(1, 10f, /* duration= */ -3).build().validate());
}
@Test
diff --git a/core/tests/coretests/src/android/os/VibratorInfoTest.java b/core/tests/coretests/src/android/os/VibratorInfoTest.java
index 6e07fa264c1c..d0e03a24427e 100644
--- a/core/tests/coretests/src/android/os/VibratorInfoTest.java
+++ b/core/tests/coretests/src/android/os/VibratorInfoTest.java
@@ -19,6 +19,7 @@ package android.os;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import android.hardware.vibrator.Braking;
@@ -43,19 +44,17 @@ public class VibratorInfoTest {
/* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f};
private static final VibratorInfo.FrequencyMapping EMPTY_FREQUENCY_MAPPING =
- new VibratorInfo.FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, Float.NaN, null);
+ new VibratorInfo.FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, null);
private static final VibratorInfo.FrequencyMapping TEST_FREQUENCY_MAPPING =
- new VibratorInfo.FrequencyMapping(TEST_MIN_FREQUENCY,
- TEST_RESONANT_FREQUENCY, TEST_FREQUENCY_RESOLUTION,
- /* suggestedSafeRangeHz= */ 50, TEST_AMPLITUDE_MAP);
+ new VibratorInfo.FrequencyMapping(TEST_RESONANT_FREQUENCY, TEST_MIN_FREQUENCY,
+ TEST_FREQUENCY_RESOLUTION, TEST_AMPLITUDE_MAP);
@Test
public void testHasAmplitudeControl() {
VibratorInfo noCapabilities = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
assertFalse(noCapabilities.hasAmplitudeControl());
VibratorInfo composeAndAmplitudeControl = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
- .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS
- | IVibrator.CAP_AMPLITUDE_CONTROL)
+ .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL)
.build();
assertTrue(composeAndAmplitudeControl.hasAmplitudeControl());
}
@@ -143,138 +142,95 @@ public class VibratorInfoTest {
}
@Test
- public void testGetFrequencyRange_invalidFrequencyMappingReturnsEmptyRange() {
+ public void testGetFrequencyRangeHz_invalidFrequencyMappingReturnsNull() {
// Invalid, contains NaN values or empty array.
- assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(
- TEST_VIBRATOR_ID).build().getFrequencyRange());
- assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID).build().getFrequencyRangeHz());
+ assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setFrequencyMapping(new VibratorInfo.FrequencyMapping(
- Float.NaN, 150, 25, 50, TEST_AMPLITUDE_MAP))
- .build().getFrequencyRange());
- assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ Float.NaN, 50, 25, TEST_AMPLITUDE_MAP))
+ .build().getFrequencyRangeHz());
+ assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setFrequencyMapping(new VibratorInfo.FrequencyMapping(
- 50, Float.NaN, 25, 50, TEST_AMPLITUDE_MAP))
- .build().getFrequencyRange());
- assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ 150, Float.NaN, 25, TEST_AMPLITUDE_MAP))
+ .build().getFrequencyRangeHz());
+ assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setFrequencyMapping(new VibratorInfo.FrequencyMapping(
- 50, 150, Float.NaN, 50, TEST_AMPLITUDE_MAP))
- .build().getFrequencyRange());
- assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID)
- .setFrequencyMapping(new VibratorInfo.FrequencyMapping(
- 50, 150, 25, Float.NaN, TEST_AMPLITUDE_MAP))
- .build().getFrequencyRange());
- assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID)
- .setFrequencyMapping(new VibratorInfo.FrequencyMapping(50, 150, 25, 50, null))
- .build().getFrequencyRange());
+ 150, 50, Float.NaN, TEST_AMPLITUDE_MAP))
+ .build().getFrequencyRangeHz());
+ assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ .setFrequencyMapping(new VibratorInfo.FrequencyMapping(150, 50, 25, null))
+ .build().getFrequencyRangeHz());
// Invalid, minFrequency > resonantFrequency
- assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setFrequencyMapping(new VibratorInfo.FrequencyMapping(
- /* minFrequencyHz= */ 250, /* resonantFrequency= */ 150, 25, 50, null))
- .build().getFrequencyRange());
+ /* resonantFrequencyHz= */ 150, /* minFrequencyHz= */ 250, 25, null))
+ .build().getFrequencyRangeHz());
// Invalid, maxFrequency < resonantFrequency by changing resolution.
- assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setFrequencyMapping(new VibratorInfo.FrequencyMapping(
- 50, 150, /* frequencyResolutionHz= */10, 50, null))
- .build().getFrequencyRange());
+ 150, 50, /* frequencyResolutionHz= */ 10, null))
+ .build().getFrequencyRangeHz());
}
@Test
- public void testGetFrequencyRange_safeRangeLimitedByMaxFrequency() {
+ public void testGetFrequencyRangeHz_resultRangeDerivedFromHalMapping() {
VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setFrequencyMapping(new VibratorInfo.FrequencyMapping(
- /* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150,
- /* frequencyResolutionHz= */ 25, /* suggestedSafeRangeHz= */ 200,
- TEST_AMPLITUDE_MAP))
+ /* resonantFrequencyHz= */ 150,
+ /* minFrequencyHz= */ 50,
+ /* frequencyResolutionHz= */ 25,
+ new float[]{
+ /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f,
+ /* 200Hz= */ 0.8f}))
.build();
- // Mapping should range from 50Hz = -2 to 200Hz = 1
- // Safe range [-1, 1] = [100Hz, 200Hz] defined by max - resonant = 50Hz
- assertEquals(Range.create(-2f, 1f), info.getFrequencyRange());
+ assertEquals(Range.create(50f, 200f), info.getFrequencyRangeHz());
}
@Test
- public void testGetFrequencyRange_safeRangeLimitedByMinFrequency() {
- VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
- .setFrequencyMapping(new VibratorInfo.FrequencyMapping(
- /* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150,
- /* frequencyResolutionHz= */ 50, /* suggestedSafeRangeHz= */ 200,
- TEST_AMPLITUDE_MAP))
- .build();
-
- // Mapping should range from 50Hz = -1 to 350Hz = 2
- // Safe range [-1, 1] = [50Hz, 250Hz] defined by resonant - min = 100Hz
- assertEquals(Range.create(-1f, 2f), info.getFrequencyRange());
- }
+ public void testGetMaxAmplitude_emptyMappingReturnsAlwaysZero() {
+ VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
+ assertEquals(0f, info.getMaxAmplitude(Float.NaN), TEST_TOLERANCE);
+ assertEquals(0f, info.getMaxAmplitude(100f), TEST_TOLERANCE);
+ assertEquals(0f, info.getMaxAmplitude(200f), TEST_TOLERANCE);
- @Test
- public void testGetFrequencyRange_validMappingReturnsFullRelativeRange() {
- VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
+ info = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
.setFrequencyMapping(new VibratorInfo.FrequencyMapping(
- /* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150,
- /* frequencyResolutionHz= */ 50, /* suggestedSafeRangeHz= */ 100,
- TEST_AMPLITUDE_MAP))
+ /* resonantFrequencyHz= */ 150,
+ /* minFrequencyHz= */ Float.NaN,
+ /* frequencyResolutionHz= */ Float.NaN,
+ null))
.build();
- // Mapping should range from 50Hz = -2 to 350Hz = 4
- // Safe range [-1, 1] = [100Hz, 200Hz] defined by suggested safe range 100Hz
- assertEquals(Range.create(-2f, 4f), info.getFrequencyRange());
- }
-
- @Test
- public void testAbsoluteFrequency_emptyMappingReturnsNaN() {
- VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
- assertTrue(Float.isNaN(info.getAbsoluteFrequency(-1)));
- assertTrue(Float.isNaN(info.getAbsoluteFrequency(0)));
- assertTrue(Float.isNaN(info.getAbsoluteFrequency(1)));
- }
-
- @Test
- public void testAbsoluteFrequency_validRangeReturnsOriginalValue() {
- VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).setFrequencyMapping(
- TEST_FREQUENCY_MAPPING).build();
- assertEquals(TEST_RESONANT_FREQUENCY, info.getAbsoluteFrequency(0), TEST_TOLERANCE);
-
- // Safe range [-1, 1] = [125Hz, 175Hz] defined by suggested safe range 100Hz
- assertEquals(125, info.getAbsoluteFrequency(-1), TEST_TOLERANCE);
- assertEquals(175, info.getAbsoluteFrequency(1), TEST_TOLERANCE);
- assertEquals(155, info.getAbsoluteFrequency(0.2f), TEST_TOLERANCE);
- assertEquals(140, info.getAbsoluteFrequency(-0.4f), TEST_TOLERANCE);
-
- // Full range [-4, 2] = [50Hz, 200Hz] defined by min frequency and amplitude mapping size
- assertEquals(50, info.getAbsoluteFrequency(info.getFrequencyRange().getLower()),
- TEST_TOLERANCE);
- assertEquals(200, info.getAbsoluteFrequency(info.getFrequencyRange().getUpper()),
- TEST_TOLERANCE);
- }
-
- @Test
- public void testGetMaxAmplitude_emptyMappingReturnsOnlyResonantFrequency() {
- VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
- assertEquals(1f, info.getMaxAmplitude(0), TEST_TOLERANCE);
- assertEquals(0f, info.getMaxAmplitude(0.1f), TEST_TOLERANCE);
- assertEquals(0f, info.getMaxAmplitude(-1), TEST_TOLERANCE);
+ assertEquals(0f, info.getMaxAmplitude(Float.NaN), TEST_TOLERANCE);
+ assertEquals(0f, info.getMaxAmplitude(100f), TEST_TOLERANCE);
+ assertEquals(0f, info.getMaxAmplitude(150f), TEST_TOLERANCE);
}
@Test
public void testGetMaxAmplitude_validMappingReturnsMappedValues() {
VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
- .setFrequencyMapping(new VibratorInfo.FrequencyMapping(/* minFrequencyHz= */ 50,
- /* resonantFrequencyHz= */ 150, /* frequencyResolutionHz= */ 25,
- /* suggestedSafeRangeHz= */ 50, TEST_AMPLITUDE_MAP))
+ .setFrequencyMapping(new VibratorInfo.FrequencyMapping(
+ /* resonantFrequencyHz= */ 150,
+ /* minFrequencyHz= */ 50,
+ /* frequencyResolutionHz= */ 25,
+ new float[]{
+ /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f,
+ /* 200Hz= */ 0.8f}))
.build();
- assertEquals(1f, info.getMaxAmplitude(0), TEST_TOLERANCE); // 150Hz
- assertEquals(0.9f, info.getMaxAmplitude(1), TEST_TOLERANCE); // 175Hz
- assertEquals(0.8f, info.getMaxAmplitude(-1), TEST_TOLERANCE); // 125Hz
- assertEquals(0.8f, info.getMaxAmplitude(info.getFrequencyRange().getUpper()),
+ assertEquals(1f, info.getMaxAmplitude(150f), TEST_TOLERANCE);
+ assertEquals(0.9f, info.getMaxAmplitude(175f), TEST_TOLERANCE);
+ assertEquals(0.8f, info.getMaxAmplitude(125f), TEST_TOLERANCE);
+ assertEquals(0.8f, info.getMaxAmplitude(info.getFrequencyRangeHz().getUpper()),
TEST_TOLERANCE); // 200Hz
- assertEquals(0.1f, info.getMaxAmplitude(info.getFrequencyRange().getLower()),
+ assertEquals(0.1f, info.getMaxAmplitude(info.getFrequencyRangeHz().getLower()),
TEST_TOLERANCE); // 50Hz
- // Rounds 145Hz to the max amplitude for 125Hz, which is lower.
- assertEquals(0.8f, info.getMaxAmplitude(-0.1f), TEST_TOLERANCE); // 145Hz
- // Rounds 185Hz to the max amplitude for 200Hz, which is lower.
- assertEquals(0.8f, info.getMaxAmplitude(1.2f), TEST_TOLERANCE); // 185Hz
+ // 145Hz maps to the max amplitude for 125Hz, which is lower.
+ assertEquals(0.8f, info.getMaxAmplitude(145f), TEST_TOLERANCE); // 145Hz
+ // 185Hz maps to the max amplitude for 200Hz, which is lower.
+ assertEquals(0.8f, info.getMaxAmplitude(185f), TEST_TOLERANCE); // 185Hz
}
@Test
@@ -317,9 +273,11 @@ public class VibratorInfoTest {
assertNotEquals(complete, completeWithDifferentPrimitiveDuration);
VibratorInfo completeWithDifferentFrequencyMapping = completeBuilder
- .setFrequencyMapping(new VibratorInfo.FrequencyMapping(TEST_MIN_FREQUENCY + 10,
- TEST_RESONANT_FREQUENCY + 20, TEST_FREQUENCY_RESOLUTION + 5,
- /* suggestedSafeRangeHz= */ 100, TEST_AMPLITUDE_MAP))
+ .setFrequencyMapping(new VibratorInfo.FrequencyMapping(
+ TEST_RESONANT_FREQUENCY + 20,
+ TEST_MIN_FREQUENCY + 10,
+ TEST_FREQUENCY_RESOLUTION + 5,
+ TEST_AMPLITUDE_MAP))
.build();
assertNotEquals(complete, completeWithDifferentFrequencyMapping);
diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java
index bdd76a5c162a..981086d6b152 100644
--- a/core/tests/coretests/src/android/os/VibratorTest.java
+++ b/core/tests/coretests/src/android/os/VibratorTest.java
@@ -27,14 +27,22 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.ContextWrapper;
import android.hardware.vibrator.IVibrator;
import android.media.AudioAttributes;
import android.platform.test.annotations.Presubmit;
import androidx.test.InstrumentationRegistry;
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.internal.util.test.FakeSettingsProviderRule;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -50,11 +58,19 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class VibratorTest {
+ @Rule
+ public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
+
+ private Context mContextSpy;
private Vibrator mVibratorSpy;
@Before
public void setUp() {
- mVibratorSpy = spy(InstrumentationRegistry.getContext().getSystemService(Vibrator.class));
+ mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
+
+ ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
+ when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
+ mVibratorSpy = spy(new SystemVibrator(mContextSpy));
}
@Test
diff --git a/core/tests/coretests/src/android/os/vibrator/OWNERS b/core/tests/coretests/src/android/os/vibrator/OWNERS
new file mode 100644
index 000000000000..b54d6bf07818
--- /dev/null
+++ b/core/tests/coretests/src/android/os/vibrator/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS \ No newline at end of file
diff --git a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
index 5f80d2a10515..3291b2d8edd9 100644
--- a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
@@ -39,19 +39,19 @@ public class RampSegmentTest {
@Test
public void testCreation() {
RampSegment ramp = new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0,
- /* StartFrequency= */ -1, /* endFrequency= */ 1, /* duration= */ 100);
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 200, /* duration= */ 100);
assertEquals(100L, ramp.getDuration());
assertTrue(ramp.hasNonZeroAmplitude());
assertEquals(1f, ramp.getStartAmplitude());
assertEquals(0f, ramp.getEndAmplitude());
- assertEquals(-1f, ramp.getStartFrequency());
- assertEquals(1f, ramp.getEndFrequency());
+ assertEquals(100f, ramp.getStartFrequencyHz());
+ assertEquals(200f, ramp.getEndFrequencyHz());
}
@Test
public void testSerialization() {
- RampSegment original = new RampSegment(0, 1, 0, 0.5f, 10);
+ RampSegment original = new RampSegment(0, 1, 10, 20.5f, 10);
Parcel parcel = Parcel.obtain();
original.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
@@ -61,7 +61,9 @@ public class RampSegmentTest {
@Test
public void testValidate() {
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0,
- /* StartFrequency= */ -1, /* endFrequency= */ 1, /* duration= */ 100).validate();
+ /* startFrequencyHz= */ 2, /* endFrequencyHz= */ 1, /* duration= */ 100).validate();
+ // Zero frequency is still used internally for unset frequency.
+ new RampSegment(0, 0, 0, 0, 0).validate();
assertThrows(IllegalArgumentException.class,
() -> new RampSegment(VibrationEffect.DEFAULT_AMPLITUDE, 0, 0, 0, 0).validate());
@@ -70,7 +72,15 @@ public class RampSegmentTest {
assertThrows(IllegalArgumentException.class,
() -> new RampSegment(0, /* endAmplitude= */ 2, 0, 0, 0).validate());
assertThrows(IllegalArgumentException.class,
+ () -> new RampSegment(0, 0, /* startFrequencyHz= */ -1, 0, 0).validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> new RampSegment(0, 0, 0, /* endFrequencyHz= */ -3, 0).validate());
+ assertThrows(IllegalArgumentException.class,
() -> new RampSegment(0, 0, 0, 0, /* duration= */ -1).validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> new RampSegment(/* startAmplitude= */ Float.NaN, 0, 0, 0, 0).validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> new RampSegment(0, 0, /* startFrequencyHz= */ Float.NaN, 0, 0).validate());
}
@Test
diff --git a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
index fdce86a27ac4..44241273d9e3 100644
--- a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
@@ -38,13 +38,13 @@ public class StepSegmentTest {
@Test
public void testCreation() {
- StepSegment step = new StepSegment(/* amplitude= */ 1f, /* frequency= */ -1f,
+ StepSegment step = new StepSegment(/* amplitude= */ 1f, /* frequencyHz= */ 1f,
/* duration= */ 100);
assertEquals(100, step.getDuration());
assertTrue(step.hasNonZeroAmplitude());
assertEquals(1f, step.getAmplitude());
- assertEquals(-1f, step.getFrequency());
+ assertEquals(1f, step.getFrequencyHz());
}
@Test
@@ -58,14 +58,22 @@ public class StepSegmentTest {
@Test
public void testValidate() {
- new StepSegment(/* amplitude= */ 0f, /* frequency= */ -1f, /* duration= */ 100).validate();
+ new StepSegment(/* amplitude= */ 0f, /* frequencyHz= */ 10f, /* duration= */ 10).validate();
+ // Zero frequency is still used internally for unset frequency.
+ new StepSegment(0, 0, 0).validate();
assertThrows(IllegalArgumentException.class,
() -> new StepSegment(/* amplitude= */ -2, 1f, 10).validate());
assertThrows(IllegalArgumentException.class,
() -> new StepSegment(/* amplitude= */ 2, 1f, 10).validate());
assertThrows(IllegalArgumentException.class,
+ () -> new StepSegment(1, /* frequencyHz*/ -1f, 10).validate());
+ assertThrows(IllegalArgumentException.class,
() -> new StepSegment(2, 1f, /* duration= */ -1).validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> new StepSegment(/* amplitude= */ Float.NaN, 1f, 10).validate());
+ assertThrows(IllegalArgumentException.class,
+ () -> new StepSegment(1, /* frequencyHz*/ Float.NaN, 10).validate());
}
@Test
diff --git a/core/tests/coretests/src/com/android/internal/content/res/TEST_MAPPING b/core/tests/coretests/src/com/android/internal/content/res/TEST_MAPPING
new file mode 100644
index 000000000000..9aed8be4f10f
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/content/res/TEST_MAPPING
@@ -0,0 +1,21 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "com.android.internal.content."
+ },
+ {
+ "include-annotation": "android.platform.test.annotations.Presubmit"
+ },
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ },
+ {
+ "exclude-annotation": "org.junit.Ignore"
+ }
+ ]
+ }
+ ]
+}
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 8d9d79d0c4d9..ce2f76457422 100644
--- a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
@@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.app.usage.NetworkStatsManager;
import android.net.NetworkCapabilities;
import android.net.NetworkStats;
import android.os.BatteryConsumer;
@@ -44,6 +45,7 @@ import com.google.common.collect.Range;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -51,6 +53,8 @@ import org.junit.runner.RunWith;
public class MobileRadioPowerCalculatorTest {
private static final double PRECISION = 0.00001;
private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+ @Mock
+ NetworkStatsManager mNetworkStatsManager;
@Rule
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
@@ -95,7 +99,8 @@ public class MobileRadioPowerCalculatorTest {
ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
new int[]{100, 200, 300, 400, 500}, 600);
- stats.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE, 10000, 10000);
+ stats.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE, 10000, 10000,
+ mNetworkStatsManager);
mStatsRule.setTime(12_000_000, 12_000_000);
@@ -157,7 +162,8 @@ public class MobileRadioPowerCalculatorTest {
mStatsRule.setNetworkStats(new NetworkStats(10000, 1)
.insertEntry("cellular", APP_UID, 0, 0, 1000, 100, 2000, 20, 100));
- stats.noteModemControllerActivity(null, POWER_DATA_UNAVAILABLE, 10000, 10000);
+ stats.noteModemControllerActivity(null, POWER_DATA_UNAVAILABLE, 10000, 10000,
+ mNetworkStatsManager);
uid.setProcessStateForTest(
BatteryStats.Uid.PROCESS_STATE_BACKGROUND, 11000);
@@ -165,7 +171,8 @@ public class MobileRadioPowerCalculatorTest {
mStatsRule.setNetworkStats(new NetworkStats(12000, 1)
.insertEntry("cellular", APP_UID, 0, 0, 1000, 250, 2000, 80, 200));
- stats.noteModemControllerActivity(null, POWER_DATA_UNAVAILABLE, 12000, 12000);
+ stats.noteModemControllerActivity(null, POWER_DATA_UNAVAILABLE, 12000, 12000,
+ mNetworkStatsManager);
assertThat(uid.getMobileRadioMeasuredBatteryConsumptionUC()).isAtMost(0);
// 12000-8000 = 4000 ms == 4_000_000 us
@@ -239,7 +246,7 @@ public class MobileRadioPowerCalculatorTest {
ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000,
new int[]{100, 200, 300, 400, 500}, 600);
- stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000);
+ stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000, mNetworkStatsManager);
mStatsRule.setTime(12_000_000, 12_000_000);
@@ -301,7 +308,7 @@ public class MobileRadioPowerCalculatorTest {
mStatsRule.setNetworkStats(new NetworkStats(10000, 1)
.insertEntry("cellular", APP_UID, 0, 0, 1000, 100, 2000, 20, 100));
- stats.noteModemControllerActivity(null, 10_000_000, 10000, 10000);
+ stats.noteModemControllerActivity(null, 10_000_000, 10000, 10000, mNetworkStatsManager);
uid.setProcessStateForTest(
BatteryStats.Uid.PROCESS_STATE_BACKGROUND, 11000);
@@ -309,7 +316,7 @@ public class MobileRadioPowerCalculatorTest {
mStatsRule.setNetworkStats(new NetworkStats(12000, 1)
.insertEntry("cellular", APP_UID, 0, 0, 1000, 250, 2000, 80, 200));
- stats.noteModemControllerActivity(null, 15_000_000, 12000, 12000);
+ stats.noteModemControllerActivity(null, 15_000_000, 12000, 12000, mNetworkStatsManager);
mStatsRule.setTime(20000, 20000);
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index 4faf349aad7e..bddb3a1906fd 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -20,6 +20,8 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
+import android.app.usage.NetworkStatsManager;
import android.net.NetworkStats;
import android.os.Handler;
import android.os.Looper;
@@ -116,7 +118,8 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
}
@Override
- protected NetworkStats readNetworkStatsLocked(String[] ifaces) {
+ protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager,
+ String[] ifaces) {
return mNetworkStats;
}
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 fc44ddc216b4..e7ce9a03f18a 100644
--- a/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java
@@ -21,6 +21,7 @@ import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
+import android.app.usage.NetworkStatsManager;
import android.net.NetworkCapabilities;
import android.net.NetworkStats;
import android.os.BatteryConsumer;
@@ -35,6 +36,7 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
@RunWith(AndroidJUnit4.class)
@SmallTest
@@ -43,6 +45,9 @@ public class WifiPowerCalculatorTest {
private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+ @Mock
+ NetworkStatsManager mNetworkStatsManager;
+
@Rule
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
.setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE, 360.0)
@@ -80,7 +85,8 @@ public class WifiPowerCalculatorTest {
final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo();
- batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000);
+ batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000,
+ mNetworkStatsManager);
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
@@ -113,7 +119,7 @@ public class WifiPowerCalculatorTest {
final BatteryStatsImpl batteryStats = setupTestNetworkNumbers();
final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo();
- batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000);
+ batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000, mNetworkStatsManager);
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
mStatsRule.apply(calculator);
@@ -160,7 +166,8 @@ public class WifiPowerCalculatorTest {
// Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
// on the packet counts.
- batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000);
+ batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000,
+ mNetworkStatsManager);
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
@@ -180,7 +187,8 @@ public class WifiPowerCalculatorTest {
// Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively
// on the packet counts.
- batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000);
+ batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000,
+ mNetworkStatsManager);
WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile());
mStatsRule.apply(calculator);
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index f17fa3b17fe5..ee0fb4456336 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -275,6 +275,7 @@ applications that come with the platform
<privapp-permissions package="com.android.server.telecom">
<permission name="android.permission.BIND_CONNECTION_SERVICE"/>
<permission name="android.permission.BIND_INCALL_SERVICE"/>
+ <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
<permission name="android.permission.CALL_PRIVILEGED"/>
<permission name="android.permission.HANDLE_CAR_MODE_CHANGES"/>
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
@@ -293,6 +294,7 @@ applications that come with the platform
<privapp-permissions package="com.android.shell">
<!-- Needed for test only -->
+ <permission name="android.permission.LAUNCH_DEVICE_MANAGER_SETUP"/>
<permission name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
<permission name="android.permission.ACCESS_LOWPAN_STATE"/>
<permission name="android.permission.BACKUP"/>
@@ -518,13 +520,9 @@ applications that come with the platform
<permission name="android.permission.MANAGE_VOICE_KEYPHRASES" />
<!-- Permission required for ATS test - CarDevicePolicyManagerTest -->
<permission name="android.permission.LOCK_DEVICE" />
- <!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
+ <!-- Permissions required for CTS test - CtsSafetyCenterTestCases -->
<permission name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
- <!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
<permission name="android.permission.READ_SAFETY_CENTER_STATUS" />
- <!-- Permission required for CTS test - CommunalManagerTest -->
- <permission name="android.permission.WRITE_COMMUNAL_STATE" />
- <permission name="android.permission.READ_COMMUNAL_STATE" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index a612265793a3..425a37891afb 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -67,7 +67,7 @@ public abstract class BaseCanvas {
* @hide
*/
protected int mDensity = Bitmap.DENSITY_NONE;
- private boolean mAllowHwBitmapsInSwMode = false;
+ private boolean mAllowHwFeaturesInSwMode = false;
protected void throwIfCannotDraw(Bitmap bitmap) {
if (bitmap.isRecycled()) {
@@ -101,14 +101,14 @@ public abstract class BaseCanvas {
public void drawArc(float left, float top, float right, float bottom, float startAngle,
float sweepAngle, boolean useCenter, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
useCenter, paint.getNativeInstance());
}
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
paint);
}
@@ -119,14 +119,14 @@ public abstract class BaseCanvas {
public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
throwIfCannotDraw(bitmap);
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawBitmap(mNativeCanvasWrapper, bitmap.getNativeInstance(), left, top,
paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity,
bitmap.mDensity);
}
public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getNativeInstance(), matrix.ni(),
paint != null ? paint.getNativeInstance() : 0);
}
@@ -137,7 +137,7 @@ public abstract class BaseCanvas {
throw new NullPointerException();
}
throwIfCannotDraw(bitmap);
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
int left, top, right, bottom;
@@ -163,7 +163,7 @@ public abstract class BaseCanvas {
throw new NullPointerException();
}
throwIfCannotDraw(bitmap);
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
float left, top, right, bottom;
@@ -202,7 +202,7 @@ public abstract class BaseCanvas {
|| (lastScanline + width > length)) {
throw new ArrayIndexOutOfBoundsException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
// quick escape if there's nothing to draw
if (width == 0 || height == 0) {
return;
@@ -226,7 +226,7 @@ public abstract class BaseCanvas {
if ((meshWidth | meshHeight | vertOffset | colorOffset) < 0) {
throw new ArrayIndexOutOfBoundsException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
if (meshWidth == 0 || meshHeight == 0) {
return;
}
@@ -243,7 +243,7 @@ public abstract class BaseCanvas {
}
public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
}
@@ -275,23 +275,23 @@ public abstract class BaseCanvas {
public void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
}
public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
@NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
}
public void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
drawLines(pts, 0, pts.length, paint);
}
public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
}
@@ -299,18 +299,19 @@ public abstract class BaseCanvas {
if (oval == null) {
throw new NullPointerException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
}
public void drawPaint(@NonNull Paint paint) {
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
}
public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint,
@@ -320,7 +321,7 @@ public abstract class BaseCanvas {
public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint,
@@ -328,7 +329,7 @@ public abstract class BaseCanvas {
}
public void drawPath(@NonNull Path path, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
if (path.isSimplePath && path.rects != null) {
nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
} else {
@@ -337,18 +338,18 @@ public abstract class BaseCanvas {
}
public void drawPoint(float x, float y, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
}
public void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
@NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
}
public void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
drawPoints(pts, 0, pts.length, paint);
}
@@ -359,7 +360,7 @@ public abstract class BaseCanvas {
if (index < 0 || index + count > text.length || count * 2 > pos.length) {
throw new IndexOutOfBoundsException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
for (int i = 0; i < count; i++) {
drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint);
}
@@ -368,22 +369,22 @@ public abstract class BaseCanvas {
@Deprecated
public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
@NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
drawPosText(text.toCharArray(), 0, text.length(), pos, paint);
}
public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
}
public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
drawRect(r.left, r.top, r.right, r.bottom, paint);
}
public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawRect(mNativeCanvasWrapper,
rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
}
@@ -394,13 +395,13 @@ public abstract class BaseCanvas {
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
@NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry,
paint.getNativeInstance());
}
public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
}
@@ -410,7 +411,7 @@ public abstract class BaseCanvas {
*/
public void drawDoubleRoundRect(@NonNull RectF outer, float outerRx, float outerRy,
@NonNull RectF inner, float innerRx, float innerRy, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
float outerLeft = outer.left;
float outerTop = outer.top;
float outerRight = outer.right;
@@ -431,7 +432,7 @@ public abstract class BaseCanvas {
*/
public void drawDoubleRoundRect(@NonNull RectF outer, @NonNull float[] outerRadii,
@NonNull RectF inner, @NonNull float[] innerRadii, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
if (innerRadii == null || outerRadii == null
|| innerRadii.length != 8 || outerRadii.length != 8) {
throw new IllegalArgumentException("Both inner and outer radii arrays must contain "
@@ -509,7 +510,7 @@ public abstract class BaseCanvas {
(text.length - index - count)) < 0) {
throw new IndexOutOfBoundsException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
paint.getNativeInstance());
}
@@ -519,7 +520,7 @@ public abstract class BaseCanvas {
if ((start | end | (end - start) | (text.length() - end)) < 0) {
throw new IndexOutOfBoundsException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
if (text instanceof String || text instanceof SpannedString ||
text instanceof SpannableString) {
nDrawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
@@ -537,7 +538,7 @@ public abstract class BaseCanvas {
}
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
paint.getNativeInstance());
}
@@ -547,7 +548,7 @@ public abstract class BaseCanvas {
if ((start | end | (end - start) | (text.length() - end)) < 0) {
throw new IndexOutOfBoundsException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
paint.getNativeInstance());
}
@@ -557,7 +558,7 @@ public abstract class BaseCanvas {
if (index < 0 || index + count > text.length) {
throw new ArrayIndexOutOfBoundsException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawTextOnPath(mNativeCanvasWrapper, text, index, count,
path.readOnlyNI(), hOffset, vOffset,
paint.mBidiFlags, paint.getNativeInstance());
@@ -566,7 +567,7 @@ public abstract class BaseCanvas {
public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
float vOffset, @NonNull Paint paint) {
if (text.length() > 0) {
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset,
paint.mBidiFlags, paint.getNativeInstance());
}
@@ -587,7 +588,7 @@ public abstract class BaseCanvas {
throw new IndexOutOfBoundsException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount,
x, y, isRtl, paint.getNativeInstance(), 0 /* measured text */);
}
@@ -606,7 +607,7 @@ public abstract class BaseCanvas {
throw new IndexOutOfBoundsException();
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
if (text instanceof String || text instanceof SpannedString ||
text instanceof SpannableString) {
nDrawTextRun(mNativeCanvasWrapper, text.toString(), start, end, contextStart,
@@ -664,7 +665,7 @@ public abstract class BaseCanvas {
if (indices != null) {
checkRange(indices.length, indexOffset, indexCount);
}
- throwIfHasHwBitmapInSwMode(paint);
+ throwIfHasHwFeaturesInSwMode(paint);
nDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
vertOffset, texs, texOffset, colors, colorOffset,
indices, indexOffset, indexCount, paint.getNativeInstance());
@@ -680,50 +681,52 @@ public abstract class BaseCanvas {
/**
* @hide
*/
- public void setHwBitmapsInSwModeEnabled(boolean enabled) {
- mAllowHwBitmapsInSwMode = enabled;
+ public void setHwFeaturesInSwModeEnabled(boolean enabled) {
+ mAllowHwFeaturesInSwMode = enabled;
}
/**
* @hide
*/
- public boolean isHwBitmapsInSwModeEnabled() {
- return mAllowHwBitmapsInSwMode;
+ public boolean isHwFeaturesInSwModeEnabled() {
+ return mAllowHwFeaturesInSwMode;
}
/**
+ * If true throw an exception
* @hide
*/
- protected void onHwBitmapInSwMode() {
- if (!mAllowHwBitmapsInSwMode) {
- throw new IllegalArgumentException(
- "Software rendering doesn't support hardware bitmaps");
- }
+ protected boolean onHwFeatureInSwMode() {
+ return !mAllowHwFeaturesInSwMode;
}
private void throwIfHwBitmapInSwMode(Bitmap bitmap) {
- if (!isHardwareAccelerated() && bitmap.getConfig() == Bitmap.Config.HARDWARE) {
- onHwBitmapInSwMode();
+ if (!isHardwareAccelerated() && bitmap.getConfig() == Bitmap.Config.HARDWARE
+ && onHwFeatureInSwMode()) {
+ throw new IllegalArgumentException(
+ "Software rendering doesn't support hardware bitmaps");
}
}
- private void throwIfHasHwBitmapInSwMode(Paint p) {
+ private void throwIfHasHwFeaturesInSwMode(Paint p) {
if (isHardwareAccelerated() || p == null) {
return;
}
- throwIfHasHwBitmapInSwMode(p.getShader());
+ throwIfHasHwFeaturesInSwMode(p.getShader());
}
- private void throwIfHasHwBitmapInSwMode(Shader shader) {
+ private void throwIfHasHwFeaturesInSwMode(Shader shader) {
if (shader == null) {
return;
}
if (shader instanceof BitmapShader) {
throwIfHwBitmapInSwMode(((BitmapShader) shader).mBitmap);
- }
- if (shader instanceof ComposeShader) {
- throwIfHasHwBitmapInSwMode(((ComposeShader) shader).mShaderA);
- throwIfHasHwBitmapInSwMode(((ComposeShader) shader).mShaderB);
+ } else if (shader instanceof RuntimeShader && onHwFeatureInSwMode()) {
+ throw new IllegalArgumentException(
+ "Software rendering doesn't support RuntimeShader");
+ } else if (shader instanceof ComposeShader) {
+ throwIfHasHwFeaturesInSwMode(((ComposeShader) shader).mShaderA);
+ throwIfHasHwFeaturesInSwMode(((ComposeShader) shader).mShaderB);
}
}
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index fc7f84c3c83e..618e6dcc4433 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -169,8 +169,7 @@ public final class Outline {
}
/**
- * Sets the Outline to the rounded rect defined by the input rect, and
- * corner radius.
+ * Sets the Outline to the rect defined by the input coordinates.
*/
public void setRect(int left, int top, int right, int bottom) {
setRoundRect(left, top, right, bottom, 0.0f);
@@ -184,7 +183,7 @@ public final class Outline {
}
/**
- * Sets the Outline to the rounded rect defined by the input rect, and corner radius.
+ * Sets the Outline to the rounded rect defined by the input coordinates and corner radius.
* <p>
* Passing a zero radius is equivalent to calling {@link #setRect(int, int, int, int)}
*/
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index 390d3d414346..ee4165b8da05 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -124,7 +124,7 @@ public class Picture {
public void endRecording() {
verifyValid();
if (mRecordingCanvas != null) {
- mRequiresHwAcceleration = mRecordingCanvas.mHoldsHwBitmap;
+ mRequiresHwAcceleration = mRecordingCanvas.mUsesHwFeature;
mRecordingCanvas = null;
nativeEndRecording(mNativePicture);
}
@@ -182,8 +182,10 @@ public class Picture {
if (mRecordingCanvas != null) {
endRecording();
}
- if (mRequiresHwAcceleration && !canvas.isHardwareAccelerated()) {
- canvas.onHwBitmapInSwMode();
+ if (mRequiresHwAcceleration && !canvas.isHardwareAccelerated()
+ && canvas.onHwFeatureInSwMode()) {
+ throw new IllegalArgumentException("Software rendering not supported for Pictures that"
+ + " require hardware acceleration");
}
nativeDraw(canvas.getNativeCanvasWrapper(), mNativePicture);
}
@@ -242,7 +244,7 @@ public class Picture {
private static class PictureCanvas extends Canvas {
private final Picture mPicture;
- boolean mHoldsHwBitmap;
+ boolean mUsesHwFeature;
public PictureCanvas(Picture pict, long nativeCanvas) {
super(nativeCanvas);
@@ -265,8 +267,9 @@ public class Picture {
}
@Override
- protected void onHwBitmapInSwMode() {
- mHoldsHwBitmap = true;
+ protected boolean onHwFeatureInSwMode() {
+ mUsesHwFeature = true;
+ return false;
}
}
}
diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
index 9ca8e3b46317..ef57f4a76007 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -178,36 +178,6 @@ public class RuntimeShader extends Shader {
setUniform(uniformName, values, false);
}
- /**
- * Old method signature used by some callers within the platform code
- * @hide
- * @deprecated use setFloatUniform instead
- */
- @Deprecated
- public void setUniform(@NonNull String uniformName, float[] values) {
- setFloatUniform(uniformName, values);
- }
-
- /**
- * Old method signature used by some callers within the platform code
- * @hide
- * @deprecated use setFloatUniform instead
- */
- @Deprecated
- public void setUniform(@NonNull String uniformName, float value) {
- setFloatUniform(uniformName, value);
- }
-
- /**
- * Old method signature used by some callers within the platform code
- * @hide
- * @deprecated use setFloatUniform instead
- */
- @Deprecated
- public void setUniform(@NonNull String uniformName, float value1, float value2) {
- setFloatUniform(uniformName, value1, value2);
- }
-
private void setFloatUniform(@NonNull String uniformName, float value1, float value2,
float value3, float value4, int count) {
if (uniformName == null) {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index b843589376c4..ffaa4ea51452 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -868,7 +868,7 @@ public class RippleDrawable extends LayerDrawable {
private void drawPatterned(@NonNull Canvas canvas) {
final Rect bounds = mHotspotBounds;
final int saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
- boolean useCanvasProps = shouldUseCanvasProps(canvas);
+ boolean useCanvasProps = !mForceSoftware;
if (isBounded()) {
canvas.clipRect(getDirtyBounds());
}
@@ -914,7 +914,11 @@ public class RippleDrawable extends LayerDrawable {
}
for (int i = 0; i < mRunningAnimations.size(); i++) {
RippleAnimationSession s = mRunningAnimations.get(i);
- if (useCanvasProps) {
+ if (!canvas.isHardwareAccelerated()) {
+ Log.e(TAG, "The RippleDrawable.STYLE_PATTERNED animation is not supported for a "
+ + "non-hardware accelerated Canvas. Skipping animation.");
+ break;
+ } else if (useCanvasProps) {
RippleAnimationSession.AnimationProperties<CanvasProperty<Float>,
CanvasProperty<Paint>>
p = s.getCanvasProperties();
@@ -1002,10 +1006,6 @@ public class RippleDrawable extends LayerDrawable {
return color;
}
- private boolean shouldUseCanvasProps(Canvas c) {
- return !mForceSoftware && c.isHardwareAccelerated();
- }
-
@Override
public void invalidateSelf() {
invalidateSelf(true);
diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java
index 272b840219c2..53a673122040 100644
--- a/graphics/java/android/graphics/drawable/RippleShader.java
+++ b/graphics/java/android/graphics/drawable/RippleShader.java
@@ -17,7 +17,6 @@
package android.graphics.drawable;
import android.annotation.ColorInt;
-import android.graphics.Color;
import android.graphics.RuntimeShader;
import android.graphics.Shader;
@@ -37,8 +36,8 @@ final class RippleShader extends RuntimeShader {
+ "uniform vec2 in_tRotation1;\n"
+ "uniform vec2 in_tRotation2;\n"
+ "uniform vec2 in_tRotation3;\n"
- + "uniform vec4 in_color;\n"
- + "uniform vec4 in_sparkleColor;\n"
+ + "layout(color) uniform vec4 in_color;\n"
+ + "layout(color) uniform vec4 in_sparkleColor;\n"
+ "uniform shader in_shader;\n";
private static final String SHADER_LIB =
"float triangleNoise(vec2 n) {\n"
@@ -134,78 +133,68 @@ final class RippleShader extends RuntimeShader {
if (shader != null) {
setInputShader("in_shader", shader);
}
- setUniform("in_hasMask", shader == null ? 0 : 1);
+ setFloatUniform("in_hasMask", shader == null ? 0 : 1);
}
public void setRadius(float radius) {
- setUniform("in_maxRadius", radius * 2.3f);
+ setFloatUniform("in_maxRadius", radius * 2.3f);
}
public void setOrigin(float x, float y) {
- setUniform("in_origin", new float[] {x, y});
+ setFloatUniform("in_origin", x, y);
}
public void setTouch(float x, float y) {
- setUniform("in_touch", new float[] {x, y});
+ setFloatUniform("in_touch", x, y);
}
public void setProgress(float progress) {
- setUniform("in_progress", progress);
+ setFloatUniform("in_progress", progress);
}
/**
* Continuous offset used as noise phase.
*/
public void setNoisePhase(float phase) {
- setUniform("in_noisePhase", phase * 0.001f);
+ setFloatUniform("in_noisePhase", phase * 0.001f);
//
// Keep in sync with: frameworks/base/libs/hwui/pipeline/skia/AnimatedDrawables.h
//
final float turbulencePhase = phase;
- setUniform("in_turbulencePhase", turbulencePhase);
+ setFloatUniform("in_turbulencePhase", turbulencePhase);
final float scale = 1.5f;
- setUniform("in_tCircle1", new float[]{
+ setFloatUniform("in_tCircle1",
(float) (scale * 0.5 + (turbulencePhase * 0.01 * Math.cos(scale * 0.55))),
- (float) (scale * 0.5 + (turbulencePhase * 0.01 * Math.sin(scale * 0.55)))
- });
- setUniform("in_tCircle2", new float[]{
+ (float) (scale * 0.5 + (turbulencePhase * 0.01 * Math.sin(scale * 0.55))));
+ setFloatUniform("in_tCircle2",
(float) (scale * 0.2 + (turbulencePhase * -0.0066 * Math.cos(scale * 0.45))),
- (float) (scale * 0.2 + (turbulencePhase * -0.0066 * Math.sin(scale * 0.45)))
- });
- setUniform("in_tCircle3", new float[]{
+ (float) (scale * 0.2 + (turbulencePhase * -0.0066 * Math.sin(scale * 0.45))));
+ setFloatUniform("in_tCircle3",
(float) (scale + (turbulencePhase * -0.0066 * Math.cos(scale * 0.35))),
- (float) (scale + (turbulencePhase * -0.0066 * Math.sin(scale * 0.35)))
- });
+ (float) (scale + (turbulencePhase * -0.0066 * Math.sin(scale * 0.35))));
final double rotation1 = turbulencePhase * PI_ROTATE_RIGHT + 1.7 * Math.PI;
- setUniform("in_tRotation1", new float[]{
- (float) Math.cos(rotation1), (float) Math.sin(rotation1)
- });
+ setFloatUniform("in_tRotation1",
+ (float) Math.cos(rotation1), (float) Math.sin(rotation1));
final double rotation2 = turbulencePhase * PI_ROTATE_LEFT + 2 * Math.PI;
- setUniform("in_tRotation2", new float[]{
- (float) Math.cos(rotation2), (float) Math.sin(rotation2)
- });
+ setFloatUniform("in_tRotation2",
+ (float) Math.cos(rotation2), (float) Math.sin(rotation2));
final double rotation3 = turbulencePhase * PI_ROTATE_RIGHT + 2.75 * Math.PI;
- setUniform("in_tRotation3", new float[]{
- (float) Math.cos(rotation3), (float) Math.sin(rotation3)
- });
+ setFloatUniform("in_tRotation3",
+ (float) Math.cos(rotation3), (float) Math.sin(rotation3));
}
/**
* Color of the circle that's under the sparkles. Sparkles will always be white.
*/
public void setColor(@ColorInt int colorInt, @ColorInt int sparkleColorInt) {
- Color color = Color.valueOf(colorInt);
- Color sparkleColor = Color.valueOf(sparkleColorInt);
- setUniform("in_color", new float[] {color.red(),
- color.green(), color.blue(), color.alpha()});
- setUniform("in_sparkleColor", new float[] {sparkleColor.red(),
- sparkleColor.green(), sparkleColor.blue(), sparkleColor.alpha()});
+ setColorUniform("in_color", colorInt);
+ setColorUniform("in_sparkleColor", sparkleColorInt);
}
public void setResolution(float w, float h) {
final float densityScale = 2.1f;
- setUniform("in_resolutionScale", new float[] {1f / w, 1f / h});
- setUniform("in_noiseScale", new float[] {densityScale / w, densityScale / h});
+ setFloatUniform("in_resolutionScale", 1f / w, 1f / h);
+ setFloatUniform("in_noiseScale", densityScale / w, densityScale / h);
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index df751fc9fa48..180c77250fd1 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -79,22 +79,23 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
}
@Override
- public void registerOrganizer() {
- if (mAnimationController != null) {
- throw new IllegalStateException("Must unregister the organizer before re-register.");
+ public void unregisterOrganizer() {
+ stopOverrideSplitAnimation();
+ mAnimationController = null;
+ super.unregisterOrganizer();
+ }
+
+ void startOverrideSplitAnimation() {
+ if (mAnimationController == null) {
+ mAnimationController = new TaskFragmentAnimationController(this);
}
- super.registerOrganizer();
- mAnimationController = new TaskFragmentAnimationController(this);
mAnimationController.registerRemoteAnimations();
}
- @Override
- public void unregisterOrganizer() {
+ void stopOverrideSplitAnimation() {
if (mAnimationController != null) {
mAnimationController.unregisterRemoteAnimations();
- mAnimationController = null;
}
- super.unregisterOrganizer();
}
/**
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index b8e8b0114b47..8f368c2bee22 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -33,6 +33,7 @@ import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -63,6 +64,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
private @NonNull Consumer<List<SplitInfo>> mEmbeddingCallback;
private final List<SplitInfo> mLastReportedSplitStates = new ArrayList<>();
+ // We currently only support split activity embedding within the one root Task.
+ private final Rect mParentBounds = new Rect();
+
public SplitController() {
mPresenter = new SplitPresenter(new MainThreadExecutor(), this);
ActivityThread activityThread = ActivityThread.currentActivityThread();
@@ -79,6 +83,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
public void setEmbeddingRules(@NonNull Set<EmbeddingRule> rules) {
mSplitRules.clear();
mSplitRules.addAll(rules);
+ updateAnimationOverride();
}
@NonNull
@@ -158,6 +163,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
@Override
public void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
@NonNull Configuration parentConfig) {
+ onParentBoundsMayChange(parentConfig.windowConfiguration.getBounds());
TaskFragmentContainer container = getContainer(fragmentToken);
if (container != null) {
mPresenter.updateContainer(container);
@@ -165,6 +171,51 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
}
+ private void onParentBoundsMayChange(Activity activity) {
+ if (activity.isFinishing()) {
+ return;
+ }
+
+ onParentBoundsMayChange(mPresenter.getParentContainerBounds(activity));
+ }
+
+ private void onParentBoundsMayChange(Rect parentBounds) {
+ if (!parentBounds.isEmpty() && !mParentBounds.equals(parentBounds)) {
+ mParentBounds.set(parentBounds);
+ updateAnimationOverride();
+ }
+ }
+
+ /**
+ * Updates if we should override transition animation. We only want to override if the Task
+ * bounds is large enough for at least one split rule.
+ */
+ private void updateAnimationOverride() {
+ if (mParentBounds.isEmpty()) {
+ // We don't know about the parent bounds yet.
+ return;
+ }
+
+ // Check if the parent container bounds can support any split rule.
+ boolean supportSplit = false;
+ for (EmbeddingRule rule : mSplitRules) {
+ if (!(rule instanceof SplitRule)) {
+ continue;
+ }
+ if (mPresenter.shouldShowSideBySide(mParentBounds, (SplitRule) rule)) {
+ supportSplit = true;
+ break;
+ }
+ }
+
+ // We only want to override if it supports split.
+ if (supportSplit) {
+ mPresenter.startOverrideSplitAnimation();
+ } else {
+ mPresenter.stopOverrideSplitAnimation();
+ }
+ }
+
void onActivityCreated(@NonNull Activity launchedActivity) {
handleActivityCreated(launchedActivity);
updateCallbackIfNecessary();
@@ -180,6 +231,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
final TaskFragmentContainer currentContainer = getContainerWithActivity(
launchedActivity.getActivityToken());
+ if (currentContainer == null) {
+ // Initial check before any TaskFragment is created.
+ onParentBoundsMayChange(launchedActivity);
+ }
+
// Check if the activity is configured to always be expanded.
if (shouldExpand(launchedActivity, null, splitRules)) {
if (shouldContainerBeExpanded(currentContainer)) {
@@ -257,6 +313,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
// onTaskFragmentParentInfoChanged
return;
}
+ // The bounds of the container may have been changed.
+ onParentBoundsMayChange(activity);
// Check if activity requires a placeholder
launchPlaceholderIfNecessary(activity);
@@ -346,7 +404,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
TaskFragmentContainer getTopActiveContainer() {
for (int i = mContainers.size() - 1; i >= 0; i--) {
TaskFragmentContainer container = mContainers.get(i);
- if (!container.isFinished()) {
+ if (!container.isFinished() && container.getTopNonFinishingActivity() != null) {
return container;
}
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java
index 3c7d2de6165f..a801dc8193fd 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java
@@ -37,32 +37,42 @@ class TaskFragmentAnimationController {
private final TaskFragmentOrganizer mOrganizer;
private final TaskFragmentAnimationRunner mRemoteRunner = new TaskFragmentAnimationRunner();
+ private final RemoteAnimationDefinition mDefinition;
+ private boolean mIsRegister;
TaskFragmentAnimationController(TaskFragmentOrganizer organizer) {
mOrganizer = organizer;
+ mDefinition = new RemoteAnimationDefinition();
+ final RemoteAnimationAdapter animationAdapter =
+ new RemoteAnimationAdapter(mRemoteRunner, 0, 0, true /* changeNeedsSnapshot */);
+ mDefinition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, animationAdapter);
+ mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, animationAdapter);
+ mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_OPEN, animationAdapter);
+ mDefinition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, animationAdapter);
+ mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, animationAdapter);
+ mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_CLOSE, animationAdapter);
+ mDefinition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter);
}
void registerRemoteAnimations() {
if (DEBUG) {
Log.v(TAG, "registerRemoteAnimations");
}
- final RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
- final RemoteAnimationAdapter animationAdapter =
- new RemoteAnimationAdapter(mRemoteRunner, 0, 0, true /* changeNeedsSnapshot */);
- definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, animationAdapter);
- definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, animationAdapter);
- definition.addRemoteAnimation(TRANSIT_OLD_TASK_OPEN, animationAdapter);
- definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, animationAdapter);
- definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, animationAdapter);
- definition.addRemoteAnimation(TRANSIT_OLD_TASK_CLOSE, animationAdapter);
- definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter);
- mOrganizer.registerRemoteAnimations(definition);
+ if (mIsRegister) {
+ return;
+ }
+ mOrganizer.registerRemoteAnimations(mDefinition);
+ mIsRegister = true;
}
void unregisterRemoteAnimations() {
if (DEBUG) {
Log.v(TAG, "unregisterRemoteAnimations");
}
+ if (!mIsRegister) {
+ return;
+ }
mOrganizer.unregisterRemoteAnimations();
+ mIsRegister = false;
}
}
diff --git a/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml b/libs/WindowManager/Shell/res/layout/background_panel.xml
index 54bb1fcab54b..c3569d80fa1e 100644
--- a/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml
+++ b/libs/WindowManager/Shell/res/layout/background_panel.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
+
<!--
- ~ Copyright (C) 2021 The Android Open Source Project
+ ~ Copyright (C) 2022 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
@@ -12,15 +13,14 @@
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
- ~ limitations under the License.
+ ~ limitations under the License
-->
-
-<resources>
- <!-- Allows PIN/Pattern to be drawn on one side of a display, and for the user to
- switch sides -->
- <bool name="can_use_one_handed_bouncer">false</bool>
-
- <!-- Will display the bouncer on one side of the display, and the current user icon and
- user switcher on the other side -->
- <bool name="bouncer_display_user_switcher">true</bool>
-</resources>
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/background_panel_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_horizontal | center_vertical"
+ android:background="@android:color/transparent">
+</LinearLayout> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index eaeade82ebb6..cf4647a09a58 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -364,13 +364,15 @@ public class Bubble implements BubbleViewProvider {
* @param context the context for the bubble.
* @param controller the bubble controller.
* @param stackView the stackView the bubble is eventually added to.
- * @param iconFactory the iconfactory use to create badged images for the bubble.
+ * @param iconFactory the icon factory use to create images for the bubble.
+ * @param badgeIconFactory the icon factory to create app badges for the bubble.
*/
void inflate(BubbleViewInfoTask.Callback callback,
Context context,
BubbleController controller,
BubbleStackView stackView,
BubbleIconFactory iconFactory,
+ BubbleBadgeIconFactory badgeIconFactory,
boolean skipInflation) {
if (isBubbleLoading()) {
mInflationTask.cancel(true /* mayInterruptIfRunning */);
@@ -380,6 +382,7 @@ public class Bubble implements BubbleViewProvider {
controller,
stackView,
iconFactory,
+ badgeIconFactory,
skipInflation,
callback,
mMainExecutor);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
new file mode 100644
index 000000000000..4eeb20769e09
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleBadgeIconFactory.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.bubbles;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.Drawable;
+
+import com.android.launcher3.icons.BaseIconFactory;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.ShadowGenerator;
+import com.android.wm.shell.R;
+
+/**
+ * Factory for creating app badge icons that are shown on bubbles.
+ */
+public class BubbleBadgeIconFactory extends BaseIconFactory {
+
+ public BubbleBadgeIconFactory(Context context) {
+ super(context, context.getResources().getConfiguration().densityDpi,
+ context.getResources().getDimensionPixelSize(R.dimen.bubble_badge_size));
+ }
+
+ /**
+ * Returns a {@link BitmapInfo} for the app-badge that is shown on top of each bubble. This
+ * will include the workprofile indicator on the badge if appropriate.
+ */
+ BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) {
+ ShadowGenerator shadowGenerator = new ShadowGenerator(mIconBitmapSize);
+ Bitmap userBadgedBitmap = createIconBitmap(userBadgedAppIcon, 1f, mIconBitmapSize);
+
+ if (userBadgedAppIcon instanceof AdaptiveIconDrawable) {
+ userBadgedBitmap = Bitmap.createScaledBitmap(
+ getCircleBitmap((AdaptiveIconDrawable) userBadgedAppIcon, /* size */
+ userBadgedAppIcon.getIntrinsicWidth()),
+ mIconBitmapSize, mIconBitmapSize, /* filter */ true);
+ }
+
+ if (isImportantConversation) {
+ final float ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.importance_ring_stroke_width);
+ final int importantConversationColor = mContext.getResources().getColor(
+ R.color.important_conversation, null);
+ Bitmap badgeAndRing = Bitmap.createBitmap(userBadgedBitmap.getWidth(),
+ userBadgedBitmap.getHeight(), userBadgedBitmap.getConfig());
+ Canvas c = new Canvas(badgeAndRing);
+
+ Paint ringPaint = new Paint();
+ ringPaint.setStyle(Paint.Style.FILL);
+ ringPaint.setColor(importantConversationColor);
+ ringPaint.setAntiAlias(true);
+ c.drawCircle(c.getWidth() / 2, c.getHeight() / 2, c.getWidth() / 2, ringPaint);
+
+ final int bitmapTop = (int) ringStrokeWidth;
+ final int bitmapLeft = (int) ringStrokeWidth;
+ final int bitmapWidth = c.getWidth() - 2 * (int) ringStrokeWidth;
+ final int bitmapHeight = c.getHeight() - 2 * (int) ringStrokeWidth;
+
+ Bitmap scaledBitmap = Bitmap.createScaledBitmap(userBadgedBitmap, bitmapWidth,
+ bitmapHeight, /* filter */ true);
+ c.drawBitmap(scaledBitmap, bitmapTop, bitmapLeft, /* paint */null);
+
+ shadowGenerator.recreateIcon(Bitmap.createBitmap(badgeAndRing), c);
+ return createIconBitmap(badgeAndRing);
+ } else {
+ Canvas c = new Canvas();
+ c.setBitmap(userBadgedBitmap);
+ shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
+ return createIconBitmap(userBadgedBitmap);
+ }
+ }
+
+ private Bitmap getCircleBitmap(AdaptiveIconDrawable icon, int size) {
+ Drawable foreground = icon.getForeground();
+ Drawable background = icon.getBackground();
+ Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas();
+ canvas.setBitmap(bitmap);
+
+ // Clip canvas to circle.
+ Path circlePath = new Path();
+ circlePath.addCircle(/* x */ size / 2f,
+ /* y */ size / 2f,
+ /* radius */ size / 2f,
+ Path.Direction.CW);
+ canvas.clipPath(circlePath);
+
+ // Draw background.
+ background.setBounds(0, 0, size, size);
+ background.draw(canvas);
+
+ // Draw foreground. The foreground and background drawables are derived from adaptive icons
+ // Some icon shapes fill more space than others, so adaptive icons are normalized to about
+ // the same size. This size is smaller than the original bounds, so we estimate
+ // the difference in this offset.
+ int offset = size / 5;
+ foreground.setBounds(-offset, -offset, size + offset, size + offset);
+ foreground.draw(canvas);
+
+ canvas.setBitmap(null);
+ return bitmap;
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 7903a5102dde..22bec3d63bcf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -151,6 +151,7 @@ public class BubbleController {
private BubbleData mBubbleData;
@Nullable private BubbleStackView mStackView;
private BubbleIconFactory mBubbleIconFactory;
+ private BubbleBadgeIconFactory mBubbleBadgeIconFactory;
private BubblePositioner mBubblePositioner;
private Bubbles.SysuiProxy mSysuiProxy;
@@ -278,6 +279,7 @@ public class BubbleController {
mBubbleData = data;
mSavedBubbleKeysPerUser = new SparseSetArray<>();
mBubbleIconFactory = new BubbleIconFactory(context);
+ mBubbleBadgeIconFactory = new BubbleBadgeIconFactory(context);
mDisplayController = displayController;
mTaskViewTransitions = taskViewTransitions;
mOneHandedOptional = oneHandedOptional;
@@ -500,6 +502,7 @@ public class BubbleController {
}
mStackView.updateStackPosition();
mBubbleIconFactory = new BubbleIconFactory(mContext);
+ mBubbleBadgeIconFactory = new BubbleBadgeIconFactory(mContext);
mStackView.onDisplaySizeChanged();
}
if (b.getBoolean(EXTRA_BUBBLE_OVERFLOW_OPENED, false)) {
@@ -778,13 +781,17 @@ public class BubbleController {
mStackView.onThemeChanged();
}
mBubbleIconFactory = new BubbleIconFactory(mContext);
+ mBubbleBadgeIconFactory = new BubbleBadgeIconFactory(mContext);
+
// Reload each bubble
- for (Bubble b: mBubbleData.getBubbles()) {
+ for (Bubble b : mBubbleData.getBubbles()) {
b.inflate(null /* callback */, mContext, this, mStackView, mBubbleIconFactory,
+ mBubbleBadgeIconFactory,
false /* skipInflation */);
}
- for (Bubble b: mBubbleData.getOverflowBubbles()) {
+ for (Bubble b : mBubbleData.getOverflowBubbles()) {
b.inflate(null /* callback */, mContext, this, mStackView, mBubbleIconFactory,
+ mBubbleBadgeIconFactory,
false /* skipInflation */);
}
}
@@ -800,6 +807,7 @@ public class BubbleController {
mScreenBounds.set(newConfig.windowConfiguration.getBounds());
mBubbleData.onMaxBubblesChanged();
mBubbleIconFactory = new BubbleIconFactory(mContext);
+ mBubbleBadgeIconFactory = new BubbleBadgeIconFactory(mContext);
mStackView.onDisplaySizeChanged();
}
if (newConfig.fontScale != mFontScale) {
@@ -961,7 +969,8 @@ public class BubbleController {
}
bubble.inflate(
(b) -> mBubbleData.overflowBubble(Bubbles.DISMISS_RELOAD_FROM_DISK, bubble),
- mContext, this, mStackView, mBubbleIconFactory, true /* skipInflation */);
+ mContext, this, mStackView, mBubbleIconFactory, mBubbleBadgeIconFactory,
+ true /* skipInflation */);
});
return null;
});
@@ -996,7 +1005,8 @@ public class BubbleController {
ensureStackViewCreated();
bubble.setInflateSynchronously(mInflateSynchronously);
bubble.inflate(b -> mBubbleData.notificationEntryUpdated(b, suppressFlyout, showInShade),
- mContext, this, mStackView, mBubbleIconFactory, false /* skipInflation */);
+ mContext, this, mStackView, mBubbleIconFactory, mBubbleBadgeIconFactory,
+ false /* skipInflation */);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
index 9374da4c4fab..f878a46d26f2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
@@ -231,8 +231,9 @@ public class BubbleFlyoutView extends FrameLayout {
* Fade animation for consecutive flyouts.
*/
void animateUpdate(Bubble.FlyoutMessage flyoutMessage, PointF stackPos,
- boolean hideDot, Runnable onHide) {
+ boolean hideDot, float[] dotCenter, Runnable onHide) {
mOnHide = onHide;
+ mDotCenter = dotCenter;
final Runnable afterFadeOut = () -> {
updateFlyoutMessage(flyoutMessage);
// Wait for TextViews to layout with updated height.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
index b0e029fdc681..9d3bf34895d3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleIconFactory.java
@@ -21,19 +21,12 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import androidx.annotation.VisibleForTesting;
import com.android.launcher3.icons.BaseIconFactory;
-import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.ShadowGenerator;
import com.android.wm.shell.R;
/**
@@ -44,12 +37,9 @@ import com.android.wm.shell.R;
@VisibleForTesting
public class BubbleIconFactory extends BaseIconFactory {
- private int mBadgeSize;
-
public BubbleIconFactory(Context context) {
super(context, context.getResources().getConfiguration().densityDpi,
context.getResources().getDimensionPixelSize(R.dimen.bubble_size));
- mBadgeSize = mContext.getResources().getDimensionPixelSize(R.dimen.bubble_badge_size);
}
/**
@@ -75,84 +65,4 @@ public class BubbleIconFactory extends BaseIconFactory {
return null;
}
}
-
- /**
- * Returns a {@link BitmapInfo} for the app-badge that is shown on top of each bubble. This
- * will include the workprofile indicator on the badge if appropriate.
- */
- BitmapInfo getBadgeBitmap(Drawable userBadgedAppIcon, boolean isImportantConversation) {
- ShadowGenerator shadowGenerator = new ShadowGenerator(mBadgeSize);
- Bitmap userBadgedBitmap = createIconBitmap(userBadgedAppIcon, 1f, mBadgeSize);
-
- if (userBadgedAppIcon instanceof AdaptiveIconDrawable) {
- userBadgedBitmap = Bitmap.createScaledBitmap(
- getCircleBitmap((AdaptiveIconDrawable) userBadgedAppIcon, /* size */
- userBadgedAppIcon.getIntrinsicWidth()),
- mBadgeSize, mBadgeSize, /* filter */ true);
- }
-
- if (isImportantConversation) {
- final float ringStrokeWidth = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.importance_ring_stroke_width);
- final int importantConversationColor = mContext.getResources().getColor(
- R.color.important_conversation, null);
- Bitmap badgeAndRing = Bitmap.createBitmap(userBadgedBitmap.getWidth(),
- userBadgedBitmap.getHeight(), userBadgedBitmap.getConfig());
- Canvas c = new Canvas(badgeAndRing);
-
- Paint ringPaint = new Paint();
- ringPaint.setStyle(Paint.Style.FILL);
- ringPaint.setColor(importantConversationColor);
- ringPaint.setAntiAlias(true);
- c.drawCircle(c.getWidth() / 2, c.getHeight() / 2, c.getWidth() / 2, ringPaint);
-
- final int bitmapTop = (int) ringStrokeWidth;
- final int bitmapLeft = (int) ringStrokeWidth;
- final int bitmapWidth = c.getWidth() - 2 * (int) ringStrokeWidth;
- final int bitmapHeight = c.getHeight() - 2 * (int) ringStrokeWidth;
-
- Bitmap scaledBitmap = Bitmap.createScaledBitmap(userBadgedBitmap, bitmapWidth,
- bitmapHeight, /* filter */ true);
- c.drawBitmap(scaledBitmap, bitmapTop, bitmapLeft, /* paint */null);
-
- shadowGenerator.recreateIcon(Bitmap.createBitmap(badgeAndRing), c);
- return createIconBitmap(badgeAndRing);
- } else {
- Canvas c = new Canvas();
- c.setBitmap(userBadgedBitmap);
- shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
- return createIconBitmap(userBadgedBitmap);
- }
- }
-
- public Bitmap getCircleBitmap(AdaptiveIconDrawable icon, int size) {
- Drawable foreground = icon.getForeground();
- Drawable background = icon.getBackground();
- Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas();
- canvas.setBitmap(bitmap);
-
- // Clip canvas to circle.
- Path circlePath = new Path();
- circlePath.addCircle(/* x */ size / 2f,
- /* y */ size / 2f,
- /* radius */ size / 2f,
- Path.Direction.CW);
- canvas.clipPath(circlePath);
-
- // Draw background.
- background.setBounds(0, 0, size, size);
- background.draw(canvas);
-
- // Draw foreground. The foreground and background drawables are derived from adaptive icons
- // Some icon shapes fill more space than others, so adaptive icons are normalized to about
- // the same size. This size is smaller than the original bounds, so we estimate
- // the difference in this offset.
- int offset = size / 5;
- foreground.setBounds(-offset, -offset, size + offset, size + offset);
- foreground.draw(canvas);
-
- canvas.setBitmap(null);
- return bitmap;
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 7bf4439410f9..d5d8b71056d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -2516,6 +2516,7 @@ public class BubbleStackView extends FrameLayout
if (mFlyout.getVisibility() == View.VISIBLE) {
mFlyout.animateUpdate(bubble.getFlyoutMessage(),
mStackAnimationController.getStackPosition(), !bubble.showDot(),
+ bubble.getIconView().getDotCenter(),
mAfterFlyoutHidden /* onHide */);
} else {
mFlyout.setVisibility(INVISIBLE);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
index b01c756c5a7e..69762c9bc06a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java
@@ -71,6 +71,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
private WeakReference<BubbleController> mController;
private WeakReference<BubbleStackView> mStackView;
private BubbleIconFactory mIconFactory;
+ private BubbleBadgeIconFactory mBadgeIconFactory;
private boolean mSkipInflation;
private Callback mCallback;
private Executor mMainExecutor;
@@ -84,6 +85,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
BubbleController controller,
BubbleStackView stackView,
BubbleIconFactory factory,
+ BubbleBadgeIconFactory badgeFactory,
boolean skipInflation,
Callback c,
Executor mainExecutor) {
@@ -92,6 +94,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
mController = new WeakReference<>(controller);
mStackView = new WeakReference<>(stackView);
mIconFactory = factory;
+ mBadgeIconFactory = badgeFactory;
mSkipInflation = skipInflation;
mCallback = c;
mMainExecutor = mainExecutor;
@@ -100,7 +103,7 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
@Override
protected BubbleViewInfo doInBackground(Void... voids) {
return BubbleViewInfo.populate(mContext.get(), mController.get(), mStackView.get(),
- mIconFactory, mBubble, mSkipInflation);
+ mIconFactory, mBadgeIconFactory, mBubble, mSkipInflation);
}
@Override
@@ -135,7 +138,8 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
@VisibleForTesting
@Nullable
public static BubbleViewInfo populate(Context c, BubbleController controller,
- BubbleStackView stackView, BubbleIconFactory iconFactory, Bubble b,
+ BubbleStackView stackView, BubbleIconFactory iconFactory,
+ BubbleBadgeIconFactory badgeIconFactory, Bubble b,
boolean skipInflation) {
BubbleViewInfo info = new BubbleViewInfo();
@@ -187,11 +191,11 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
bubbleDrawable = appIcon;
}
- BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon,
+ BitmapInfo badgeBitmapInfo = badgeIconFactory.getBadgeBitmap(badgedIcon,
b.isImportantConversation());
info.badgeBitmap = badgeBitmapInfo.icon;
// Raw badge bitmap never includes the important conversation ring
- info.mRawBadgeBitmap = iconFactory.getBadgeBitmap(badgedIcon, false).icon;
+ info.mRawBadgeBitmap = badgeIconFactory.getBadgeBitmap(badgedIcon, false).icon;
info.bubbleBitmap = iconFactory.createBadgedIconBitmap(bubbleDrawable).icon;
// Dot color & placement
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index ad9ebb2ef6ae..36e55bae18c3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -137,14 +137,16 @@ public class SplitDecorManager extends WindowlessWindowManager {
return;
}
- if (mIcon == null) {
- // TODO: add fade-in animation.
+ if (mBackgroundLeash == null) {
mBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
RESIZING_BACKGROUND_SURFACE_NAME, mSurfaceSession);
t.setColor(mBackgroundLeash, getResizingBackgroundColor(resizingTask))
.setLayer(mBackgroundLeash, SPLIT_DIVIDER_LAYER - 1)
.show(mBackgroundLeash);
+ }
+ if (mIcon == null && resizingTask.topActivityInfo != null) {
+ // TODO: add fade-in animation.
mIcon = mIconProvider.getIcon(resizingTask.topActivityInfo);
mResizingIconView.setImageDrawable(mIcon);
mResizingIconView.setVisibility(View.VISIBLE);
@@ -168,12 +170,16 @@ public class SplitDecorManager extends WindowlessWindowManager {
return;
}
+ if (mBackgroundLeash != null) {
+ t.remove(mBackgroundLeash);
+ mBackgroundLeash = null;
+ }
+
if (mIcon != null) {
mResizingIconView.setVisibility(View.GONE);
mResizingIconView.setImageDrawable(null);
- t.remove(mBackgroundLeash).hide(mIconLeash);
+ t.hide(mIconLeash);
mIcon = null;
- mBackgroundLeash = null;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
new file mode 100644
index 000000000000..c20b7d9b2747
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/BackgroundWindowManager.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.onehanded;
+
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+
+import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
+import static com.android.wm.shell.onehanded.OneHandedState.STATE_ENTERING;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.os.Binder;
+import android.util.Slog;
+import android.view.ContextThemeWrapper;
+import android.view.IWindow;
+import android.view.LayoutInflater;
+import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.SurfaceSession;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowlessWindowManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.common.DisplayLayout;
+
+import java.io.PrintWriter;
+
+/**
+ * Holds view hierarchy of a root surface and helps inflate a themeable view for background.
+ */
+public final class BackgroundWindowManager extends WindowlessWindowManager {
+ private static final String TAG = BackgroundWindowManager.class.getSimpleName();
+ private static final int THEME_COLOR_OFFSET = 10;
+
+ private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
+ mTransactionFactory;
+
+ private Context mContext;
+ private Rect mDisplayBounds;
+ private SurfaceControlViewHost mViewHost;
+ private SurfaceControl mLeash;
+ private View mBackgroundView;
+ private @OneHandedState.State int mCurrentState;
+
+ public BackgroundWindowManager(Context context) {
+ super(context.getResources().getConfiguration(), null /* rootSurface */,
+ null /* hostInputToken */);
+ mContext = context;
+ mTransactionFactory = SurfaceControl.Transaction::new;
+ }
+
+ @Override
+ public SurfaceControl getSurfaceControl(IWindow window) {
+ return super.getSurfaceControl(window);
+ }
+
+ @Override
+ public void setConfiguration(Configuration configuration) {
+ super.setConfiguration(configuration);
+ mContext = mContext.createConfigurationContext(configuration);
+ }
+
+ /**
+ * onConfigurationChanged events for updating background theme color.
+ */
+ public void onConfigurationChanged() {
+ if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
+ updateThemeOnly();
+ }
+ }
+
+ /**
+ * One-handed mode state changed callback
+ * @param newState of One-handed mode representing by {@link OneHandedState}
+ */
+ public void onStateChanged(int newState) {
+ mCurrentState = newState;
+ }
+
+ @Override
+ protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
+ final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+ .setColorLayer()
+ .setBufferSize(mDisplayBounds.width(), mDisplayBounds.height())
+ .setFormat(PixelFormat.RGB_888)
+ .setOpaque(true)
+ .setName(TAG)
+ .setCallsite("BackgroundWindowManager#attachToParentSurface");
+ mLeash = builder.build();
+ b.setParent(mLeash);
+ }
+
+ /** Inflates background view on to the root surface. */
+ boolean initView() {
+ if (mBackgroundView != null || mViewHost != null) {
+ return false;
+ }
+
+ mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+ mBackgroundView = (View) LayoutInflater.from(mContext)
+ .inflate(R.layout.background_panel, null /* root */);
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ mDisplayBounds.width(), mDisplayBounds.height(), 0 /* TYPE NONE */,
+ FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL | FLAG_WATCH_OUTSIDE_TOUCH
+ | FLAG_SLIPPERY, PixelFormat.TRANSLUCENT);
+ lp.token = new Binder();
+ lp.setTitle("background-panel");
+ lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
+ mBackgroundView.setBackgroundColor(getThemeColorForBackground());
+ mViewHost.setView(mBackgroundView, lp);
+ return true;
+ }
+
+ /**
+ * Called when onDisplayAdded() or onDisplayRemoved() callback.
+ * @param displayLayout The latest {@link DisplayLayout} for display bounds.
+ */
+ public void onDisplayChanged(DisplayLayout displayLayout) {
+ // One-handed mode is only available on portrait.
+ if (displayLayout.height() > displayLayout.width()) {
+ mDisplayBounds = new Rect(0, 0, displayLayout.width(), displayLayout.height());
+ } else {
+ mDisplayBounds = new Rect(0, 0, displayLayout.height(), displayLayout.width());
+ }
+ }
+
+ private void updateThemeOnly() {
+ if (mBackgroundView == null || mViewHost == null || mLeash == null) {
+ Slog.w(TAG, "Background view or SurfaceControl does not exist when trying to "
+ + "update theme only!");
+ return;
+ }
+
+ WindowManager.LayoutParams lp = (WindowManager.LayoutParams)
+ mBackgroundView.getLayoutParams();
+ mBackgroundView.setBackgroundColor(getThemeColorForBackground());
+ mViewHost.setView(mBackgroundView, lp);
+ }
+
+ /**
+ * Shows the background layer when One-handed mode triggered.
+ */
+ public void showBackgroundLayer() {
+ if (!initView()) {
+ updateThemeOnly();
+ return;
+ }
+ if (mLeash == null) {
+ Slog.w(TAG, "SurfaceControl mLeash is null, can't show One-handed mode "
+ + "background panel!");
+ return;
+ }
+
+ mTransactionFactory.getTransaction()
+ .setAlpha(mLeash, 1.0f)
+ .setLayer(mLeash, -1 /* at bottom-most layer */)
+ .show(mLeash)
+ .apply();
+ }
+
+ /**
+ * Remove the leash of background layer after stop One-handed mode.
+ */
+ public void removeBackgroundLayer() {
+ if (mBackgroundView != null) {
+ mBackgroundView = null;
+ }
+
+ if (mViewHost != null) {
+ mViewHost.release();
+ mViewHost = null;
+ }
+
+ if (mLeash != null) {
+ mTransactionFactory.getTransaction().remove(mLeash).apply();
+ mLeash = null;
+ }
+ }
+
+ /**
+ * Gets {@link SurfaceControl} of the background layer.
+ * @return {@code null} if not exist.
+ */
+ @Nullable
+ SurfaceControl getSurfaceControl() {
+ return mLeash;
+ }
+
+ private int getThemeColor() {
+ final Context themedContext = new ContextThemeWrapper(mContext,
+ com.android.internal.R.style.Theme_DeviceDefault_DayNight);
+ return themedContext.getColor(R.color.one_handed_tutorial_background_color);
+ }
+
+ int getThemeColorForBackground() {
+ final int origThemeColor = getThemeColor();
+ return android.graphics.Color.argb(Color.alpha(origThemeColor),
+ Color.red(origThemeColor) - THEME_COLOR_OFFSET,
+ Color.green(origThemeColor) - THEME_COLOR_OFFSET,
+ Color.blue(origThemeColor) - THEME_COLOR_OFFSET);
+ }
+
+ private float adjustColor(int origColor) {
+ return Math.max(origColor - THEME_COLOR_OFFSET, 0) / 255.0f;
+ }
+
+ void dump(@NonNull PrintWriter pw) {
+ final String innerPrefix = " ";
+ pw.println(TAG);
+ pw.print(innerPrefix + "mDisplayBounds=");
+ pw.println(mDisplayBounds);
+ pw.print(innerPrefix + "mViewHost=");
+ pw.println(mViewHost);
+ pw.print(innerPrefix + "mLeash=");
+ pw.println(mLeash);
+ pw.print(innerPrefix + "mBackgroundView=");
+ pw.println(mBackgroundView);
+ }
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
deleted file mode 100644
index 9e1c61aac868..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.onehanded;
-
-import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
-
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.view.ContextThemeWrapper;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-import android.view.animation.LinearInterpolator;
-import android.window.DisplayAreaAppearedInfo;
-import android.window.DisplayAreaInfo;
-import android.window.DisplayAreaOrganizer;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import com.android.wm.shell.R;
-import com.android.wm.shell.common.DisplayLayout;
-
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.concurrent.Executor;
-
-/**
- * Manages OneHanded color background layer areas.
- * To avoid when turning the Dark theme on, users can not clearly identify
- * the screen has entered one handed mode.
- */
-public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer
- implements OneHandedAnimationCallback, OneHandedState.OnStateChangedListener {
- private static final String TAG = "OneHandedBackgroundPanelOrganizer";
- private static final int THEME_COLOR_OFFSET = 10;
- private static final int ALPHA_ANIMATION_DURATION = 200;
-
- private final Context mContext;
- private final SurfaceSession mSurfaceSession = new SurfaceSession();
- private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
- mTransactionFactory;
-
- private @OneHandedState.State int mCurrentState;
- private ValueAnimator mAlphaAnimator;
-
- private float mTranslationFraction;
- private float[] mThemeColor;
-
- /**
- * The background to distinguish the boundary of translated windows and empty region when
- * one handed mode triggered.
- */
- private Rect mBkgBounds;
- private Rect mStableInsets;
-
- @Nullable
- @VisibleForTesting
- SurfaceControl mBackgroundSurface;
- @Nullable
- private SurfaceControl mParentLeash;
-
- public OneHandedBackgroundPanelOrganizer(Context context, DisplayLayout displayLayout,
- OneHandedSettingsUtil settingsUtil, Executor executor) {
- super(executor);
- mContext = context;
- mTranslationFraction = settingsUtil.getTranslationFraction(context);
- mTransactionFactory = SurfaceControl.Transaction::new;
- updateThemeColors();
- }
-
- @Override
- public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
- @NonNull SurfaceControl leash) {
- mParentLeash = leash;
- }
-
- @Override
- public List<DisplayAreaAppearedInfo> registerOrganizer(int displayAreaFeature) {
- final List<DisplayAreaAppearedInfo> displayAreaInfos;
- displayAreaInfos = super.registerOrganizer(displayAreaFeature);
- for (int i = 0; i < displayAreaInfos.size(); i++) {
- final DisplayAreaAppearedInfo info = displayAreaInfos.get(i);
- onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash());
- }
- return displayAreaInfos;
- }
-
- @Override
- public void unregisterOrganizer() {
- super.unregisterOrganizer();
- removeBackgroundPanelLayer();
- mParentLeash = null;
- }
-
- @Override
- public void onAnimationUpdate(SurfaceControl.Transaction tx, float xPos, float yPos) {
- final int yTopPos = (mStableInsets.top - mBkgBounds.height()) + Math.round(yPos);
- tx.setPosition(mBackgroundSurface, 0, yTopPos);
- }
-
- @Nullable
- @VisibleForTesting
- boolean isRegistered() {
- return mParentLeash != null;
- }
-
- void createBackgroundSurface() {
- mBackgroundSurface = new SurfaceControl.Builder(mSurfaceSession)
- .setBufferSize(mBkgBounds.width(), mBkgBounds.height())
- .setColorLayer()
- .setFormat(PixelFormat.RGB_888)
- .setOpaque(true)
- .setName("one-handed-background-panel")
- .setCallsite("OneHandedBackgroundPanelOrganizer")
- .build();
-
- // TODO(185890335) Avoid Dimming for mid-range luminance wallpapers flash.
- mAlphaAnimator = ValueAnimator.ofFloat(1.0f, 0.0f);
- mAlphaAnimator.setInterpolator(new LinearInterpolator());
- mAlphaAnimator.setDuration(ALPHA_ANIMATION_DURATION);
- mAlphaAnimator.addUpdateListener(
- animator -> detachBackgroundFromParent(animator));
- }
-
- void detachBackgroundFromParent(ValueAnimator animator) {
- if (mBackgroundSurface == null || mParentLeash == null) {
- return;
- }
- // TODO(185890335) Avoid Dimming for mid-range luminance wallpapers flash.
- final float currentValue = (float) animator.getAnimatedValue();
- final SurfaceControl.Transaction tx = mTransactionFactory.getTransaction();
- if (currentValue == 0.0f) {
- tx.reparent(mBackgroundSurface, null).apply();
- } else {
- tx.setAlpha(mBackgroundSurface, (float) animator.getAnimatedValue()).apply();
- }
- }
-
- /**
- * Called when onDisplayAdded() or onDisplayRemoved() callback.
- *
- * @param displayLayout The latest {@link DisplayLayout} representing current displayId
- */
- public void onDisplayChanged(DisplayLayout displayLayout) {
- mStableInsets = displayLayout.stableInsets();
- // Ensure the mBkgBounds is portrait, due to OHM only support on portrait
- if (displayLayout.height() > displayLayout.width()) {
- mBkgBounds = new Rect(0, 0, displayLayout.width(),
- Math.round(displayLayout.height() * mTranslationFraction) + mStableInsets.top);
- } else {
- mBkgBounds = new Rect(0, 0, displayLayout.height(),
- Math.round(displayLayout.width() * mTranslationFraction) + mStableInsets.top);
- }
- }
-
- @VisibleForTesting
- void onStart() {
- if (mBackgroundSurface == null) {
- createBackgroundSurface();
- }
- showBackgroundPanelLayer();
- }
-
- /**
- * Called when transition finished.
- */
- public void onStopFinished() {
- if (mAlphaAnimator == null) {
- return;
- }
- mAlphaAnimator.start();
- }
-
- @VisibleForTesting
- void showBackgroundPanelLayer() {
- if (mParentLeash == null) {
- return;
- }
-
- if (mBackgroundSurface == null) {
- createBackgroundSurface();
- }
-
- // TODO(185890335) Avoid Dimming for mid-range luminance wallpapers flash.
- if (mAlphaAnimator.isRunning()) {
- mAlphaAnimator.end();
- }
-
- mTransactionFactory.getTransaction()
- .reparent(mBackgroundSurface, mParentLeash)
- .setAlpha(mBackgroundSurface, 1.0f)
- .setLayer(mBackgroundSurface, -1 /* at bottom-most layer */)
- .setColor(mBackgroundSurface, mThemeColor)
- .show(mBackgroundSurface)
- .apply();
- }
-
- @VisibleForTesting
- void removeBackgroundPanelLayer() {
- if (mBackgroundSurface == null) {
- return;
- }
-
- mTransactionFactory.getTransaction()
- .remove(mBackgroundSurface)
- .apply();
- mBackgroundSurface = null;
- }
-
- /**
- * onConfigurationChanged events for updating tutorial text.
- */
- public void onConfigurationChanged() {
- updateThemeColors();
-
- if (mCurrentState != STATE_ACTIVE) {
- return;
- }
- showBackgroundPanelLayer();
- }
-
- private void updateThemeColors() {
- final Context themedContext = new ContextThemeWrapper(mContext,
- com.android.internal.R.style.Theme_DeviceDefault_DayNight);
- final int themeColor = themedContext.getColor(
- R.color.one_handed_tutorial_background_color);
- mThemeColor = new float[]{
- adjustColor(Color.red(themeColor)),
- adjustColor(Color.green(themeColor)),
- adjustColor(Color.blue(themeColor))};
- }
-
- private float adjustColor(int origColor) {
- return Math.max(origColor - THEME_COLOR_OFFSET, 0) / 255.0f;
- }
-
- @Override
- public void onStateChanged(int newState) {
- mCurrentState = newState;
- }
-
- void dump(@NonNull PrintWriter pw) {
- final String innerPrefix = " ";
- pw.println(TAG);
- pw.print(innerPrefix + "mBackgroundSurface=");
- pw.println(mBackgroundSurface);
- pw.print(innerPrefix + "mBkgBounds=");
- pw.println(mBkgBounds);
- pw.print(innerPrefix + "mThemeColor=");
- pw.println(mThemeColor);
- pw.print(innerPrefix + "mTranslationFraction=");
- pw.println(mTranslationFraction);
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 96f82fa5ce36..48acfc1c76e7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -99,7 +99,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
private OneHandedEventCallback mEventCallback;
private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
- private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;
private OneHandedUiEventLogger mOneHandedUiEventLogger;
private final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
@@ -163,7 +162,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
public void onStopFinished(Rect bounds) {
mState.setState(STATE_NONE);
notifyShortcutStateChanged(STATE_NONE);
- mBackgroundPanelOrganizer.onStopFinished();
}
};
@@ -201,32 +199,28 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
OneHandedAccessibilityUtil accessibilityUtil = new OneHandedAccessibilityUtil(context);
OneHandedTimeoutHandler timeoutHandler = new OneHandedTimeoutHandler(mainExecutor);
OneHandedState oneHandedState = new OneHandedState();
+ BackgroundWindowManager backgroundWindowManager = new BackgroundWindowManager(context);
OneHandedTutorialHandler tutorialHandler = new OneHandedTutorialHandler(context,
- settingsUtil, windowManager);
+ settingsUtil, windowManager, backgroundWindowManager);
OneHandedAnimationController animationController =
new OneHandedAnimationController(context);
OneHandedTouchHandler touchHandler = new OneHandedTouchHandler(timeoutHandler,
mainExecutor);
- OneHandedBackgroundPanelOrganizer oneHandedBackgroundPanelOrganizer =
- new OneHandedBackgroundPanelOrganizer(context, displayLayout, settingsUtil,
- mainExecutor);
OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
context, displayLayout, settingsUtil, animationController, tutorialHandler,
- oneHandedBackgroundPanelOrganizer, jankMonitor, mainExecutor);
+ jankMonitor, mainExecutor);
OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger);
IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
ServiceManager.getService(Context.OVERLAY_SERVICE));
- return new OneHandedController(context, displayController,
- oneHandedBackgroundPanelOrganizer, organizer, touchHandler, tutorialHandler,
- settingsUtil, accessibilityUtil, timeoutHandler, oneHandedState, jankMonitor,
- oneHandedUiEventsLogger, overlayManager, taskStackListener, mainExecutor,
- mainHandler);
+ return new OneHandedController(context, displayController, organizer, touchHandler,
+ tutorialHandler, settingsUtil, accessibilityUtil, timeoutHandler, oneHandedState,
+ jankMonitor, oneHandedUiEventsLogger, overlayManager, taskStackListener,
+ mainExecutor, mainHandler);
}
@VisibleForTesting
OneHandedController(Context context,
DisplayController displayController,
- OneHandedBackgroundPanelOrganizer backgroundPanelOrganizer,
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
OneHandedTouchHandler touchHandler,
OneHandedTutorialHandler tutorialHandler,
@@ -243,7 +237,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
mContext = context;
mOneHandedSettingsUtil = settingsUtil;
mOneHandedAccessibilityUtil = oneHandedAccessibilityUtil;
- mBackgroundPanelOrganizer = backgroundPanelOrganizer;
mDisplayAreaOrganizer = displayAreaOrganizer;
mDisplayController = displayController;
mTouchHandler = touchHandler;
@@ -286,7 +279,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
mAccessibilityManager.addAccessibilityStateChangeListener(
mAccessibilityStateChangeListener);
- mState.addSListeners(mBackgroundPanelOrganizer);
mState.addSListeners(mTutorialHandler);
}
@@ -368,7 +360,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
mDisplayAreaOrganizer.getDisplayLayout().height() * mOffSetFraction);
mOneHandedAccessibilityUtil.announcementForScreenReader(
mOneHandedAccessibilityUtil.getOneHandedStartDescription());
- mBackgroundPanelOrganizer.onStart();
mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
mTimeoutHandler.resetTimer();
mOneHandedUiEventLogger.writeEvent(
@@ -461,7 +452,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
}
mDisplayAreaOrganizer.setDisplayLayout(newDisplayLayout);
mTutorialHandler.onDisplayChanged(newDisplayLayout);
- mBackgroundPanelOrganizer.onDisplayChanged(newDisplayLayout);
}
private ContentObserver getObserver(Runnable onChangeRunnable) {
@@ -585,7 +575,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
if (!mIsOneHandedEnabled) {
mDisplayAreaOrganizer.unregisterOrganizer();
- mBackgroundPanelOrganizer.unregisterOrganizer();
// Do NOT register + unRegister DA in the same call
return;
}
@@ -594,11 +583,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
mDisplayAreaOrganizer.registerOrganizer(
OneHandedDisplayAreaOrganizer.FEATURE_ONE_HANDED);
}
-
- if (!mBackgroundPanelOrganizer.isRegistered()) {
- mBackgroundPanelOrganizer.registerOrganizer(
- OneHandedBackgroundPanelOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL);
- }
}
@VisibleForTesting
@@ -613,13 +597,12 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
}
private void onConfigChanged(Configuration newConfig) {
- if (mTutorialHandler == null || mBackgroundPanelOrganizer == null) {
+ if (mTutorialHandler == null) {
return;
}
if (!mIsOneHandedEnabled || newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
return;
}
- mBackgroundPanelOrganizer.onConfigurationChanged();
mTutorialHandler.onConfigurationChanged();
}
@@ -650,10 +633,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
pw.print(innerPrefix + "mIsSwipeToNotificationEnabled=");
pw.println(mIsSwipeToNotificationEnabled);
- if (mBackgroundPanelOrganizer != null) {
- mBackgroundPanelOrganizer.dump(pw);
- }
-
if (mDisplayAreaOrganizer != null) {
mDisplayAreaOrganizer.dump(pw);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index 87eb40cbde62..f61d1b95bd85 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -80,7 +80,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
mSurfaceControlTransactionFactory;
private OneHandedTutorialHandler mTutorialHandler;
private List<OneHandedTransitionCallback> mTransitionCallbacks = new ArrayList<>();
- private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;
@VisibleForTesting
OneHandedAnimationCallback mOneHandedAnimationCallback =
@@ -135,7 +134,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
OneHandedSettingsUtil oneHandedSettingsUtil,
OneHandedAnimationController animationController,
OneHandedTutorialHandler tutorialHandler,
- OneHandedBackgroundPanelOrganizer oneHandedBackgroundGradientOrganizer,
InteractionJankMonitor jankMonitor,
ShellExecutor mainExecutor) {
super(mainExecutor);
@@ -150,7 +148,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
SystemProperties.getInt(ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION,
animationDurationConfig);
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
- mBackgroundPanelOrganizer = oneHandedBackgroundGradientOrganizer;
mTutorialHandler = tutorialHandler;
}
@@ -258,7 +255,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
animator.setTransitionDirection(direction)
.addOneHandedAnimationCallback(mOneHandedAnimationCallback)
.addOneHandedAnimationCallback(mTutorialHandler)
- .addOneHandedAnimationCallback(mBackgroundPanelOrganizer)
.setDuration(durationMs)
.start();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
index 88f33755fa2d..04e8cf9d2c44 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java
@@ -32,7 +32,6 @@ import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.os.SystemProperties;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -65,6 +64,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
private final float mTutorialHeightRatio;
private final WindowManager mWindowManager;
+ private final BackgroundWindowManager mBackgroundWindowManager;
private @OneHandedState.State int mCurrentState;
private int mTutorialAreaHeight;
@@ -79,9 +79,10 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
private int mAlphaAnimationDurationMs;
public OneHandedTutorialHandler(Context context, OneHandedSettingsUtil settingsUtil,
- WindowManager windowManager) {
+ WindowManager windowManager, BackgroundWindowManager backgroundWindowManager) {
mContext = context;
mWindowManager = windowManager;
+ mBackgroundWindowManager = backgroundWindowManager;
mTutorialHeightRatio = settingsUtil.getTranslationFraction(context);
mAlphaAnimationDurationMs = settingsUtil.getTransitionDuration(context);
}
@@ -110,8 +111,19 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
}
@Override
+ public void onStartFinished(Rect bounds) {
+ fillBackgroundColor();
+ }
+
+ @Override
+ public void onStopFinished(Rect bounds) {
+ removeBackgroundSurface();
+ }
+
+ @Override
public void onStateChanged(int newState) {
mCurrentState = newState;
+ mBackgroundWindowManager.onStateChanged(newState);
switch (newState) {
case STATE_ENTERING:
createViewAndAttachToWindow(mContext);
@@ -126,7 +138,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
case STATE_NONE:
checkTransitionEnd();
removeTutorialFromWindowManager();
- break;
default:
break;
}
@@ -146,6 +157,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
}
mTutorialAreaHeight = Math.round(mDisplayBounds.height() * mTutorialHeightRatio);
mAlphaTransitionStart = mTutorialAreaHeight * START_TRANSITION_FRACTION;
+ mBackgroundWindowManager.onDisplayChanged(displayLayout);
}
@VisibleForTesting
@@ -169,6 +181,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
private void attachTargetToWindow() {
try {
mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
+ mBackgroundWindowManager.showBackgroundLayer();
} catch (IllegalStateException e) {
// This shouldn't happen, but if the target is already added, just update its
// layout params.
@@ -186,6 +199,11 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
mTargetViewContainer = null;
}
+ @VisibleForTesting
+ void removeBackgroundSurface() {
+ mBackgroundWindowManager.removeBackgroundLayer();
+ }
+
/**
* Returns layout params for the dismiss target, using the latest display metrics.
*/
@@ -213,9 +231,12 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
* onConfigurationChanged events for updating tutorial text.
*/
public void onConfigurationChanged() {
+ mBackgroundWindowManager.onConfigurationChanged();
+
removeTutorialFromWindowManager();
if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
createViewAndAttachToWindow(mContext);
+ fillBackgroundColor();
updateThemeColor();
checkTransitionEnd();
}
@@ -247,6 +268,14 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
tutorialDesc.setTextColor(themedTextColorSecondary);
}
+ private void fillBackgroundColor() {
+ if (mTargetViewContainer == null || mBackgroundWindowManager == null) {
+ return;
+ }
+ mTargetViewContainer.setBackgroundColor(
+ mBackgroundWindowManager.getThemeColorForBackground());
+ }
+
private void setupAlphaTransition(boolean isEntering) {
final float start = isEntering ? 0.0f : 1.0f;
final float end = isEntering ? 1.0f : 0.0f;
@@ -282,5 +311,9 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
pw.println(mAlphaTransitionStart);
pw.print(innerPrefix + "mAlphaAnimationDurationMs=");
pw.println(mAlphaAnimationDurationMs);
+
+ if (mBackgroundWindowManager != null) {
+ mBackgroundWindowManager.dump(pw);
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 1716380c1f7c..69e78364c5e1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -155,7 +155,8 @@ public class PipTransition extends PipTransitionController {
switch (type) {
case TRANSIT_EXIT_PIP:
- startExitAnimation(info, startTransaction, finishCallback, exitPipChange);
+ startExitAnimation(info, startTransaction, finishTransaction, finishCallback,
+ exitPipChange);
break;
case TRANSIT_EXIT_PIP_TO_SPLIT:
startExitToSplitAnimation(info, startTransaction, finishTransaction,
@@ -283,6 +284,7 @@ public class PipTransition extends PipTransitionController {
private void startExitAnimation(@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
+ @NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback,
@NonNull TransitionInfo.Change pipChange) {
TransitionInfo.Change displayRotationChange = null;
@@ -298,8 +300,8 @@ public class PipTransition extends PipTransitionController {
if (displayRotationChange != null) {
// Exiting PIP to fullscreen with orientation change.
- startExpandAndRotationAnimation(info, startTransaction, finishCallback,
- displayRotationChange, pipChange);
+ startExpandAndRotationAnimation(info, startTransaction, finishTransaction,
+ finishCallback, displayRotationChange, pipChange);
return;
}
@@ -322,6 +324,7 @@ public class PipTransition extends PipTransitionController {
private void startExpandAndRotationAnimation(@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
+ @NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback,
@NonNull TransitionInfo.Change displayRotationChange,
@NonNull TransitionInfo.Change pipChange) {
@@ -335,7 +338,6 @@ public class PipTransition extends PipTransitionController {
rotator.handleClosingChanges(info, startTransaction, rotateDelta, displayW, displayH);
mFinishCallback = (wct, wctCB) -> {
- rotator.cleanUp();
mPipOrganizer.onExitPipFinished(pipChange.getTaskInfo());
finishCallback.onTransitionFinished(wct, wctCB);
};
@@ -366,6 +368,7 @@ public class PipTransition extends PipTransitionController {
endBounds, startBounds, new Rect(), degree, x, y, true /* isExpanding */,
pipRotateDelta == ROTATION_270 /* clockwise */);
startTransaction.apply();
+ rotator.cleanUp(finishTransaction);
// Expand and rotate the pip window to fullscreen.
final PipAnimationController.PipTransitionAnimator animator =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
index 92a359891003..915c5939c34b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
@@ -140,6 +140,7 @@ public class PipDismissTargetHandler implements ViewTreeObserver.OnPreDrawListen
});
mMagnetizedPip = mMotionHelper.getMagnetizedPip();
+ mMagnetizedPip.clearAllTargets();
mMagneticTarget = mMagnetizedPip.addTarget(mTargetView, 0);
updateMagneticTargetSize();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index 7decb54d16bb..338c944f7eec 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -292,7 +292,6 @@ public class RecentTasksController implements TaskStackListenerCallback,
* Invalidates this instance, preventing future calls from updating the controller.
*/
void invalidate() {
- Slog.d("b/206648922", "invalidating controller: " + mController);
mController = null;
}
@@ -313,13 +312,16 @@ public class RecentTasksController implements TaskStackListenerCallback,
@Override
public GroupedRecentTaskInfo[] getRecentTasks(int maxNum, int flags, int userId)
throws RemoteException {
+ if (mController == null) {
+ // The controller is already invalidated -- just return an empty task list for now
+ return new GroupedRecentTaskInfo[0];
+ }
+
final GroupedRecentTaskInfo[][] out = new GroupedRecentTaskInfo[][]{null};
executeRemoteCallWithTaskPermission(mController, "getRecentTasks",
(controller) -> out[0] = controller.getRecentTasks(maxNum, flags, userId)
.toArray(new GroupedRecentTaskInfo[0]),
true /* blocking */);
- Slog.d("b/206648922", "getRecentTasks(" + maxNum + "): " + out[0]
- + " mController=" + mController);
return out[0];
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java
index 08c99b2c4a83..8c71f749b2c3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java
@@ -35,13 +35,11 @@ import java.util.List;
*/
public class CounterRotatorHelper {
private final ArrayMap<WindowContainerToken, CounterRotator> mRotatorMap = new ArrayMap<>();
- private SurfaceControl mRootLeash;
/** Puts the surface controls of closing changes to counter-rotated surfaces. */
public void handleClosingChanges(@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
int rotateDelta, int displayW, int displayH) {
- mRootLeash = info.getRootLeash();
final List<TransitionInfo.Change> changes = info.getChanges();
final int numChanges = changes.size();
for (int i = numChanges - 1; i >= 0; --i) {
@@ -71,10 +69,15 @@ public class CounterRotatorHelper {
}
}
- /** Restores to the original state, i.e. reparent back to transition root. */
- public void cleanUp() {
+ /**
+ * Removes the counter rotation surface in the finish transaction. No need to reparent the
+ * children as the finish transaction should have already taken care of that.
+ *
+ * This can only be called after startTransaction for {@link #handleClosingChanges} is applied.
+ */
+ public void cleanUp(@NonNull SurfaceControl.Transaction finishTransaction) {
for (int i = mRotatorMap.size() - 1; i >= 0; --i) {
- mRotatorMap.valueAt(i).cleanUp(mRootLeash);
+ mRotatorMap.valueAt(i).cleanUp(finishTransaction);
}
mRotatorMap.clear();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 5833ca80d384..11b23875437f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -282,7 +282,6 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
final Runnable onAnimFinish = () -> {
if (!animations.isEmpty()) return;
- rotator.cleanUp();
if (mRotationAnimation != null) {
mRotationAnimation.kill();
mRotationAnimation = null;
@@ -382,6 +381,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
}
startTransaction.apply();
+ rotator.cleanUp(finishTransaction);
TransitionMetrics.getInstance().reportAnimationStart(transition);
// run finish now in-case there are no animations
onAnimFinish.run();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/CounterRotator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/CounterRotator.java
index b9b671635010..7f8eaf1a9b55 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/CounterRotator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/CounterRotator.java
@@ -18,14 +18,11 @@ package com.android.wm.shell.util;
import android.view.SurfaceControl;
-import java.util.ArrayList;
-
/**
* Utility class that takes care of counter-rotating surfaces during a transition animation.
*/
public class CounterRotator {
- SurfaceControl mSurface = null;
- ArrayList<SurfaceControl> mRotateChildren = null;
+ private SurfaceControl mSurface = null;
/** Gets the surface with the counter-rotation. */
public SurfaceControl getSurface() {
@@ -41,7 +38,6 @@ public class CounterRotator {
public void setup(SurfaceControl.Transaction t, SurfaceControl parent, int rotateDelta,
float displayW, float displayH) {
if (rotateDelta == 0) return;
- mRotateChildren = new ArrayList<>();
// We want to counter-rotate, so subtract from 4
rotateDelta = 4 - (rotateDelta + 4) % 4;
mSurface = new SurfaceControl.Builder()
@@ -64,24 +60,19 @@ public class CounterRotator {
}
/**
- * Add a surface that needs to be counter-rotate.
+ * Adds a surface that needs to be counter-rotate.
*/
public void addChild(SurfaceControl.Transaction t, SurfaceControl child) {
if (mSurface == null) return;
t.reparent(child, mSurface);
- mRotateChildren.add(child);
}
/**
- * Clean-up. This undoes any reparenting and effectively stops the counter-rotation.
+ * Clean-up. Since finishTransaction should reset all change leashes, we only need to remove the
+ * counter rotation surface.
*/
- public void cleanUp(SurfaceControl rootLeash) {
+ public void cleanUp(SurfaceControl.Transaction finishTransaction) {
if (mSurface == null) return;
- SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- for (int i = mRotateChildren.size() - 1; i >= 0; --i) {
- t.reparent(mRotateChildren.get(i), rootLeash);
- }
- t.remove(mSurface);
- t.apply();
+ finishTransaction.remove(mSurface);
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
index 6c9fed9dc19b..9a220070db01 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
@@ -22,6 +22,7 @@ import androidx.test.filters.FlakyTest
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.LAUNCHER_COMPONENT
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import org.junit.Test
@@ -51,11 +52,28 @@ abstract class ExitPipTransition(testSpec: FlickerTestParameter) : PipTransition
@Presubmit
@Test
open fun pipWindowBecomesInvisible() {
- testSpec.assertWm {
- this.invoke("hasPipWindow") {
- it.isPinned(pipApp.component).isAppWindowVisible(pipApp.component)
- }.then().invoke("!hasPipWindow") {
- it.isNotPinned(pipApp.component).isAppWindowInvisible(pipApp.component)
+ if (isShellTransitionsEnabled) {
+ // When Shell transition is enabled, we change the windowing mode at start, but
+ // update the visibility after the transition is finished, so we can't check isNotPinned
+ // and isAppWindowInvisible in the same assertion block.
+ testSpec.assertWm {
+ this.invoke("hasPipWindow") {
+ it.isPinned(pipApp.component)
+ .isAppWindowVisible(pipApp.component)
+ .isAppWindowOnTop(pipApp.component)
+ }.then().invoke("!hasPipWindow") {
+ it.isNotPinned(pipApp.component)
+ .isAppWindowNotOnTop(pipApp.component)
+ }
+ }
+ testSpec.assertWmEnd { isAppWindowInvisible(pipApp.component) }
+ } else {
+ testSpec.assertWm {
+ this.invoke("hasPipWindow") {
+ it.isPinned(pipApp.component).isAppWindowVisible(pipApp.component)
+ }.then().invoke("!hasPipWindow") {
+ it.isNotPinned(pipApp.component).isAppWindowInvisible(pipApp.component)
+ }
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
index c75076d00574..8adebb8f28c9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
@@ -24,10 +24,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec
-import org.junit.Assume.assumeFalse
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Rule
import org.junit.Test
@@ -88,20 +85,10 @@ class ExitPipWithDismissButtonTest(testSpec: FlickerTestParameter) : ExitPipTran
flickerRule.checkFlakyAssertions()
}
- @Before
- fun onBefore() {
- // This CUJ don't work in shell transitions because of b/204570898 b/204562589
- assumeFalse(isShellTransitionsEnabled)
- }
-
/** {@inheritDoc} */
@FlakyTest(bugId = 206753786)
@Test
- override fun statusBarLayerRotatesScales() {
- // This test doesn't work in shell transitions because of b/206753786
- assumeFalse(isShellTransitionsEnabled)
- super.statusBarLayerRotatesScales()
- }
+ override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
companion object {
/**
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index 52177c2c7684..ef9ff4fc63c2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -26,9 +26,6 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.LAUNCHER_COMPONENT
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume.assumeFalse
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -65,12 +62,6 @@ class ExpandPipOnDoubleClickTest(testSpec: FlickerTestParameter) : PipTransition
}
}
- @Before
- fun onBefore() {
- // This CUJ don't work in shell transitions because of b/204570898 b/204562589
- assumeFalse(isShellTransitionsEnabled)
- }
-
/**
* Checks that the pip app window remains inside the display bounds throughout the whole
* animation
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/BackgroundWindowManagerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/BackgroundWindowManagerTest.java
new file mode 100644
index 000000000000..f3f70673b332
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/BackgroundWindowManagerTest.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.onehanded;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.testing.TestableLooper;
+
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayLayout;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Tests for {@link BackgroundWindowManager} */
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidJUnit4.class)
+public class BackgroundWindowManagerTest extends ShellTestCase {
+ private BackgroundWindowManager mBackgroundWindowManager;
+ @Mock
+ private DisplayLayout mMockDisplayLayout;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mBackgroundWindowManager = new BackgroundWindowManager(mContext);
+ mBackgroundWindowManager.onDisplayChanged(mMockDisplayLayout);
+ }
+
+ @Test
+ @UiThreadTest
+ public void testInitRelease() {
+ mBackgroundWindowManager.initView();
+ assertThat(mBackgroundWindowManager.getSurfaceControl()).isNotNull();
+
+ mBackgroundWindowManager.removeBackgroundLayer();
+ assertThat(mBackgroundWindowManager.getSurfaceControl()).isNull();
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java
deleted file mode 100644
index 7b9553c5ef9b..000000000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizerTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.onehanded;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL;
-
-import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
-import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.Display;
-import android.view.SurfaceControl;
-import android.window.DisplayAreaInfo;
-import android.window.IWindowContainerToken;
-import android.window.WindowContainerToken;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayLayout;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class OneHandedBackgroundPanelOrganizerTest extends OneHandedTestCase {
- private DisplayAreaInfo mDisplayAreaInfo;
- private Display mDisplay;
- private DisplayLayout mDisplayLayout;
- private OneHandedBackgroundPanelOrganizer mSpiedBackgroundPanelOrganizer;
- private WindowContainerToken mToken;
- private SurfaceControl mLeash;
-
- @Mock
- IWindowContainerToken mMockRealToken;
- @Mock
- DisplayController mMockDisplayController;
- @Mock
- OneHandedSettingsUtil mMockSettingsUtil;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mToken = new WindowContainerToken(mMockRealToken);
- mLeash = new SurfaceControl();
- mDisplay = mContext.getDisplay();
- mDisplayLayout = new DisplayLayout(mContext, mDisplay);
- when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
- mDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY,
- FEATURE_ONE_HANDED_BACKGROUND_PANEL);
-
- mSpiedBackgroundPanelOrganizer = spy(
- new OneHandedBackgroundPanelOrganizer(mContext, mDisplayLayout, mMockSettingsUtil,
- Runnable::run));
- mSpiedBackgroundPanelOrganizer.onDisplayChanged(mDisplayLayout);
- }
-
- @Test
- public void testOnDisplayAreaAppeared() {
- mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
-
- assertThat(mSpiedBackgroundPanelOrganizer.isRegistered()).isTrue();
- verify(mSpiedBackgroundPanelOrganizer, never()).showBackgroundPanelLayer();
- }
-
- @Test
- public void testShowBackgroundLayer() {
- mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, null);
- mSpiedBackgroundPanelOrganizer.onStart();
-
- verify(mSpiedBackgroundPanelOrganizer).showBackgroundPanelLayer();
- }
-
- @Test
- public void testRemoveBackgroundLayer() {
- mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
-
- assertThat(mSpiedBackgroundPanelOrganizer.isRegistered()).isNotNull();
-
- reset(mSpiedBackgroundPanelOrganizer);
- mSpiedBackgroundPanelOrganizer.removeBackgroundPanelLayer();
-
- assertThat(mSpiedBackgroundPanelOrganizer.mBackgroundSurface).isNull();
- }
-
- @Test
- public void testStateNone_onConfigurationChanged() {
- mSpiedBackgroundPanelOrganizer.onStateChanged(STATE_NONE);
- mSpiedBackgroundPanelOrganizer.onConfigurationChanged();
-
- verify(mSpiedBackgroundPanelOrganizer, never()).showBackgroundPanelLayer();
- }
-
- @Test
- public void testStateActivate_onConfigurationChanged() {
- mSpiedBackgroundPanelOrganizer.onStateChanged(STATE_ACTIVE);
- mSpiedBackgroundPanelOrganizer.onConfigurationChanged();
-
- verify(mSpiedBackgroundPanelOrganizer).showBackgroundPanelLayer();
- }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
index 636e875bed7e..2886b97a3020 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
@@ -73,8 +73,6 @@ public class OneHandedControllerTest extends OneHandedTestCase {
@Mock
DisplayController mMockDisplayController;
@Mock
- OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer;
- @Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
@Mock
OneHandedEventCallback mMockEventCallback;
@@ -115,7 +113,6 @@ public class OneHandedControllerTest extends OneHandedTestCase {
when(mMockDisplayController.getDisplayLayout(anyInt())).thenReturn(null);
when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>());
when(mMockDisplayAreaOrganizer.isReady()).thenReturn(true);
- when(mMockBackgroundOrganizer.isRegistered()).thenReturn(true);
when(mMockSettingsUitl.getSettingsOneHandedModeEnabled(any(), anyInt())).thenReturn(
mDefaultEnabled);
when(mMockSettingsUitl.getSettingsOneHandedModeTimeout(any(), anyInt())).thenReturn(
@@ -134,7 +131,6 @@ public class OneHandedControllerTest extends OneHandedTestCase {
mSpiedOneHandedController = spy(new OneHandedController(
mContext,
mMockDisplayController,
- mMockBackgroundOrganizer,
mMockDisplayAreaOrganizer,
mMockTouchHandler,
mMockTutorialHandler,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
index df21163c68cd..9c7f7237871a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
@@ -95,8 +95,6 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
@Mock
WindowContainerTransaction mMockWindowContainerTransaction;
@Mock
- OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer;
- @Mock
ShellExecutor mMockShellMainExecutor;
@Mock
OneHandedSettingsUtil mMockSettingsUitl;
@@ -143,7 +141,6 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
mMockSettingsUitl,
mMockAnimationController,
mTutorialHandler,
- mMockBackgroundOrganizer,
mJankMonitor,
mMockShellMainExecutor));
@@ -431,7 +428,6 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
mMockSettingsUitl,
mMockAnimationController,
mTutorialHandler,
- mMockBackgroundOrganizer,
mJankMonitor,
mMockShellMainExecutor));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java
index 58399b6444fa..dba1b8b86261 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedStateTest.java
@@ -67,8 +67,6 @@ public class OneHandedStateTest extends OneHandedTestCase {
@Mock
DisplayController mMockDisplayController;
@Mock
- OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer;
- @Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
@Mock
OneHandedTouchHandler mMockTouchHandler;
@@ -105,7 +103,6 @@ public class OneHandedStateTest extends OneHandedTestCase {
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>());
- when(mMockBackgroundOrganizer.isRegistered()).thenReturn(true);
when(mMockSettingsUitl.getSettingsOneHandedModeEnabled(any(), anyInt())).thenReturn(
mDefaultEnabled);
when(mMockSettingsUitl.getSettingsOneHandedModeTimeout(any(), anyInt())).thenReturn(
@@ -123,7 +120,6 @@ public class OneHandedStateTest extends OneHandedTestCase {
mSpiedOneHandedController = spy(new OneHandedController(
mContext,
mMockDisplayController,
- mMockBackgroundOrganizer,
mMockDisplayAreaOrganizer,
mMockTouchHandler,
mMockTutorialHandler,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
index b1434ca325b7..63d8bfd1e7ef 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
@@ -56,6 +56,8 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
OneHandedSettingsUtil mMockSettingsUtil;
@Mock
WindowManager mMockWindowManager;
+ @Mock
+ BackgroundWindowManager mMockBackgroundWindowManager;
@Before
public void setUp() {
@@ -63,10 +65,11 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
when(mMockSettingsUtil.getTutorialShownCounts(any(), anyInt())).thenReturn(0);
mDisplay = mContext.getDisplay();
- mDisplayLayout = new DisplayLayout(mContext, mDisplay);
+ mDisplayLayout = new DisplayLayout(getTestContext().getApplicationContext(), mDisplay);
mSpiedTransitionState = spy(new OneHandedState());
mSpiedTutorialHandler = spy(
- new OneHandedTutorialHandler(mContext, mMockSettingsUtil, mMockWindowManager));
+ new OneHandedTutorialHandler(mContext, mMockSettingsUtil, mMockWindowManager,
+ mMockBackgroundWindowManager));
mTimeoutHandler = new OneHandedTimeoutHandler(mMockShellMainExecutor);
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index a2d0103450f5..dc31bdd6f8ff 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -35,7 +35,6 @@ cc_defaults {
"skia_deps",
//"hwui_bugreport_font_cache_usage",
//"hwui_compile_for_perf",
- "hwui_pgo",
"hwui_lto",
],
@@ -159,22 +158,6 @@ cc_defaults {
],
}
-// Build libhwui with PGO by default.
-// Location of PGO profile data is defined in build/soong/cc/pgo.go
-// and is separate from hwui.
-// To turn it off, set ANDROID_PGO_NO_PROFILE_USE environment variable
-// or set enable_profile_use property to false.
-cc_defaults {
- name: "hwui_pgo",
-
- pgo: {
- instrumentation: true,
- profile_file: "hwui/hwui.profdata",
- benchmarks: ["hwui"],
- enable_profile_use: true,
- },
-}
-
// Build hwui library with ThinLTO by default.
cc_defaults {
name: "hwui_lto",
@@ -631,6 +614,7 @@ cc_library {
version_script: "libhwui.map.txt",
},
},
+ afdo: true,
}
cc_library_static {
@@ -764,15 +748,3 @@ cc_benchmark {
"tests/microbench/RenderNodeBench.cpp",
],
}
-
-// ----------------------------------------
-// Phony target to build benchmarks for PGO
-// ----------------------------------------
-
-phony {
- name: "pgo-targets-hwui",
- required: [
- "hwuimicro",
- "hwuimacro",
- ],
-}
diff --git a/libs/hwui/jni/NinePatch.cpp b/libs/hwui/jni/NinePatch.cpp
index b7ddd211b0de..08fc80fbdafd 100644
--- a/libs/hwui/jni/NinePatch.cpp
+++ b/libs/hwui/jni/NinePatch.cpp
@@ -67,7 +67,7 @@ public:
size_t chunkSize = obj != NULL ? env->GetArrayLength(obj) : 0;
if (chunkSize < (int) (sizeof(Res_png_9patch))) {
jniThrowRuntimeException(env, "Array too small for chunk.");
- return NULL;
+ return 0;
}
int8_t* storage = new int8_t[chunkSize];
diff --git a/libs/hwui/jni/android_util_PathParser.cpp b/libs/hwui/jni/android_util_PathParser.cpp
index 72995efb1c21..8cbb70ed2c86 100644
--- a/libs/hwui/jni/android_util_PathParser.cpp
+++ b/libs/hwui/jni/android_util_PathParser.cpp
@@ -61,7 +61,7 @@ static jlong createPathDataFromStringPath(JNIEnv* env, jobject, jstring inputStr
} else {
delete pathData;
doThrowIAE(env, result.failureMessage.c_str());
- return NULL;
+ return 0;
}
}
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 2c94820d50c1..ecdd4b616e0f 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -1860,7 +1860,7 @@ public final class GnssMeasurement implements Parcelable {
gnssMeasurement.mSatelliteInterSignalBiasUncertaintyNanos = parcel.readDouble();
if (gnssMeasurement.hasSatellitePvt()) {
ClassLoader classLoader = getClass().getClassLoader();
- gnssMeasurement.mSatellitePvt = parcel.readParcelable(classLoader, android.location.SatellitePvt.class);
+ gnssMeasurement.mSatellitePvt = parcel.readParcelable(classLoader);
}
if (gnssMeasurement.hasCorrelationVectors()) {
CorrelationVector[] correlationVectorsArray =
diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java
index b744017027b7..a07a64acb6e6 100644
--- a/location/java/android/location/GnssMeasurementsEvent.java
+++ b/location/java/android/location/GnssMeasurementsEvent.java
@@ -156,7 +156,7 @@ public final class GnssMeasurementsEvent implements Parcelable {
public GnssMeasurementsEvent createFromParcel(Parcel in) {
ClassLoader classLoader = getClass().getClassLoader();
- GnssClock clock = in.readParcelable(classLoader, android.location.GnssClock.class);
+ GnssClock clock = in.readParcelable(classLoader);
int measurementsLength = in.readInt();
GnssMeasurement[] measurementsArray = new GnssMeasurement[measurementsLength];
diff --git a/location/java/android/location/GpsMeasurementsEvent.java b/location/java/android/location/GpsMeasurementsEvent.java
index 6b834f324839..f3feb7a4c7b6 100644
--- a/location/java/android/location/GpsMeasurementsEvent.java
+++ b/location/java/android/location/GpsMeasurementsEvent.java
@@ -112,7 +112,7 @@ public class GpsMeasurementsEvent implements Parcelable {
public GpsMeasurementsEvent createFromParcel(Parcel in) {
ClassLoader classLoader = getClass().getClassLoader();
- GpsClock clock = in.readParcelable(classLoader, android.location.GpsClock.class);
+ GpsClock clock = in.readParcelable(classLoader);
int measurementsLength = in.readInt();
GpsMeasurement[] measurementsArray = new GpsMeasurement[measurementsLength];
diff --git a/location/java/android/location/GpsNavigationMessageEvent.java b/location/java/android/location/GpsNavigationMessageEvent.java
index b37fe3dfb792..2d5d6ebd5990 100644
--- a/location/java/android/location/GpsNavigationMessageEvent.java
+++ b/location/java/android/location/GpsNavigationMessageEvent.java
@@ -92,7 +92,7 @@ public class GpsNavigationMessageEvent implements Parcelable {
@Override
public GpsNavigationMessageEvent createFromParcel(Parcel in) {
ClassLoader classLoader = getClass().getClassLoader();
- GpsNavigationMessage navigationMessage = in.readParcelable(classLoader, android.location.GpsNavigationMessage.class);
+ GpsNavigationMessage navigationMessage = in.readParcelable(classLoader);
return new GpsNavigationMessageEvent(navigationMessage);
}
diff --git a/location/java/android/location/SatellitePvt.java b/location/java/android/location/SatellitePvt.java
index aa43cfd8711c..794a8d0731f9 100644
--- a/location/java/android/location/SatellitePvt.java
+++ b/location/java/android/location/SatellitePvt.java
@@ -465,9 +465,9 @@ public final class SatellitePvt implements Parcelable {
public SatellitePvt createFromParcel(Parcel in) {
int flags = in.readInt();
ClassLoader classLoader = getClass().getClassLoader();
- PositionEcef positionEcef = in.readParcelable(classLoader, android.location.SatellitePvt.PositionEcef.class);
- VelocityEcef velocityEcef = in.readParcelable(classLoader, android.location.SatellitePvt.VelocityEcef.class);
- ClockInfo clockInfo = in.readParcelable(classLoader, android.location.SatellitePvt.ClockInfo.class);
+ PositionEcef positionEcef = in.readParcelable(classLoader);
+ VelocityEcef velocityEcef = in.readParcelable(classLoader);
+ ClockInfo clockInfo = in.readParcelable(classLoader);
double ionoDelayMeters = in.readDouble();
double tropoDelayMeters = in.readDouble();
diff --git a/location/java/android/location/provider/LocationProviderBase.java b/location/java/android/location/provider/LocationProviderBase.java
index 88a24794411c..529edddf4cf0 100644
--- a/location/java/android/location/provider/LocationProviderBase.java
+++ b/location/java/android/location/provider/LocationProviderBase.java
@@ -26,7 +26,9 @@ import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
@@ -308,9 +310,7 @@ public abstract class LocationProviderBase {
synchronized (mBinder) {
try {
manager.onInitialize(mAllowed, mProperties, mAttributionTag);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
Log.w(mTag, e);
}
@@ -320,12 +320,28 @@ public abstract class LocationProviderBase {
@Override
public void setRequest(ProviderRequest request) {
- onSetRequest(request);
+ try {
+ onSetRequest(request);
+ } catch (RuntimeException e) {
+ // exceptions on one-way binder threads are dropped - move to a different thread
+ Log.w(mTag, e);
+ new Handler(Looper.getMainLooper()).post(() -> {
+ throw new AssertionError(e);
+ });
+ }
}
@Override
public void flush() {
- onFlush(this::onFlushComplete);
+ try {
+ onFlush(this::onFlushComplete);
+ } catch (RuntimeException e) {
+ // exceptions on one-way binder threads are dropped - move to a different thread
+ Log.w(mTag, e);
+ new Handler(Looper.getMainLooper()).post(() -> {
+ throw new AssertionError(e);
+ });
+ }
}
private void onFlushComplete() {
@@ -333,9 +349,7 @@ public abstract class LocationProviderBase {
if (manager != null) {
try {
manager.onFlushComplete();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (RuntimeException e) {
+ } catch (RemoteException | RuntimeException e) {
Log.w(mTag, e);
}
}
@@ -343,7 +357,15 @@ public abstract class LocationProviderBase {
@Override
public void sendExtraCommand(String command, Bundle extras) {
- onSendExtraCommand(command, extras);
+ try {
+ onSendExtraCommand(command, extras);
+ } catch (RuntimeException e) {
+ // exceptions on one-way binder threads are dropped - move to a different thread
+ Log.w(mTag, e);
+ new Handler(Looper.getMainLooper()).post(() -> {
+ throw new AssertionError(e);
+ });
+ }
}
}
}
diff --git a/media/OWNERS b/media/OWNERS
index 0aff43e00671..5f501372666b 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -3,7 +3,6 @@ elaurent@google.com
essick@google.com
etalvala@google.com
hdmoon@google.com
-hkuang@google.com
hunga@google.com
insun@google.com
jaewan@google.com
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index d2c49e0a0a32..af5a3da5f3e2 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1357,7 +1357,7 @@ public class AudioSystem
return DEVICE_OUT_BLE_SPEAKER_NAME;
case DEVICE_OUT_DEFAULT:
default:
- return Integer.toString(device);
+ return "0x" + Integer.toHexString(device);
}
}
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index bd0f32e6ffee..69ce8d2a3d93 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -18,10 +18,13 @@ package android.media;
import android.annotation.IntRange;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.graphics.GraphicBuffer;
import android.graphics.ImageFormat;
import android.graphics.ImageFormat.Format;
import android.graphics.Rect;
+import android.hardware.DataSpace;
+import android.hardware.DataSpace.NamedDataSpace;
import android.hardware.HardwareBuffer;
import android.hardware.HardwareBuffer.Usage;
import android.hardware.camera2.MultiResolutionImageReader;
@@ -136,8 +139,7 @@ public class ImageReader implements AutoCloseable {
// If the format is private don't default to USAGE_CPU_READ_OFTEN since it may not
// work, and is inscrutable anyway
return new ImageReader(width, height, format, maxImages,
- format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN,
- /*parent*/ null);
+ format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN, null);
}
/**
@@ -268,44 +270,32 @@ public class ImageReader implements AutoCloseable {
// If the format is private don't default to USAGE_CPU_READ_OFTEN since it may not
// work, and is inscrutable anyway
return new ImageReader(width, height, format, maxImages,
- format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN,
- parent);
+ format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN, parent);
}
-
- /**
- * @hide
- */
- protected ImageReader(int width, int height, int format, int maxImages, long usage,
- MultiResolutionImageReader parent) {
- mWidth = width;
- mHeight = height;
- mFormat = format;
- mUsage = usage;
- mMaxImages = maxImages;
- mParent = parent;
-
+ private void initializeImageReader(int width, int height, int imageFormat, int maxImages,
+ long usage, int hardwareBufferFormat, long dataSpace, boolean useLegacyImageFormat) {
if (width < 1 || height < 1) {
throw new IllegalArgumentException(
"The image dimensions must be positive");
}
- if (mMaxImages < 1) {
+
+ if (maxImages < 1) {
throw new IllegalArgumentException(
"Maximum outstanding image count must be at least 1");
}
- if (format == ImageFormat.NV21) {
+ if (imageFormat == ImageFormat.NV21) {
throw new IllegalArgumentException(
- "NV21 format is not supported");
+ "NV21 format is not supported");
}
- mNumPlanes = ImageUtils.getNumPlanesForFormat(mFormat);
+ nativeInit(new WeakReference<>(this), width, height, maxImages, usage,
+ hardwareBufferFormat, dataSpace);
- nativeInit(new WeakReference<>(this), width, height, format, maxImages, usage);
+ mIsReaderValid = true;
mSurface = nativeGetSurface();
-
- mIsReaderValid = true;
// Estimate the native buffer allocation size and register it so it gets accounted for
// during GC. Note that this doesn't include the buffers required by the buffer queue
// itself and the buffers requested by the producer.
@@ -313,10 +303,46 @@ public class ImageReader implements AutoCloseable {
// complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some
// size.
mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(
- width, height, format, /*buffer count*/ 1);
+ width, height, useLegacyImageFormat ? imageFormat : hardwareBufferFormat,
+ /*buffer count*/ 1);
VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes);
}
+ private ImageReader(int width, int height, int imageFormat, int maxImages, long usage,
+ MultiResolutionImageReader parent) {
+ mWidth = width;
+ mHeight = height;
+ mFormat = imageFormat;
+ mUsage = usage;
+ mMaxImages = maxImages;
+ mParent = parent;
+ // retrieve hal Format and hal dataspace from imageFormat
+ mHardwareBufferFormat = PublicFormatUtils.getHalFormat(mFormat);
+ mDataSpace = PublicFormatUtils.getHalDataspace(mFormat);
+ mUseLegacyImageFormat = true;
+ mNumPlanes = ImageUtils.getNumPlanesForFormat(mFormat);
+
+ initializeImageReader(width, height, imageFormat, maxImages, usage, mHardwareBufferFormat,
+ mDataSpace, mUseLegacyImageFormat);
+ }
+
+ private ImageReader(int width, int height, int maxImages, long usage,
+ MultiResolutionImageReader parent, int hardwareBufferFormat, long dataSpace) {
+ mWidth = width;
+ mHeight = height;
+ mFormat = ImageFormat.UNKNOWN; // set default image format value as UNKNOWN
+ mUsage = usage;
+ mMaxImages = maxImages;
+ mParent = parent;
+ mHardwareBufferFormat = hardwareBufferFormat;
+ mDataSpace = dataSpace;
+ mUseLegacyImageFormat = false;
+ mNumPlanes = ImageUtils.getNumPlanesForHardwareBufferFormat(mHardwareBufferFormat);
+
+ initializeImageReader(width, height, mFormat, maxImages, usage, hardwareBufferFormat,
+ dataSpace, mUseLegacyImageFormat);
+ }
+
/**
* The default width of {@link Image Images}, in pixels.
*
@@ -354,6 +380,10 @@ public class ImageReader implements AutoCloseable {
* As of now, each format is only compatible to itself.
* The actual format of the images can be found using {@link Image#getFormat}.</p>
*
+ * <p>Use this function if the ImageReader instance is created by factory method
+ * {@code newInstance} function or by builder pattern {@code ImageReader.Builder} and using
+ * {@link Builder#setImageFormat}.</p>
+ *
* @return the expected format of an Image
*
* @see ImageFormat
@@ -363,6 +393,32 @@ public class ImageReader implements AutoCloseable {
}
/**
+ * The default {@link HardwareBuffer} format of {@link Image Images}.
+ *
+ * <p>Use this function if the ImageReader instance is created by builder pattern
+ * {@code ImageReader.Builder} and using {@link Builder#setDefaultHardwareBufferFormat} and
+ * {@link Builder#setDefaultDataSpace}.</p>
+ *
+ * @return the expected {@link HardwareBuffer} format of an Image.
+ */
+ public @HardwareBuffer.Format int getHardwareBufferFormat() {
+ return mHardwareBufferFormat;
+ }
+
+ /**
+ * The default dataspace of {@link Image Images}.
+ *
+ * <p>Use this function if the ImageReader instance is created by builder pattern
+ * {@code ImageReader.Builder} and {@link Builder#setDefaultDataSpace}.</p>
+ *
+ * @return the expected dataspace of an Image.
+ */
+ @SuppressLint("MethodNameUnits")
+ public @NamedDataSpace long getDataSpace() {
+ return mDataSpace;
+ }
+
+ /**
* Maximum number of images that can be acquired from the ImageReader by any time (for example,
* with {@link #acquireNextImage}).
*
@@ -384,6 +440,15 @@ public class ImageReader implements AutoCloseable {
}
/**
+ * The usage flag of images that can be produced by the ImageReader.
+ *
+ * @return The usage flag of the images for this ImageReader.
+ */
+ public @Usage long getUsage() {
+ return mUsage;
+ }
+
+ /**
* <p>Get a {@link Surface} that can be used to produce {@link Image Images} for this
* {@code ImageReader}.</p>
*
@@ -469,7 +534,12 @@ public class ImageReader implements AutoCloseable {
* @hide
*/
public Image acquireNextImageNoThrowISE() {
- SurfaceImage si = new SurfaceImage(mFormat);
+ SurfaceImage si;
+ if (mUseLegacyImageFormat) {
+ si = new SurfaceImage(mFormat);
+ } else {
+ si = new SurfaceImage(mHardwareBufferFormat, mDataSpace);
+ }
return acquireNextSurfaceImage(si) == ACQUIRE_SUCCESS ? si : null;
}
@@ -492,7 +562,7 @@ public class ImageReader implements AutoCloseable {
// A null image will eventually be returned if ImageReader is already closed.
int status = ACQUIRE_NO_BUFS;
if (mIsReaderValid) {
- status = nativeImageSetup(si);
+ status = nativeImageSetup(si, mUseLegacyImageFormat);
}
switch (status) {
@@ -545,7 +615,12 @@ public class ImageReader implements AutoCloseable {
public Image acquireNextImage() {
// Initialize with reader format, but can be overwritten by native if the image
// format is different from the reader format.
- SurfaceImage si = new SurfaceImage(mFormat);
+ SurfaceImage si;
+ if (mUseLegacyImageFormat) {
+ si = new SurfaceImage(mFormat);
+ } else {
+ si = new SurfaceImage(mHardwareBufferFormat, mDataSpace);
+ }
int status = acquireNextSurfaceImage(si);
switch (status) {
@@ -838,13 +913,161 @@ public class ImageReader implements AutoCloseable {
}
}
+ /**
+ * Builder class for {@link ImageReader} objects.
+ */
+ public static final class Builder {
+ private int mWidth;
+ private int mHeight;
+ private int mMaxImages = 1;
+ private int mImageFormat = ImageFormat.UNKNOWN;
+ private int mHardwareBufferFormat = HardwareBuffer.RGBA_8888;
+ private long mDataSpace = DataSpace.DATASPACE_UNKNOWN;
+ private long mUsage = HardwareBuffer.USAGE_CPU_READ_OFTEN;
+ private boolean mUseLegacyImageFormat = false;
+
+ /**
+ * Constructs a new builder for {@link ImageReader}.
+ *
+ * @param width The default width in pixels that will be passed to the producer.
+ * May be overridden by the producer.
+ * @param height The default height in pixels that will be passed to the producer.
+ * May be overridden by the producer.
+ * @see Image
+ */
+ public Builder(@IntRange(from = 1) int width, @IntRange(from = 1) int height) {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ /**
+ * Set the maximal number of images.
+ *
+ * @param maxImages The maximum number of images the user will want to
+ * access simultaneously. This should be as small as possible to
+ * limit memory use. Default value is 1.
+ * @return the Builder instance with customized usage value.
+ */
+ public @NonNull Builder setMaxImages(int maxImages) {
+ mMaxImages = maxImages;
+ return this;
+ }
+
+ /**
+ * Set the consumer usage flag.
+ *
+ * @param usage The intended usage of the images consumed by this ImageReader.
+ * See the usages on {@link HardwareBuffer} for a list of valid usage bits.
+ * Default value is {@link HardwareBuffer#USAGE_CPU_READ_OFTEN}.
+ * @return the Builder instance with customized usage value.
+ *
+ * @see HardwareBuffer
+ */
+ public @NonNull Builder setUsage(long usage) {
+ mUsage = usage;
+ return this;
+ }
+
+ /**
+ * Set the default image format passed by the producer. May be overridden by the producer.
+ *
+ * <p>{@link #setImageFormat} function replaces the combination of
+ * {@link #setDefaultHardwareBufferFormat} and {@link #setDefaultDataSpace} functions.
+ * Either this or these two functions must be called to initialize an {@code ImageReader}
+ * instance.</p>
+ *
+ * @param imageFormat The format of the image that this reader will produce. This
+ * must be one of the {@link android.graphics.ImageFormat} or
+ * {@link android.graphics.PixelFormat} constants. Note that not
+ * all formats are supported, like ImageFormat.NV21. The default value is
+ * {@link ImageFormat#UNKNOWN}.
+ * @return the builder instance with customized image format value.
+ *
+ * @see #setDefaultHardwareBufferFormat
+ * @see #setDefaultDataSpace
+ */
+ public @NonNull Builder setImageFormat(@Format int imageFormat) {
+ mImageFormat = imageFormat;
+ mUseLegacyImageFormat = true;
+ mHardwareBufferFormat = HardwareBuffer.RGBA_8888;
+ mDataSpace = DataSpace.DATASPACE_UNKNOWN;
+ return this;
+ }
+
+ /**
+ * Set the default hardwareBuffer format passed by the producer.
+ * May be overridden by the producer.
+ *
+ * <p>This function works together with {@link #setDefaultDataSpace} for an
+ * {@link ImageReader} instance. Setting at least one of these two replaces
+ * {@link #setImageFormat} function.</p>
+ *
+ * <p>The format of the Image can be overridden after {@link #setImageFormat} by calling
+ * this function and then {@link #setDefaultDataSpace} functions.
+ * <i>Warning:</i> Missing one of callings for initializing or overriding the format may
+ * involve undefined behaviors.</p>
+ *
+ * @param hardwareBufferFormat The HardwareBuffer format of the image that this reader
+ * will produce. The default value is
+ * {@link HardwareBuffer#RGBA_8888 HardwareBuffer.RGBA_8888}.
+ * @return the builder instance with customized hardwareBuffer value.
+ *
+ * @see #setDefaultDataSpace
+ * @see #setImageFormat
+ */
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public @NonNull Builder setDefaultHardwareBufferFormat(
+ @HardwareBuffer.Format int hardwareBufferFormat) {
+ mHardwareBufferFormat = hardwareBufferFormat;
+ mUseLegacyImageFormat = false;
+ mImageFormat = ImageFormat.UNKNOWN;
+ return this;
+ }
+
+ /**
+ * Set the default dataspace passed by the producer.
+ * May be overridden by the producer.
+ *
+ * <p>This function works together with {@link #setDefaultHardwareBufferFormat} for an
+ * {@link ImageReader} instance. Setting at least one of these two replaces
+ * {@link #setImageFormat} function.</p>
+ *
+ * @param dataSpace The dataspace of the image that this reader will produce.
+ * The default value is {@link DataSpace#DATASPACE_UNKNOWN}.
+ * @return the builder instance with customized dataspace value.
+ *
+ * @see #setDefaultHardwareBufferFormat
+ */
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public @NonNull Builder setDefaultDataSpace(@NamedDataSpace long dataSpace) {
+ mDataSpace = dataSpace;
+ mUseLegacyImageFormat = false;
+ mImageFormat = ImageFormat.UNKNOWN;
+ return this;
+ }
+
+ /**
+ * Builds a new ImageReader object.
+ *
+ * @return The new ImageReader object.
+ */
+ public @NonNull ImageReader build() {
+ if (mUseLegacyImageFormat) {
+ return new ImageReader(mWidth, mHeight, mImageFormat, mMaxImages, mUsage, null);
+ } else {
+ return new ImageReader(mWidth, mHeight, mMaxImages, mUsage, null,
+ mHardwareBufferFormat, mDataSpace);
+ }
+ }
+ }
+
private final int mWidth;
private final int mHeight;
private final int mFormat;
private final long mUsage;
private final int mMaxImages;
private final int mNumPlanes;
- private final Surface mSurface;
+ private Surface mSurface;
private int mEstimatedNativeAllocBytes;
private final Object mListenerLock = new Object();
@@ -861,6 +1084,12 @@ public class ImageReader implements AutoCloseable {
// MultiResolutionImageReader.
private final MultiResolutionImageReader mParent;
+ private final int mHardwareBufferFormat;
+
+ private final long mDataSpace;
+
+ private final boolean mUseLegacyImageFormat;
+
/**
* This field is used by native code, do not access or modify.
*/
@@ -897,6 +1126,12 @@ public class ImageReader implements AutoCloseable {
mFormat = format;
}
+ SurfaceImage(int hardwareBufferFormat, long dataSpace) {
+ mHardwareBufferFormat = hardwareBufferFormat;
+ mDataSpace = dataSpace;
+ mFormat = PublicFormatUtils.getPublicFormat(mHardwareBufferFormat, mDataSpace);
+ }
+
@Override
public void close() {
ImageReader.this.releaseImage(this);
@@ -909,10 +1144,15 @@ public class ImageReader implements AutoCloseable {
@Override
public int getFormat() {
throwISEIfImageIsInvalid();
- int readerFormat = ImageReader.this.getImageFormat();
- // Assume opaque reader always produce opaque images.
- mFormat = (readerFormat == ImageFormat.PRIVATE) ? readerFormat :
- nativeGetFormat(readerFormat);
+ // update mFormat only if ImageReader is initialized by factory pattern.
+ // if using builder pattern, mFormat has been updated upon initialization.
+ // no need update here.
+ if (ImageReader.this.mUseLegacyImageFormat) {
+ int readerFormat = ImageReader.this.getImageFormat();
+ // Assume opaque reader always produce opaque images.
+ mFormat = (readerFormat == ImageFormat.PRIVATE) ? readerFormat :
+ nativeGetFormat(readerFormat);
+ }
return mFormat;
}
@@ -1125,6 +1365,8 @@ public class ImageReader implements AutoCloseable {
private SurfacePlane[] mPlanes;
private int mFormat = ImageFormat.UNKNOWN;
+ private int mHardwareBufferFormat = HardwareBuffer.RGBA_8888;
+ private long mDataSpace = DataSpace.DATASPACE_UNKNOWN;
// If this image is detached from the ImageReader.
private AtomicBoolean mIsDetached = new AtomicBoolean(false);
@@ -1137,8 +1379,8 @@ public class ImageReader implements AutoCloseable {
private synchronized native HardwareBuffer nativeGetHardwareBuffer();
}
- private synchronized native void nativeInit(Object weakSelf, int w, int h,
- int fmt, int maxImgs, long consumerUsage);
+ private synchronized native void nativeInit(Object weakSelf, int w, int h, int maxImgs,
+ long consumerUsage, int hardwareBufferFormat, long dataSpace);
private synchronized native void nativeClose();
private synchronized native void nativeReleaseImage(Image i);
private synchronized native Surface nativeGetSurface();
@@ -1152,7 +1394,7 @@ public class ImageReader implements AutoCloseable {
* @see #ACQUIRE_NO_BUFS
* @see #ACQUIRE_MAX_IMAGES
*/
- private synchronized native int nativeImageSetup(Image i);
+ private synchronized native int nativeImageSetup(Image i, boolean legacyValidateImageFormat);
/**
* @hide
diff --git a/media/java/android/media/ImageUtils.java b/media/java/android/media/ImageUtils.java
index 7837d7e39599..2f1a36cba9d0 100644
--- a/media/java/android/media/ImageUtils.java
+++ b/media/java/android/media/ImageUtils.java
@@ -18,6 +18,7 @@ package android.media;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
+import android.hardware.HardwareBuffer;
import android.media.Image.Plane;
import android.util.Size;
@@ -77,6 +78,34 @@ class ImageUtils {
}
/**
+ * Only a subset of the formats defined in
+ * {@link android.graphics.HardwareBuffer.Format} constants are supported by ImageReader.
+ */
+ public static int getNumPlanesForHardwareBufferFormat(int hardwareBufferFormat) {
+ switch(hardwareBufferFormat) {
+ case HardwareBuffer.YCBCR_420_888:
+ return 3;
+ case HardwareBuffer.RGBA_8888:
+ case HardwareBuffer.RGBX_8888:
+ case HardwareBuffer.RGB_888:
+ case HardwareBuffer.RGB_565:
+ case HardwareBuffer.RGBA_FP16:
+ case HardwareBuffer.RGBA_1010102:
+ case HardwareBuffer.BLOB:
+ case HardwareBuffer.D_16:
+ case HardwareBuffer.D_24:
+ case HardwareBuffer.DS_24UI8:
+ case HardwareBuffer.D_FP32:
+ case HardwareBuffer.DS_FP32UI8:
+ case HardwareBuffer.S_UI8:
+ return 1;
+ default:
+ throw new UnsupportedOperationException(
+ String.format("Invalid hardwareBuffer format specified %d",
+ hardwareBufferFormat));
+ }
+ }
+ /**
* <p>
* Copy source image data to destination Image.
* </p>
diff --git a/media/java/android/media/MediaDescription.java b/media/java/android/media/MediaDescription.java
index dece6bdbb35f..458562afb6ef 100644
--- a/media/java/android/media/MediaDescription.java
+++ b/media/java/android/media/MediaDescription.java
@@ -142,10 +142,10 @@ public class MediaDescription implements Parcelable {
mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- mIcon = in.readParcelable(null, android.graphics.Bitmap.class);
- mIconUri = in.readParcelable(null, android.net.Uri.class);
+ mIcon = in.readParcelable(null);
+ mIconUri = in.readParcelable(null);
mExtras = in.readBundle();
- mMediaUri = in.readParcelable(null, android.net.Uri.class);
+ mMediaUri = in.readParcelable(null);
}
/**
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 2427fa64562d..9c9e83b0987d 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -371,7 +371,7 @@ public final class MediaRoute2Info implements Parcelable {
mFeatures = in.createStringArrayList();
mType = in.readInt();
mIsSystem = in.readBoolean();
- mIconUri = in.readParcelable(null, android.net.Uri.class);
+ mIconUri = in.readParcelable(null);
mDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mConnectionState = in.readInt();
mClientPackageName = in.readString();
diff --git a/media/java/android/media/PublicFormatUtils.java b/media/java/android/media/PublicFormatUtils.java
new file mode 100644
index 000000000000..6268804128c6
--- /dev/null
+++ b/media/java/android/media/PublicFormatUtils.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media;
+
+/**
+ * Package private utility class for PublicFormat related methods.
+ */
+class PublicFormatUtils {
+ public static int getHalFormat(int imageFormat) {
+ return nativeGetHalFormat(imageFormat);
+ }
+ public static long getHalDataspace(int imageFormat) {
+ return nativeGetHalDataspace(imageFormat);
+ }
+ public static int getPublicFormat(int imageFormat, long dataspace) {
+ return nativeGetPublicFormat(imageFormat, dataspace);
+ }
+ private static native int nativeGetHalFormat(int imageFormat);
+ private static native long nativeGetHalDataspace(int imageFormat);
+ private static native int nativeGetPublicFormat(int imageFormat, long dataspace);
+}
diff --git a/media/java/android/media/midi/MidiDeviceStatus.java b/media/java/android/media/midi/MidiDeviceStatus.java
index aa0626742ac2..b11827966b1a 100644
--- a/media/java/android/media/midi/MidiDeviceStatus.java
+++ b/media/java/android/media/midi/MidiDeviceStatus.java
@@ -115,7 +115,7 @@ public final class MidiDeviceStatus implements Parcelable {
new Parcelable.Creator<MidiDeviceStatus>() {
public MidiDeviceStatus createFromParcel(Parcel in) {
ClassLoader classLoader = MidiDeviceInfo.class.getClassLoader();
- MidiDeviceInfo deviceInfo = in.readParcelable(classLoader, android.media.midi.MidiDeviceInfo.class);
+ MidiDeviceInfo deviceInfo = in.readParcelable(classLoader);
boolean[] inputPortOpen = in.createBooleanArray();
int[] outputPortOpenCount = in.createIntArray();
return new MidiDeviceStatus(deviceInfo, inputPortOpen, outputPortOpenCount);
diff --git a/media/java/android/media/musicrecognition/RecognitionRequest.java b/media/java/android/media/musicrecognition/RecognitionRequest.java
index b8757a351e24..3298d634d342 100644
--- a/media/java/android/media/musicrecognition/RecognitionRequest.java
+++ b/media/java/android/media/musicrecognition/RecognitionRequest.java
@@ -152,8 +152,8 @@ public final class RecognitionRequest implements Parcelable {
}
private RecognitionRequest(Parcel in) {
- mAudioFormat = in.readParcelable(AudioFormat.class.getClassLoader(), android.media.AudioFormat.class);
- mAudioAttributes = in.readParcelable(AudioAttributes.class.getClassLoader(), android.media.AudioAttributes.class);
+ mAudioFormat = in.readParcelable(AudioFormat.class.getClassLoader());
+ mAudioAttributes = in.readParcelable(AudioAttributes.class.getClassLoader());
mCaptureSession = in.readInt();
mMaxAudioLengthSeconds = in.readInt();
mIgnoreBeginningFrames = in.readInt();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 955ae3ca28fb..1da41fb87b40 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -1022,7 +1022,7 @@ public final class MediaController {
mVolumeControl = in.readInt();
mMaxVolume = in.readInt();
mCurrentVolume = in.readInt();
- mAudioAttrs = in.readParcelable(null, android.media.AudioAttributes.class);
+ mAudioAttrs = in.readParcelable(null);
mVolumeControlId = in.readString();
}
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index d34e6360d95f..770b8aa705af 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -66,6 +66,7 @@ interface ITvInputManager {
int seq, int userId);
void releaseSession(in IBinder sessionToken, int userId);
int getClientPid(in String sessionId);
+ int getClientPriority(int useCase, in String sessionId);
void setMainSession(in IBinder sessionToken, int userId);
void setSurface(in IBinder sessionToken, in Surface surface, int userId);
diff --git a/media/java/android/media/tv/TvContentRatingSystemInfo.java b/media/java/android/media/tv/TvContentRatingSystemInfo.java
index 947b2d67bfce..f44ded3dbd37 100644
--- a/media/java/android/media/tv/TvContentRatingSystemInfo.java
+++ b/media/java/android/media/tv/TvContentRatingSystemInfo.java
@@ -94,8 +94,8 @@ public final class TvContentRatingSystemInfo implements Parcelable {
};
private TvContentRatingSystemInfo(Parcel in) {
- mXmlUri = in.readParcelable(null, android.net.Uri.class);
- mApplicationInfo = in.readParcelable(null, android.content.pm.ApplicationInfo.class);
+ mXmlUri = in.readParcelable(null);
+ mApplicationInfo = in.readParcelable(null);
}
@Override
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index e60d5378f88c..54cb2bff5566 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -653,16 +653,16 @@ public final class TvInputInfo implements Parcelable {
mType = in.readInt();
mIsHardwareInput = in.readByte() == 1;
mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
- mIconUri = in.readParcelable(null, android.net.Uri.class);
+ mIconUri = in.readParcelable(null);
mLabelResId = in.readInt();
- mIcon = in.readParcelable(null, android.graphics.drawable.Icon.class);
- mIconStandby = in.readParcelable(null, android.graphics.drawable.Icon.class);
- mIconDisconnected = in.readParcelable(null, android.graphics.drawable.Icon.class);
+ mIcon = in.readParcelable(null);
+ mIconStandby = in.readParcelable(null);
+ mIconDisconnected = in.readParcelable(null);
mSetupActivity = in.readString();
mCanRecord = in.readByte() == 1;
mCanPauseRecording = in.readByte() == 1;
mTunerCount = in.readInt();
- mHdmiDeviceInfo = in.readParcelable(null, android.hardware.hdmi.HdmiDeviceInfo.class);
+ mHdmiDeviceInfo = in.readParcelable(null);
mIsConnectedToHdmiSwitch = in.readByte() == 1;
mHdmiConnectionRelativePosition = in.readInt();
mParentId = in.readString();
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index ad86002f862d..52036b0c511e 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -764,6 +764,9 @@ public final class TvInputManager {
@Override
public void run() {
mSessionCallback.onVideoAvailable(mSession);
+ if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
+ mSession.getIAppSession().notifyVideoAvailable();
+ }
}
});
}
@@ -773,6 +776,9 @@ public final class TvInputManager {
@Override
public void run() {
mSessionCallback.onVideoUnavailable(mSession, reason);
+ if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
+ mSession.getIAppSession().notifyVideoUnavailable(reason);
+ }
}
});
}
@@ -782,6 +788,9 @@ public final class TvInputManager {
@Override
public void run() {
mSessionCallback.onContentAllowed(mSession);
+ if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
+ mSession.getIAppSession().notifyContentAllowed();
+ }
}
});
}
@@ -791,6 +800,9 @@ public final class TvInputManager {
@Override
public void run() {
mSessionCallback.onContentBlocked(mSession, rating);
+ if (mSession.mIAppNotificationEnabled && mSession.getIAppSession() != null) {
+ mSession.getIAppSession().notifyContentBlocked(rating);
+ }
}
});
}
@@ -1786,6 +1798,29 @@ public final class TvInputManager {
};
/**
+ * Returns a priority for the given use case type and the client's foreground or background
+ * status.
+ *
+ * @param useCase the use case type of the client. When the given use case type is invalid,
+ * the default use case type will be used. {@see TvInputService#PriorityHintUseCaseType}.
+ * @param sessionId the unique id of the session owned by the client. When {@code null},
+ * the caller will be used as a client. When the session is invalid, background status
+ * will be used as a client's status. Otherwise, TV app corresponding to the given
+ * session id will be used as a client.
+ * {@see TvInputService#onCreateSession(String, String)}.
+ *
+ * @return the use case priority value for the given use case type and the client's foreground
+ * or background status.
+ *
+ * @hide
+ */
+ @SystemApi
+ public int getClientPriority(@TvInputService.PriorityHintUseCaseType int useCase,
+ @Nullable String sessionId) {
+ return getClientPriorityInternal(useCase, sessionId);
+ };
+
+ /**
* Creates a recording {@link Session} for a given TV input.
*
* <p>The number of sessions that can be created at the same time is limited by the capability
@@ -1829,6 +1864,14 @@ public final class TvInputManager {
return clientPid;
}
+ private int getClientPriorityInternal(int useCase, String sessionId) {
+ try {
+ return mService.getClientPriority(useCase, sessionId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/**
* Returns the TvStreamConfig list of the given TV input.
*
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index bd5a343963df..3a40d6ff1fb4 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -592,6 +592,24 @@ public abstract class TvInputService extends Service {
});
}
+ /** @hide */
+ public void notifyTuned(@NonNull Uri channelUri) {
+ executeOrPostRunnableOnMainThread(new Runnable() {
+ @MainThread
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) Log.d(TAG, "notifyTuned");
+ if (mSessionCallback != null) {
+ mSessionCallback.onTuned(channelUri);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "error in notifyTuned", e);
+ }
+ }
+ });
+ }
+
/**
* Sends the list of all audio/video/subtitle tracks. The is used by the framework to
* maintain the track information for a given session, which in turn is used by
diff --git a/media/java/android/media/tv/interactive/ITvIAppManager.aidl b/media/java/android/media/tv/interactive/ITvIAppManager.aidl
index 23201faa1c5a..2e0435927ae8 100644
--- a/media/java/android/media/tv/interactive/ITvIAppManager.aidl
+++ b/media/java/android/media/tv/interactive/ITvIAppManager.aidl
@@ -51,6 +51,10 @@ interface ITvIAppManager {
void notifyTuned(in IBinder sessionToken, in Uri channelUri, int userId);
void notifyTrackSelected(in IBinder sessionToken, int type, in String trackId, int userId);
void notifyTracksChanged(in IBinder sessionToken, in List<TvTrackInfo> tracks, int userId);
+ void notifyVideoAvailable(in IBinder sessionToken, int userId);
+ void notifyVideoUnavailable(in IBinder sessionToken, int reason, int userId);
+ void notifyContentAllowed(in IBinder sessionToken, int userId);
+ void notifyContentBlocked(in IBinder sessionToken, in String rating, int userId);
void setSurface(in IBinder sessionToken, in Surface surface, int userId);
void dispatchSurfaceChanged(in IBinder sessionToken, int format, int width, int height,
int userId);
diff --git a/media/java/android/media/tv/interactive/ITvIAppSession.aidl b/media/java/android/media/tv/interactive/ITvIAppSession.aidl
index 52f9a874aca2..2788ff65e301 100644
--- a/media/java/android/media/tv/interactive/ITvIAppSession.aidl
+++ b/media/java/android/media/tv/interactive/ITvIAppSession.aidl
@@ -42,6 +42,10 @@ oneway interface ITvIAppSession {
void notifyTuned(in Uri channelUri);
void notifyTrackSelected(int type, in String trackId);
void notifyTracksChanged(in List<TvTrackInfo> tracks);
+ void notifyVideoAvailable();
+ void notifyVideoUnavailable(int reason);
+ void notifyContentAllowed();
+ void notifyContentBlocked(in String rating);
void setSurface(in Surface surface);
void dispatchSurfaceChanged(int format, int width, int height);
void notifyBroadcastInfoResponse(in BroadcastInfoResponse response);
diff --git a/media/java/android/media/tv/interactive/TvIAppInfo.java b/media/java/android/media/tv/interactive/TvIAppInfo.java
index 79d94cce77fe..b5245fc0856e 100644
--- a/media/java/android/media/tv/interactive/TvIAppInfo.java
+++ b/media/java/android/media/tv/interactive/TvIAppInfo.java
@@ -127,6 +127,7 @@ public final class TvIAppInfo implements Parcelable {
/**
* Gets supported interactive app types
*/
+ @NonNull
public List<String> getSupportedTypes() {
return new ArrayList<>(mTypes);
}
diff --git a/media/java/android/media/tv/interactive/TvIAppManager.java b/media/java/android/media/tv/interactive/TvIAppManager.java
index d1fd1df74e1b..9685e3af8c53 100644
--- a/media/java/android/media/tv/interactive/TvIAppManager.java
+++ b/media/java/android/media/tv/interactive/TvIAppManager.java
@@ -26,6 +26,7 @@ import android.media.tv.AdRequest;
import android.media.tv.AdResponse;
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.BroadcastInfoResponse;
+import android.media.tv.TvContentRating;
import android.media.tv.TvInputManager;
import android.media.tv.TvTrackInfo;
import android.net.Uri;
@@ -1037,6 +1038,66 @@ public final class TvIAppManager {
}
}
+ /**
+ * Notifies IAPP session when video is available.
+ */
+ public void notifyVideoAvailable() {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.notifyVideoAvailable(mToken, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Notifies IAPP session when video is unavailable.
+ */
+ public void notifyVideoUnavailable(int reason) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.notifyVideoUnavailable(mToken, reason, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Notifies IAPP session when content is allowed.
+ */
+ public void notifyContentAllowed() {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.notifyContentAllowed(mToken, mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Notifies IAPP session when content is blocked.
+ */
+ public void notifyContentBlocked(TvContentRating rating) {
+ if (mToken == null) {
+ Log.w(TAG, "The session has been already released");
+ return;
+ }
+ try {
+ mService.notifyContentBlocked(mToken, rating.flattenToString(), mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private void flushPendingEventsLocked() {
mHandler.removeMessages(InputEventHandler.MSG_FLUSH_INPUT_EVENT);
diff --git a/media/java/android/media/tv/interactive/TvIAppService.java b/media/java/android/media/tv/interactive/TvIAppService.java
index 1480ff643d99..4993bc31768c 100644
--- a/media/java/android/media/tv/interactive/TvIAppService.java
+++ b/media/java/android/media/tv/interactive/TvIAppService.java
@@ -31,6 +31,7 @@ import android.media.tv.AdRequest;
import android.media.tv.AdResponse;
import android.media.tv.BroadcastInfoRequest;
import android.media.tv.BroadcastInfoResponse;
+import android.media.tv.TvContentRating;
import android.media.tv.TvTrackInfo;
import android.net.Uri;
import android.os.AsyncTask;
@@ -113,6 +114,19 @@ public abstract class TvIAppService extends Service {
public static final String IAPP_SERVICE_COMMAND_TYPE_SET_STREAM_VOLUME = "set_stream_volume";
/** @hide */
public static final String IAPP_SERVICE_COMMAND_TYPE_SELECT_TRACK = "select_track";
+ /** @hide */
+ public static final String COMMAND_PARAMETER_KEY_CHANNEL_URI = "command_channel_uri";
+ /** @hide */
+ public static final String COMMAND_PARAMETER_KEY_INPUT_ID = "command_input_id";
+ /** @hide */
+ public static final String COMMAND_PARAMETER_KEY_VOLUME = "command_volume";
+ /** @hide */
+ public static final String COMMAND_PARAMETER_KEY_TRACK_TYPE = "command_track_type";
+ /** @hide */
+ public static final String COMMAND_PARAMETER_KEY_TRACK_ID = "command_track_id";
+ /** @hide */
+ public static final String COMMAND_PARAMETER_KEY_TRACK_SELECT_MODE =
+ "command_track_select_mode";
private final Handler mServiceHandler = new ServiceHandler();
private final RemoteCallbackList<ITvIAppServiceCallback> mCallbacks =
@@ -429,6 +443,34 @@ public abstract class TvIAppService extends Service {
}
/**
+ * Called when video is available.
+ * @hide
+ */
+ public void onVideoAvailable() {
+ }
+
+ /**
+ * Called when video is unavailable.
+ * @hide
+ */
+ public void onVideoUnavailable(int reason) {
+ }
+
+ /**
+ * Called when content is allowed.
+ * @hide
+ */
+ public void onContentAllowed() {
+ }
+
+ /**
+ * Called when content is blocked.
+ * @hide
+ */
+ public void onContentBlocked(TvContentRating rating) {
+ }
+
+ /**
* Called when a broadcast info response is received.
* @hide
*/
@@ -803,6 +845,33 @@ public abstract class TvIAppService extends Service {
onTracksChanged(tracks);
}
+ void notifyVideoAvailable() {
+ if (DEBUG) {
+ Log.d(TAG, "notifyVideoAvailable");
+ }
+ onVideoAvailable();
+ }
+
+ void notifyVideoUnavailable(int reason) {
+ if (DEBUG) {
+ Log.d(TAG, "notifyVideoAvailable (reason=" + reason + ")");
+ }
+ onVideoUnavailable(reason);
+ }
+
+ void notifyContentAllowed() {
+ if (DEBUG) {
+ Log.d(TAG, "notifyContentAllowed");
+ }
+ notifyContentAllowed();
+ }
+
+ void notifyContentBlocked(TvContentRating rating) {
+ if (DEBUG) {
+ Log.d(TAG, "notifyContentBlocked (rating=" + rating.flattenToString() + ")");
+ }
+ onContentBlocked(rating);
+ }
/**
* Calls {@link #onBroadcastInfoResponse}.
@@ -1169,6 +1238,26 @@ public abstract class TvIAppService extends Service {
}
@Override
+ public void notifyVideoAvailable() {
+ mSessionImpl.notifyVideoAvailable();
+ }
+
+ @Override
+ public void notifyVideoUnavailable(int reason) {
+ mSessionImpl.notifyVideoUnavailable(reason);
+ }
+
+ @Override
+ public void notifyContentAllowed() {
+ mSessionImpl.notifyContentAllowed();
+ }
+
+ @Override
+ public void notifyContentBlocked(String rating) {
+ mSessionImpl.notifyContentBlocked(TvContentRating.unflattenFromString(rating));
+ }
+
+ @Override
public void setSurface(Surface surface) {
mSessionImpl.setSurface(surface);
}
diff --git a/media/java/android/media/tv/interactive/TvIAppView.java b/media/java/android/media/tv/interactive/TvIAppView.java
index 1ce14ae98351..b29505578184 100644
--- a/media/java/android/media/tv/interactive/TvIAppView.java
+++ b/media/java/android/media/tv/interactive/TvIAppView.java
@@ -27,6 +27,7 @@ import android.media.tv.TvInputManager;
import android.media.tv.TvTrackInfo;
import android.media.tv.TvView;
import android.media.tv.interactive.TvIAppManager.Session;
+import android.media.tv.interactive.TvIAppManager.Session.FinishedInputEventCallback;
import android.media.tv.interactive.TvIAppManager.SessionCallback;
import android.net.Uri;
import android.os.Bundle;
@@ -34,11 +35,14 @@ import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
+import android.view.InputEvent;
+import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewRootImpl;
import java.util.List;
@@ -80,6 +84,7 @@ public class TvIAppView extends ViewGroup {
private final AttributeSet mAttrs;
private final int mDefStyleAttr;
private final XmlResourceParser mParser;
+ private OnUnhandledInputEventListener mOnUnhandledInputEventListener;
private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
@Override
@@ -272,6 +277,77 @@ public class TvIAppView extends ViewGroup {
mSession.dispatchSurfaceChanged(format, width, height);
}
+ private final FinishedInputEventCallback mFinishedInputEventCallback =
+ new FinishedInputEventCallback() {
+ @Override
+ public void onFinishedInputEvent(Object token, boolean handled) {
+ if (DEBUG) {
+ Log.d(TAG, "onFinishedInputEvent(token=" + token + ", handled="
+ + handled + ")");
+ }
+ if (handled) {
+ return;
+ }
+ // TODO: Re-order unhandled events.
+ InputEvent event = (InputEvent) token;
+ if (dispatchUnhandledInputEvent(event)) {
+ return;
+ }
+ ViewRootImpl viewRootImpl = getViewRootImpl();
+ if (viewRootImpl != null) {
+ viewRootImpl.dispatchUnhandledInputEvent(event);
+ }
+ }
+ };
+
+ /**
+ * Dispatches an unhandled input event to the next receiver.
+ */
+ public boolean dispatchUnhandledInputEvent(@NonNull InputEvent event) {
+ if (mOnUnhandledInputEventListener != null) {
+ if (mOnUnhandledInputEventListener.onUnhandledInputEvent(event)) {
+ return true;
+ }
+ }
+ return onUnhandledInputEvent(event);
+ }
+
+ /**
+ * Called when an unhandled input event also has not been handled by the user provided
+ * callback. This is the last chance to handle the unhandled input event in the TvIAppView.
+ *
+ * @param event The input event.
+ * @return If you handled the event, return {@code true}. If you want to allow the event to be
+ * handled by the next receiver, return {@code false}.
+ */
+ public boolean onUnhandledInputEvent(@NonNull InputEvent event) {
+ return false;
+ }
+
+ /**
+ * Registers a callback to be invoked when an input event is not handled
+ * by the TV Interactive App.
+ *
+ * @param listener The callback to be invoked when the unhandled input event is received.
+ */
+ public void setOnUnhandledInputEventListener(@NonNull OnUnhandledInputEventListener listener) {
+ mOnUnhandledInputEventListener = listener;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(@NonNull KeyEvent event) {
+ if (super.dispatchKeyEvent(event)) {
+ return true;
+ }
+ if (mSession == null) {
+ return false;
+ }
+ InputEvent copiedEvent = event.copy();
+ int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback,
+ mHandler);
+ return ret != Session.DISPATCH_NOT_HANDLED;
+ }
+
/**
* Prepares the interactive application.
*/
@@ -514,6 +590,24 @@ public class TvIAppView extends ViewGroup {
*/
public void onRequestTrackInfoList(@NonNull String iAppServiceId) {
}
+
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when the unhandled input event is received.
+ */
+ public interface OnUnhandledInputEventListener {
+ /**
+ * Called when an input event was not handled by the TV Interactive App.
+ *
+ * <p>This is called asynchronously from where the event is dispatched. It gives the host
+ * application a chance to handle the unhandled input events.
+ *
+ * @param event The input event.
+ * @return If you handled the event, return {@code true}. If you want to allow the event to
+ * be handled by the next receiver, return {@code false}.
+ */
+ boolean onUnhandledInputEvent(@NonNull InputEvent event);
}
private class MySessionCallback extends SessionCallback {
diff --git a/media/java/android/media/tv/tuner/Lnb.java b/media/java/android/media/tv/tuner/Lnb.java
index 6a6a22c1fc0e..50a208344c3a 100644
--- a/media/java/android/media/tv/tuner/Lnb.java
+++ b/media/java/android/media/tv/tuner/Lnb.java
@@ -28,6 +28,9 @@ import android.media.tv.tuner.Tuner.Result;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.Executor;
/**
@@ -145,9 +148,9 @@ public class Lnb implements AutoCloseable {
private static final String TAG = "Lnb";
- LnbCallback mCallback;
- Executor mExecutor;
- Tuner mTuner;
+ Map<LnbCallback, Executor> mCallbackMap =
+ new HashMap<LnbCallback, Executor>();
+ Tuner mOwner;
private final Object mCallbackLock = new Object();
@@ -164,38 +167,82 @@ public class Lnb implements AutoCloseable {
private Lnb() {}
- void setCallback(Executor executor, @Nullable LnbCallback callback, Tuner tuner) {
+ void setCallbackAndOwner(Executor executor, @Nullable LnbCallback callback, Tuner tuner) {
synchronized (mCallbackLock) {
- mCallback = callback;
- mExecutor = executor;
- mTuner = tuner;
+ if (callback != null && executor != null) {
+ addCallback(callback, executor);
+ }
+ }
+ setOwner(tuner);
+ }
+
+ /**
+ * Adds LnbCallback
+ *
+ * @param callback the callback to receive notifications from LNB.
+ * @param executor the executor on which callback will be invoked. Cannot be null.
+ */
+ public void addCallback(@NonNull LnbCallback callback, @NonNull Executor executor) {
+ Objects.requireNonNull(callback, "callback must not be null");
+ Objects.requireNonNull(executor, "executor must not be null");
+ synchronized (mCallbackLock) {
+ mCallbackMap.put(callback, executor);
+ }
+ }
+
+ /**
+ * Removes LnbCallback
+ *
+ * @param callback the callback be removed for callback
+ *
+ * @return {@code true} when successful. {@code false} otherwise.
+ */
+ public boolean removeCallback(@NonNull LnbCallback callback) {
+ Objects.requireNonNull(callback, "callback must not be null");
+ synchronized (mCallbackLock) {
+ boolean result = (mCallbackMap.remove(callback) != null);
+ return result;
+ }
+ }
+
+ // allow owner transfer independent of whether callback is registered or not
+ /* package */ void setOwner(@NonNull Tuner newOwner) {
+ Objects.requireNonNull(newOwner, "newOwner must not be null");
+ synchronized (mLock) {
+ mOwner = newOwner;
}
}
private void onEvent(int eventType) {
synchronized (mCallbackLock) {
- if (mExecutor != null && mCallback != null) {
- mExecutor.execute(() -> {
- synchronized (mCallbackLock) {
- if (mCallback != null) {
- mCallback.onEvent(eventType);
+ for (LnbCallback callback : mCallbackMap.keySet()) {
+ Executor executor = mCallbackMap.get(callback);
+ if (callback != null && executor != null) {
+ executor.execute(() -> {
+ synchronized (mCallbackLock) {
+ if (callback != null) {
+ callback.onEvent(eventType);
+ }
}
- }
- });
+ });
+ }
}
}
}
private void onDiseqcMessage(byte[] diseqcMessage) {
synchronized (mCallbackLock) {
- if (mExecutor != null && mCallback != null) {
- mExecutor.execute(() -> {
- synchronized (mCallbackLock) {
- if (mCallback != null) {
- mCallback.onDiseqcMessage(diseqcMessage);
+ for (LnbCallback callback : mCallbackMap.keySet()) {
+ Executor executor = mCallbackMap.get(callback);
+ if (callback != null && executor != null) {
+ executor.execute(() -> {
+ synchronized (mCallbackLock) {
+ if (callback != null) {
+ callback.onDiseqcMessage(diseqcMessage);
+ }
}
- }
- });
+ });
+ }
}
}
}
@@ -279,7 +326,11 @@ public class Lnb implements AutoCloseable {
TunerUtils.throwExceptionForResult(res, "Failed to close LNB");
} else {
mIsClosed = true;
- mTuner.releaseLnb();
+ if (mOwner != null) {
+ mOwner.releaseLnb();
+ mOwner = null;
+ }
+ mCallbackMap.clear();
}
}
}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 4128abf03e07..9c4a83a235c0 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -241,7 +241,7 @@ public class Tuner implements AutoCloseable {
private static final String TAG = "MediaTvTuner";
- private static final boolean DEBUG = false;
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final int MSG_RESOURCE_LOST = 1;
private static final int MSG_ON_FILTER_EVENT = 2;
@@ -250,7 +250,6 @@ public class Tuner implements AutoCloseable {
private static final int FILTER_CLEANUP_THRESHOLD = 256;
-
/** @hide */
@IntDef(prefix = "DVR_TYPE_", value = {DVR_TYPE_RECORD, DVR_TYPE_PLAYBACK})
@Retention(RetentionPolicy.SOURCE)
@@ -455,6 +454,260 @@ public class Tuner implements AutoCloseable {
}
/**
+ * Transfers the ownership of shared frontend and its associated resources.
+ *
+ * @param newOwner the Tuner instance to be the new owner.
+ *
+ * @return result status of tune operation.
+ */
+ public int transferOwner(@NonNull Tuner newOwner) {
+ acquireTRMSLock("transferOwner()");
+ mFrontendLock.lock();
+ mFrontendCiCamLock.lock();
+ mLnbLock.lock();
+ try {
+
+ if (!isFrontendOwner() || !isNewOwnerQualifiedForTransfer(newOwner)) {
+ return RESULT_INVALID_STATE;
+ }
+
+ int res = transferFeOwner(newOwner);
+ if (res != RESULT_SUCCESS) {
+ return res;
+ }
+
+ res = transferCiCamOwner(newOwner);
+ if (res != RESULT_SUCCESS) {
+ return res;
+ }
+
+ res = transferLnbOwner(newOwner);
+ if (res != RESULT_SUCCESS) {
+ return res;
+ }
+ } finally {
+ mFrontendLock.unlock();
+ mFrontendCiCamLock.unlock();
+ mLnbLock.unlock();
+ releaseTRMSLock();
+ }
+ return RESULT_SUCCESS;
+ }
+
+ /**
+ * Resets or copies Frontend related settings.
+ */
+ private void replicateFrontendSettings(@Nullable Tuner src) {
+ mFrontendLock.lock();
+ try {
+ if (src == null) {
+ if (DEBUG) {
+ Log.d(TAG, "resetting Frontend params for " + mClientId);
+ }
+ mFrontend = null;
+ mFrontendHandle = null;
+ mFrontendInfo = null;
+ mFrontendType = FrontendSettings.TYPE_UNDEFINED;
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "copying Frontend params from " + src.mClientId
+ + " to " + mClientId);
+ }
+ mFrontend = src.mFrontend;
+ mFrontendHandle = src.mFrontendHandle;
+ mFrontendInfo = src.mFrontendInfo;
+ mFrontendType = src.mFrontendType;
+ }
+ } finally {
+ mFrontendLock.unlock();
+ }
+ }
+
+ /**
+ * Sets the frontend owner. mFeOwnerTuner should be null for the owner Tuner instance.
+ */
+ private void setFrontendOwner(Tuner owner) {
+ mFrontendLock.lock();
+ try {
+ mFeOwnerTuner = owner;
+ } finally {
+ mFrontendLock.unlock();
+ }
+ }
+
+ /**
+ * Resets or copies the CiCam related settings.
+ */
+ private void replicateCiCamSettings(@Nullable Tuner src) {
+ mFrontendCiCamLock.lock();
+ try {
+ if (src == null) {
+ if (DEBUG) {
+ Log.d(TAG, "resetting CiCamParams: " + mClientId);
+ }
+ mFrontendCiCamHandle = null;
+ mFrontendCiCamId = null;
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "copying CiCamParams from " + src.mClientId + " to " + mClientId);
+ Log.d(TAG, "mFrontendCiCamHandle:" + src.mFrontendCiCamHandle + ", "
+ + "mFrontendCiCamId:" + src.mFrontendCiCamId);
+ }
+ mFrontendCiCamHandle = src.mFrontendCiCamHandle;
+ mFrontendCiCamId = src.mFrontendCiCamId;
+ }
+ } finally {
+ mFrontendCiCamLock.unlock();
+ }
+ }
+
+ /**
+ * Resets or copies Lnb related settings.
+ */
+ private void replicateLnbSettings(@Nullable Tuner src) {
+ mLnbLock.lock();
+ try {
+ if (src == null) {
+ if (DEBUG) {
+ Log.d(TAG, "resetting Lnb params");
+ }
+ mLnb = null;
+ mLnbHandle = null;
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "copying Lnb params from " + src.mClientId + " to " + mClientId);
+ }
+ mLnb = src.mLnb;
+ mLnbHandle = src.mLnbHandle;
+ }
+ } finally {
+ mLnbLock.unlock();
+ }
+ }
+
+ /**
+ * Checks if it is a frontend resource owner.
+ * Proper mutex must be held prior to calling this.
+ */
+ private boolean isFrontendOwner() {
+ boolean notAnOwner = (mFeOwnerTuner != null);
+ if (notAnOwner) {
+ Log.e(TAG, "transferOwner() - cannot be called on the non-owner");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Checks if the newOwner is qualified.
+ * Proper mutex must be held prior to calling this.
+ */
+ private boolean isNewOwnerQualifiedForTransfer(@NonNull Tuner newOwner) {
+ // new owner must be the current sharee
+ boolean newOwnerIsTheCurrentSharee = (newOwner.mFeOwnerTuner == this)
+ && (newOwner.mFrontendHandle.equals(mFrontendHandle));
+ if (!newOwnerIsTheCurrentSharee) {
+ Log.e(TAG, "transferOwner() - new owner must be the current sharee");
+ return false;
+ }
+
+ // new owner must not be holding any of the to-be-shared resources
+ boolean newOwnerAlreadyHoldsToBeSharedResource =
+ (newOwner.mFrontendCiCamHandle != null || newOwner.mLnb != null);
+ if (newOwnerAlreadyHoldsToBeSharedResource) {
+ Log.e(TAG, "transferOwner() - new owner cannot be holding CiCam"
+ + " nor Lnb resource");
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Transfers the ownership of the already held frontend resource.
+ * Proper mutex must be held prior to calling this.
+ */
+ private int transferFeOwner(@NonNull Tuner newOwner) {
+ // handle native resource first
+ newOwner.nativeUpdateFrontend(getNativeContext());
+ nativeUpdateFrontend(0);
+
+ // transfer frontend related settings
+ newOwner.replicateFrontendSettings(this);
+
+ // transfer the frontend owner info
+ setFrontendOwner(newOwner);
+ newOwner.setFrontendOwner(null);
+
+ // handle TRM
+ if (mTunerResourceManager.transferOwner(
+ TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND,
+ mClientId, newOwner.mClientId)) {
+ return RESULT_SUCCESS;
+ } else {
+ return RESULT_UNKNOWN_ERROR;
+ }
+ }
+
+ /**
+ * Transfers the ownership of CiCam resource.
+ * This is a no-op if the CiCam resource is not held.
+ * Proper mutex must be held prior to calling this.
+ */
+ private int transferCiCamOwner(Tuner newOwner) {
+ boolean notAnOwner = (mFrontendCiCamHandle == null);
+ if (notAnOwner) {
+ // There is nothing to do here if there is no CiCam
+ return RESULT_SUCCESS;
+ }
+
+ // no need to handle at native level
+
+ // transfer the CiCam info at Tuner level
+ newOwner.replicateCiCamSettings(this);
+ replicateCiCamSettings(null);
+
+ // handle TRM
+ if (mTunerResourceManager.transferOwner(
+ TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM,
+ mClientId, newOwner.mClientId)) {
+ return RESULT_SUCCESS;
+ } else {
+ return RESULT_UNKNOWN_ERROR;
+ }
+ }
+
+ /**
+ * Transfers the ownership of Lnb resource.
+ * This is a no-op if the Lnb resource is not held.
+ * Proper mutex must be held prior to calling this.
+ */
+ private int transferLnbOwner(Tuner newOwner) {
+ boolean notAnOwner = (mLnb == null);
+ if (notAnOwner) {
+ // There is nothing to do here if there is no Lnb
+ return RESULT_SUCCESS;
+ }
+
+ // no need to handle at native level
+
+ // set the new owner
+ mLnb.setOwner(newOwner);
+
+ newOwner.replicateLnbSettings(this);
+ replicateLnbSettings(null);
+
+ // handle TRM
+ if (mTunerResourceManager.transferOwner(
+ TunerResourceManager.TUNER_RESOURCE_TYPE_LNB,
+ mClientId, newOwner.mClientId)) {
+ return RESULT_SUCCESS;
+ } else {
+ return RESULT_UNKNOWN_ERROR;
+ }
+ }
+
+ /**
* Updates client priority with an arbitrary value along with a nice value.
*
* <p>Tuner resource manager (TRM) uses the client priority value to decide whether it is able
@@ -547,59 +800,114 @@ public class Tuner implements AutoCloseable {
}
}
+ /**
+ * Either unshares the frontend resource (for sharee) or release Frontend (for owner)
+ */
+ public void closeFrontend() {
+ acquireTRMSLock("closeFrontend()");
+ try {
+ releaseFrontend();
+ } finally {
+ releaseTRMSLock();
+ }
+ }
+
+ /**
+ * Releases frontend resource for the owner. Unshares frontend resource for the sharee.
+ */
private void releaseFrontend() {
+ if (DEBUG) {
+ Log.d(TAG, "Tuner#releaseFrontend");
+ }
mFrontendLock.lock();
try {
if (mFrontendHandle != null) {
+ if (DEBUG) {
+ Log.d(TAG, "mFrontendHandle not null");
+ }
if (mFeOwnerTuner != null) {
+ if (DEBUG) {
+ Log.d(TAG, "mFeOwnerTuner not null - sharee");
+ }
// unregister self from the Frontend callback
mFeOwnerTuner.unregisterFrontendCallbackListener(this);
mFeOwnerTuner = null;
+ nativeUnshareFrontend();
} else {
+ if (DEBUG) {
+ Log.d(TAG, "mFeOwnerTuner null - owner");
+ }
// close resource as owner
int res = nativeCloseFrontend(mFrontendHandle);
if (res != Tuner.RESULT_SUCCESS) {
TunerUtils.throwExceptionForResult(res, "failed to close frontend");
}
- mTunerResourceManager.releaseFrontend(mFrontendHandle, mClientId);
}
+ if (DEBUG) {
+ Log.d(TAG, "call TRM#releaseFrontend :" + mFrontendHandle + ", " + mClientId);
+ }
+ mTunerResourceManager.releaseFrontend(mFrontendHandle, mClientId);
FrameworkStatsLog
.write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId,
FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__UNKNOWN);
- mFrontendHandle = null;
- mFrontend = null;
+ replicateFrontendSettings(null);
}
} finally {
mFrontendLock.unlock();
}
}
+ /**
+ * Releases CiCam resource if held. No-op otherwise.
+ */
+ private void releaseCiCam() {
+ mFrontendCiCamLock.lock();
+ try {
+ if (mFrontendCiCamHandle != null) {
+ if (DEBUG) {
+ Log.d(TAG, "unlinking CiCam : " + mFrontendCiCamHandle + " for " + mClientId);
+ }
+ int result = nativeUnlinkCiCam(mFrontendCiCamId);
+ if (result == RESULT_SUCCESS) {
+ mTunerResourceManager.releaseCiCam(mFrontendCiCamHandle, mClientId);
+ replicateCiCamSettings(null);
+ } else {
+ Log.e(TAG, "nativeUnlinkCiCam(" + mFrontendCiCamHandle + ") for mClientId:"
+ + mClientId + "failed with result:" + result);
+ }
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "NOT unlinking CiCam : " + mClientId);
+ }
+ }
+ } finally {
+ mFrontendCiCamLock.unlock();
+ }
+ }
+
private void releaseAll() {
+ // release CiCam before frontend because frontend handle is needed to unlink CiCam
+ releaseCiCam();
+
releaseFrontend();
mLnbLock.lock();
try {
// mLnb will be non-null only for owner tuner
if (mLnb != null) {
+ if (DEBUG) {
+ Log.d(TAG, "calling mLnb.close() : " + mClientId);
+ }
mLnb.close();
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "NOT calling mLnb.close() : " + mClientId);
+ }
}
} finally {
mLnbLock.unlock();
}
- mFrontendCiCamLock.lock();
- try {
- if (mFrontendCiCamHandle != null) {
- int result = nativeUnlinkCiCam(mFrontendCiCamId);
- if (result == RESULT_SUCCESS) {
- mTunerResourceManager.releaseCiCam(mFrontendCiCamHandle, mClientId);
- mFrontendCiCamId = null;
- mFrontendCiCamHandle = null;
- }
- }
- } finally {
- mFrontendCiCamLock.unlock();
- }
synchronized (mDescramblers) {
if (!mDescramblers.isEmpty()) {
@@ -669,8 +977,11 @@ public class Tuner implements AutoCloseable {
*/
private native Frontend nativeOpenFrontendByHandle(int handle);
private native int nativeShareFrontend(int id);
+ private native int nativeUnshareFrontend();
private native void nativeRegisterFeCbListener(long nativeContext);
private native void nativeUnregisterFeCbListener(long nativeContext);
+ // nativeUpdateFrontend must be called on the new owner first
+ private native void nativeUpdateFrontend(long nativeContext);
@Result
private native int nativeTune(int type, FrontendSettings settings);
private native int nativeStopTune();
@@ -997,6 +1308,21 @@ public class Tuner implements AutoCloseable {
mFrontendHandle = feHandle[0];
mFrontend = nativeOpenFrontendByHandle(mFrontendHandle);
}
+
+ // For satellite type, set Lnb if valid handle exists.
+ // This is necessary as now that we support closeFrontend().
+ if (mFrontendType == FrontendSettings.TYPE_DVBS
+ || mFrontendType == FrontendSettings.TYPE_ISDBS
+ || mFrontendType == FrontendSettings.TYPE_ISDBS3) {
+ mLnbLock.lock();
+ try {
+ if (mLnbHandle != null && mLnb != null) {
+ nativeSetLnb(mLnb);
+ }
+ } finally {
+ mLnbLock.unlock();
+ }
+ }
return granted;
}
@@ -1756,12 +2082,12 @@ public class Tuner implements AutoCloseable {
Objects.requireNonNull(executor, "executor must not be null");
Objects.requireNonNull(cb, "LnbCallback must not be null");
if (mLnb != null) {
- mLnb.setCallback(executor, cb, this);
+ mLnb.setCallbackAndOwner(executor, cb, this);
return mLnb;
}
if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_LNB, mLnbLock)
&& mLnb != null) {
- mLnb.setCallback(executor, cb, this);
+ mLnb.setCallbackAndOwner(executor, cb, this);
setLnb(mLnb);
return mLnb;
}
@@ -1795,7 +2121,7 @@ public class Tuner implements AutoCloseable {
mLnbHandle = null;
}
mLnb = newLnb;
- mLnb.setCallback(executor, cb, this);
+ mLnb.setCallbackAndOwner(executor, cb, this);
setLnb(mLnb);
}
return mLnb;
@@ -2081,8 +2407,15 @@ public class Tuner implements AutoCloseable {
try {
if (mLnbHandle != null) {
// LNB handle can be null if it's opened by name.
+ if (DEBUG) {
+ Log.d(TAG, "releasing Lnb");
+ }
mTunerResourceManager.releaseLnb(mLnbHandle, mClientId);
mLnbHandle = null;
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "NOT releasing Lnb because mLnbHandle is null");
+ }
}
mLnb = null;
} finally {
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 45c2a5a90c70..9f4423644877 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -626,8 +626,12 @@ public class Filter implements AutoCloseable {
* be a no-op. Use {@link TunerVersionChecker#getTunerVersion()} to get the version information.
*
* @param delayInMs specifies the duration of the delay in milliseconds.
+ * @return one of the following results: {@link Tuner#RESULT_SUCCESS},
+ * {@link Tuner#RESULT_UNAVAILABLE}, {@link Tuner#RESULT_NOT_INITIALIZED},
+ * {@link Tuner#RESULT_INVALID_STATE}, {@link Tuner#RESULT_INVALID_ARGUMENT},
+ * {@link Tuner#RESULT_OUT_OF_MEMORY}, or {@link Tuner#RESULT_UNKNOWN_ERROR}.
*/
- public int delayCallbackUntilTimeMillis(long delayInMs) {
+ public int delayCallbackUntilMillisElapsed(long delayInMs) {
if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
TunerVersionChecker.TUNER_VERSION_2_0, "setTimeDelayHint")) {
return Tuner.RESULT_UNAVAILABLE;
@@ -652,8 +656,12 @@ public class Filter implements AutoCloseable {
* be a no-op. Use {@link TunerVersionChecker#getTunerVersion()} to get the version information.
*
* @param delayInBytes specifies the duration of the delay in bytes.
+ * @return one of the following results: {@link Tuner#RESULT_SUCCESS},
+ * {@link Tuner#RESULT_UNAVAILABLE}, {@link Tuner#RESULT_NOT_INITIALIZED},
+ * {@link Tuner#RESULT_INVALID_STATE}, {@link Tuner#RESULT_INVALID_ARGUMENT},
+ * {@link Tuner#RESULT_OUT_OF_MEMORY}, or {@link Tuner#RESULT_UNKNOWN_ERROR}.
*/
- public int delayCallbackUntilBufferFilled(int delayInBytes) {
+ public int delayCallbackUntilBytesAccumulated(int delayInBytes) {
if (!TunerVersionChecker.checkHigherOrEqualVersionTo(
TunerVersionChecker.TUNER_VERSION_2_0, "setTimeDelayHint")) {
return Tuner.RESULT_UNAVAILABLE;
diff --git a/media/java/android/media/tv/tuner/filter/SectionSettings.java b/media/java/android/media/tv/tuner/filter/SectionSettings.java
index 94fda30fecb1..f123675a8940 100644
--- a/media/java/android/media/tv/tuner/filter/SectionSettings.java
+++ b/media/java/android/media/tv/tuner/filter/SectionSettings.java
@@ -16,12 +16,13 @@
package android.media.tv.tuner.filter;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.media.tv.tuner.TunerUtils;
/**
- * Filter Settings for Section data according to ISO/IEC 13818-1.
+ * Filter Settings for Section data according to ISO/IEC 13818-1 and ISO/IEC 23008-1.
*
* @hide
*/
@@ -30,12 +31,15 @@ public abstract class SectionSettings extends Settings {
final boolean mCrcEnabled;
final boolean mIsRepeat;
final boolean mIsRaw;
+ final int mBitWidthOfLengthField;
- SectionSettings(int mainType, boolean crcEnabled, boolean isRepeat, boolean isRaw) {
+ SectionSettings(int mainType, boolean crcEnabled, boolean isRepeat, boolean isRaw,
+ int bitWidthOfLengthField) {
super(TunerUtils.getFilterSubtype(mainType, Filter.SUBTYPE_SECTION));
mCrcEnabled = crcEnabled;
mIsRepeat = isRepeat;
mIsRaw = isRaw;
+ mBitWidthOfLengthField = bitWidthOfLengthField;
}
/**
@@ -62,6 +66,7 @@ public abstract class SectionSettings extends Settings {
public boolean isRepeat() {
return mIsRepeat;
}
+
/**
* Returns whether the filter sends {@link FilterCallback#onFilterStatusChanged} instead of
* {@link FilterCallback#onFilterEvent}.
@@ -71,6 +76,17 @@ public abstract class SectionSettings extends Settings {
}
/**
+ * Returns the bit width of the MMTP (MPEG Media Transport Protocol) section message's length
+ * field according to ISO/IEC 23008-1.
+ *
+ * The section filter uses this for CRC (Cyclic redundancy check) checking when
+ * {@link #isCrcEnabled()} is {@code true}.
+ */
+ public int getBitWidthOfLengthField() {
+ return mBitWidthOfLengthField;
+ }
+
+ /**
* Builder for {@link SectionSettings}.
*
* @param <T> The subclass to be built.
@@ -80,6 +96,7 @@ public abstract class SectionSettings extends Settings {
boolean mCrcEnabled;
boolean mIsRepeat;
boolean mIsRaw;
+ int mBitWidthOfLengthField;
Builder(int mainType) {
mMainType = mainType;
@@ -114,6 +131,7 @@ public abstract class SectionSettings extends Settings {
mIsRepeat = isRepeat;
return self();
}
+
/**
* Sets whether the filter send onFilterStatus instead of
* {@link FilterCallback#onFilterEvent}.
@@ -124,6 +142,23 @@ public abstract class SectionSettings extends Settings {
return self();
}
+ /**
+ * Sets the bit width for the MMTP(MPEG Media Transport Protocol) section message's length
+ * field according to ISO/IEC 23008-1.
+ *
+ * The section filter uses this for CRC (Cyclic redundancy check) checking when
+ * {@link #isCrcEnabled()} is {@code true}.
+ *
+ * <p>This field is only supported in Tuner 2.0 or higher version. Unsupported version will
+ * cause no-op. Use {@link android.media.tv.tuner.TunerVersionChecker#getTunerVersion()}
+ * to get the version information.
+ */
+ @NonNull
+ public T setBitWidthOfLengthField(@IntRange(from = 0) int bitWidthOfLengthField) {
+ mBitWidthOfLengthField = bitWidthOfLengthField;
+ return self();
+ }
+
/* package */ abstract T self();
}
}
diff --git a/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java b/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java
index edfe85ede943..766a5c9e67cb 100644
--- a/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java
+++ b/media/java/android/media/tv/tuner/filter/SectionSettingsWithSectionBits.java
@@ -30,10 +30,9 @@ public class SectionSettingsWithSectionBits extends SectionSettings {
private final byte[] mMask;
private final byte[] mMode;
-
private SectionSettingsWithSectionBits(int mainType, boolean isCheckCrc, boolean isRepeat,
- boolean isRaw, byte[] filter, byte[] mask, byte[] mode) {
- super(mainType, isCheckCrc, isRepeat, isRaw);
+ boolean isRaw, int bitWidthOfLengthField, byte[] filter, byte[] mask, byte[] mode) {
+ super(mainType, isCheckCrc, isRepeat, isRaw, bitWidthOfLengthField);
mFilter = filter;
mMask = mask;
mMode = mode;
@@ -126,8 +125,8 @@ public class SectionSettingsWithSectionBits extends SectionSettings {
*/
@NonNull
public SectionSettingsWithSectionBits build() {
- return new SectionSettingsWithSectionBits(
- mMainType, mCrcEnabled, mIsRepeat, mIsRaw, mFilter, mMask, mMode);
+ return new SectionSettingsWithSectionBits(mMainType, mCrcEnabled, mIsRepeat, mIsRaw,
+ mBitWidthOfLengthField, mFilter, mMask, mMode);
}
@Override
diff --git a/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java b/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java
index ff8f796455c6..eddef40caba4 100644
--- a/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java
+++ b/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java
@@ -37,8 +37,8 @@ public class SectionSettingsWithTableInfo extends SectionSettings {
private final int mVersion;
private SectionSettingsWithTableInfo(int mainType, boolean isCheckCrc, boolean isRepeat,
- boolean isRaw, int tableId, int version) {
- super(mainType, isCheckCrc, isRepeat, isRaw);
+ boolean isRaw, int bitWidthOfLengthField, int tableId, int version) {
+ super(mainType, isCheckCrc, isRepeat, isRaw, bitWidthOfLengthField);
mTableId = tableId;
mVersion = version;
}
@@ -99,8 +99,8 @@ public class SectionSettingsWithTableInfo extends SectionSettings {
*/
@NonNull
public SectionSettingsWithTableInfo build() {
- return new SectionSettingsWithTableInfo(
- mMainType, mCrcEnabled, mIsRepeat, mIsRaw, mTableId, mVersion);
+ return new SectionSettingsWithTableInfo(mMainType, mCrcEnabled, mIsRepeat, mIsRaw,
+ mBitWidthOfLengthField, mTableId, mVersion);
}
@Override
diff --git a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
index fe611c711273..5ada89e9dea7 100644
--- a/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
+++ b/media/java/android/media/tv/tunerresourcemanager/TunerResourceManager.java
@@ -21,9 +21,12 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
+import android.annotation.SuppressLint;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.media.tv.TvInputService;
import android.os.Binder;
import android.os.RemoteException;
import android.util.Log;
@@ -415,6 +418,25 @@ public class TunerResourceManager {
}
/**
+ * Transfers the ownership of shared resource.
+ *
+ * <p><strong>Note:</strong> Only the existing frontend sharee can be the new owner.
+ *
+ * @param resourceType the type of the resource to transfer the ownership for.
+ * @param currentOwnerId the id of the current owner client.
+ * @param newOwnerId the id of the new owner client.
+ *
+ * @return true if successful and false otherwise.
+ */
+ public boolean transferOwner(int resourceType, int currentOwnerId, int newOwnerId) {
+ try {
+ return mService.transferOwner(resourceType, currentOwnerId, newOwnerId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Requests a Tuner Demux resource.
*
* <p>There are three possible scenarios:
@@ -702,6 +724,49 @@ public class TunerResourceManager {
}
/**
+ * Returns a priority for the given use case type and the client's foreground or background
+ * status.
+ *
+ * @param useCase the use case type of the client. When the given use case type is invalid,
+ * the default use case type will be used. {@see TvInputService#PriorityHintUseCaseType}.
+ * @param pid the pid of the client. When the pid is invalid, background status will be used as
+ * a client's status. Otherwise, client's app corresponding to the given session id will
+ * be used as a client. {@see TvInputService#onCreateSession(String, String)}.
+ *
+ * @return the client priority..
+ */
+ public int getClientPriority(@TvInputService.PriorityHintUseCaseType int useCase, int pid) {
+ try {
+ return mService.getClientPriority(useCase, pid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns a config priority for the given use case type and the foreground or background
+ * status.
+ *
+ * @param useCase the use case type of the client. When the given use case type is invalid,
+ * the default use case type will be used. {@see TvInputService#PriorityHintUseCaseType}.
+ * @param isForeground {@code true} if foreground, {@code false} otherwise.
+ *
+ * @return the config priority.
+ *
+ * @hide
+ */
+ @TestApi
+ @SuppressLint("ShowingMemberInHiddenClass")
+ public int getConfigPriority(@TvInputService.PriorityHintUseCaseType int useCase,
+ boolean isForeground) {
+ try {
+ return mService.getConfigPriority(useCase, isForeground);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Interface used to receive events from TunerResourceManager.
*/
public abstract static class ResourcesReclaimListener {
diff --git a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
index 5f3582046d15..d16fc6ca1dc7 100644
--- a/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
+++ b/media/java/android/media/tv/tunerresourcemanager/aidl/android/media/tv/tunerresourcemanager/ITunerResourceManager.aidl
@@ -177,6 +177,19 @@ interface ITunerResourceManager {
void shareFrontend(in int selfClientId, in int targetClientId);
/*
+ * Transfers the ownership of the shared resource.
+ *
+ * <p><strong>Note:</strong> Only the existing frontend sharee can be the new owner.
+ *
+ * @param resourceType the type of resource to transfer the ownership for.
+ * @param currentOwnerId the id of the current owner client.
+ * @param newOwnerId the id of the new owner client.
+ *
+ * @return true if successful. false otherwise.
+ */
+ boolean transferOwner(in int resourceType, in int currentOwnerId, in int newOwnerId);
+
+ /*
* This API is used by the Tuner framework to request an available demux from the TunerHAL.
*
* <p>There are three possible scenarios:
@@ -442,4 +455,30 @@ interface ITunerResourceManager {
* guaranteed to work and may be unrecoverrable. (This should not happen.)
*/
boolean releaseLock(in int clientId);
+
+ /**
+ * Returns a priority for the given use case type and the client's foreground or background
+ * status.
+ *
+ * @param useCase the use case type of the client. When the given use case type is invalid,
+ * the default use case type will be used. {@see TvInputService#PriorityHintUseCaseType}.
+ * @param pid the pid of the client. When the pid is invalid, background status will be used as
+ * a client's status. Otherwise, client's app corresponding to the given session id will
+ * be used as a client. {@see TvInputService#onCreateSession(String, String)}.
+ *
+ * @return the client priority..
+ */
+ int getClientPriority(int useCase, int pid);
+
+ /**
+ * Returns a config priority for the given use case type and the foreground or background
+ * status.
+ *
+ * @param useCase the use case type of the client. When the given use case type is invalid,
+ * the default use case type will be used. {@see TvInputService#PriorityHintUseCaseType}.
+ * @param isForeground {@code true} if foreground, {@code false} otherwise.
+ *
+ * @return the config priority.
+ */
+ int getConfigPriority(int useCase, boolean isForeground);
}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index e817f2dc9e1d..feae6065c680 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -39,6 +39,7 @@ cc_library_shared {
"android_media_MediaProfiles.cpp",
"android_media_MediaRecorder.cpp",
"android_media_MediaSync.cpp",
+ "android_media_PublicFormatUtils.cpp",
"android_media_ResampleInputStream.cpp",
"android_media_Streams.cpp",
"android_media_SyncParams.cpp",
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 021507c8631c..6002e2884db8 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -375,18 +375,13 @@ static void ImageReader_classInit(JNIEnv* env, jclass clazz)
}
static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint width, jint height,
- jint format, jint maxImages, jlong ndkUsage)
-{
+ jint maxImages, jlong ndkUsage, jint nativeFormat, jlong dataSpace) {
status_t res;
- int nativeFormat;
- android_dataspace nativeDataspace;
- ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
- __FUNCTION__, width, height, format, maxImages);
+ ALOGV("%s: width:%d, height: %d, nativeFormat: %d, maxImages:%d",
+ __FUNCTION__, width, height, nativeFormat, maxImages);
- PublicFormat publicFormat = static_cast<PublicFormat>(format);
- nativeFormat = mapPublicFormatToHalFormat(publicFormat);
- nativeDataspace = mapPublicFormatToHalDataspace(publicFormat);
+ android_dataspace nativeDataspace = static_cast<android_dataspace>(dataSpace);
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
@@ -400,7 +395,7 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint w
BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
sp<BufferItemConsumer> bufferConsumer;
String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
- width, height, format, maxImages, getpid(),
+ width, height, nativeFormat, maxImages, getpid(),
createProcessUniqueId());
uint64_t consumerUsage =
android_hardware_HardwareBuffer_convertToGrallocUsageBits(ndkUsage);
@@ -527,7 +522,8 @@ static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
ALOGV("%s: Image (format: 0x%x) has been released", __FUNCTION__, ctx->getBufferFormat());
}
-static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) {
+static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image,
+ jboolean legacyValidateImageFormat) {
ALOGV("%s:", __FUNCTION__);
JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
if (ctx == NULL) {
@@ -590,7 +586,7 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) {
ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
__FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
}
- if (imgReaderFmt != bufferFormat) {
+ if (legacyValidateImageFormat && imgReaderFmt != bufferFormat) {
if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 &&
isPossiblyYUV(bufferFormat)) {
// Treat formats that are compatible with flexible YUV
@@ -958,10 +954,10 @@ static jobject Image_getHardwareBuffer(JNIEnv* env, jobject thiz) {
static const JNINativeMethod gImageReaderMethods[] = {
{"nativeClassInit", "()V", (void*)ImageReader_classInit },
- {"nativeInit", "(Ljava/lang/Object;IIIIJ)V", (void*)ImageReader_init },
+ {"nativeInit", "(Ljava/lang/Object;IIIJIJ)V", (void*)ImageReader_init },
{"nativeClose", "()V", (void*)ImageReader_close },
{"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease },
- {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup },
+ {"nativeImageSetup", "(Landroid/media/Image;Z)I", (void*)ImageReader_imageSetup },
{"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface },
{"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage },
{"nativeCreateImagePlanes",
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 8dcdc989ec8f..a548a472fc3a 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -1454,6 +1454,7 @@ extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);
extern int register_android_media_MediaMuxer(JNIEnv *env);
extern int register_android_media_MediaRecorder(JNIEnv *env);
extern int register_android_media_MediaSync(JNIEnv *env);
+extern int register_android_media_PublicFormatUtils(JNIEnv *env);
extern int register_android_media_ResampleInputStream(JNIEnv *env);
extern int register_android_media_MediaProfiles(JNIEnv *env);
extern int register_android_mtp_MtpDatabase(JNIEnv *env);
@@ -1501,6 +1502,11 @@ jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
goto bail;
}
+ if (register_android_media_PublicFormatUtils(env) < 0) {
+ ALOGE("ERROR: PublicFormatUtils native registration failed\n");
+ goto bail;
+ }
+
if (register_android_media_ResampleInputStream(env) < 0) {
ALOGE("ERROR: ResampleInputStream native registration failed\n");
goto bail;
diff --git a/media/jni/android_media_PublicFormatUtils.cpp b/media/jni/android_media_PublicFormatUtils.cpp
new file mode 100644
index 000000000000..09ebdeeff06f
--- /dev/null
+++ b/media/jni/android_media_PublicFormatUtils.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PublicFormatUtils_JNI"
+
+#include <utils/misc.h>
+#include <ui/PublicFormat.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <jni.h>
+
+using namespace android;
+
+static jint android_media_PublicFormatUtils_getHalFormat(JNIEnv* /*env*/, jobject /*thiz*/,
+ jint imageFormat) {
+ PublicFormat publicFormat = static_cast<PublicFormat>(imageFormat);
+ int nativeFormat = mapPublicFormatToHalFormat(publicFormat);
+ return static_cast<jint>(nativeFormat);
+}
+
+static jlong android_media_PublicFormatUtils_getHalDataspace(JNIEnv* /*env*/, jobject /*thiz*/,
+ jint imageFormat) {
+ PublicFormat publicFormat = static_cast<PublicFormat>(imageFormat);
+ android_dataspace
+ nativeDataspace = mapPublicFormatToHalDataspace(publicFormat);
+ return static_cast<jlong>(nativeDataspace);
+}
+
+static jint android_media_PublicFormatUtils_getPublicFormat(JNIEnv* /*env*/, jobject /*thiz*/,
+ jint hardwareBufferFormat,
+ jlong dataspace) {
+ PublicFormat nativeFormat = mapHalFormatDataspaceToPublicFormat(
+ hardwareBufferFormat, static_cast<android_dataspace>(dataspace));
+ return static_cast<jint>(nativeFormat);
+}
+
+static const JNINativeMethod gMethods[] = {
+ {"nativeGetHalFormat", "(I)I", (void*)android_media_PublicFormatUtils_getHalFormat},
+ {"nativeGetHalDataspace", "(I)J", (void*)android_media_PublicFormatUtils_getHalDataspace},
+ {"nativeGetPublicFormat", "(IJ)I",(void*)android_media_PublicFormatUtils_getPublicFormat}
+};
+
+int register_android_media_PublicFormatUtils(JNIEnv *env) {
+ return AndroidRuntime::registerNativeMethods(env,
+ "android/media/PublicFormatUtils", gMethods, NELEM(gMethods));
+}
+
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index c601649b74a1..1b41494814b7 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -461,6 +461,7 @@ MediaEvent::MediaEvent(sp<FilterClient> filterClient, native_handle_t *avHandle,
}
MediaEvent::~MediaEvent() {
+ android::Mutex::Autolock autoLock(mLock);
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->DeleteWeakGlobalRef(mMediaEventObj);
mMediaEventObj = nullptr;
@@ -977,7 +978,8 @@ FrontendClientCallbackImpl::FrontendClientCallbackImpl(JTuner* jtuner, jweak lis
void FrontendClientCallbackImpl::addCallbackListener(JTuner* jtuner, jweak listener) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jweak listenerRef = env->NewWeakGlobalRef(listener);
- ALOGV("addCallbackListener() with listener:%p and ref:%p @%p", listener, listenerRef, this);
+ ALOGV("addCallbackListener() with listener:%p and ref:%p @%p",
+ listener, listenerRef, this);
std::scoped_lock<std::mutex> lock(mMutex);
mListenersMap[jtuner] = listenerRef;
}
@@ -1344,18 +1346,43 @@ int JTuner::shareFrontend(int feId) {
return (int)Result::SUCCESS;
}
+int JTuner::unshareFrontend() {
+ if (mFeClient != nullptr) {
+ ALOGE("Cannot unshare frontend because this session is already holding %d"
+ " as an owner instead of as a sharee", mFeClient->getId());
+ return (int)Result::INVALID_STATE;
+ }
+
+ mSharedFeId = (int)Constant::INVALID_FRONTEND_ID;
+ return (int)Result::SUCCESS;
+}
+
void JTuner::registerFeCbListener(JTuner* jtuner) {
+ ALOGV("registerFeCbListener: %p", jtuner);
if (mFeClientCb != nullptr && jtuner != nullptr) {
mFeClientCb->addCallbackListener(jtuner, jtuner->getObject());
}
}
void JTuner::unregisterFeCbListener(JTuner* jtuner) {
+ ALOGV("unregisterFeCbListener: %p", jtuner);
if (mFeClientCb != nullptr && jtuner != nullptr) {
mFeClientCb->removeCallbackListener(jtuner);
}
}
+void JTuner::updateFrontend(JTuner* jtuner) {
+ if (jtuner == nullptr) {
+ ALOGV("JTuner::updateFrontend(null) called for previous owner: %p", this);
+ mFeClient = nullptr;
+ mFeClientCb = nullptr;
+ } else {
+ ALOGV("JTuner::updateFrontend(%p) called for new owner: %p", jtuner, this);
+ mFeClient = jtuner->mFeClient;
+ mFeClientCb = jtuner->mFeClientCb;
+ }
+}
+
jobject JTuner::getAnalogFrontendCaps(JNIEnv *env, FrontendCapabilities &caps) {
jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendCapabilities");
jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(II)V");
@@ -3318,6 +3345,12 @@ static int android_media_tv_Tuner_share_frontend(
return tuner->shareFrontend(id);
}
+static int android_media_tv_Tuner_unshare_frontend(
+ JNIEnv *env, jobject thiz) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ return tuner->unshareFrontend();
+}
+
static void android_media_tv_Tuner_register_fe_cb_listener(
JNIEnv *env, jobject thiz, jlong shareeJTuner) {
sp<JTuner> tuner = getTuner(env, thiz);
@@ -3332,6 +3365,17 @@ static void android_media_tv_Tuner_unregister_fe_cb_listener(
tuner->unregisterFeCbListener(jtuner);
}
+static void android_media_tv_Tuner_update_frontend(JNIEnv *env, jobject thiz, jlong jtunerPtr) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ JTuner *jtuner;
+ if (jtunerPtr == 0) {
+ jtuner = nullptr;
+ } else {
+ jtuner = (JTuner *) jtunerPtr;
+ }
+ tuner->updateFrontend(jtuner);
+}
+
static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
sp<JTuner> tuner = getTuner(env, thiz);
FrontendSettings setting = getFrontendSettings(env, type, settings);
@@ -3515,11 +3559,14 @@ static DemuxFilterSectionSettings getFilterSectionSettings(JNIEnv *env, const jo
bool isCheckCrc = env->GetBooleanField(settings, env->GetFieldID(clazz, "mCrcEnabled", "Z"));
bool isRepeat = env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRepeat", "Z"));
bool isRaw = env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsRaw", "Z"));
+ int32_t bitWidthOfLengthField =
+ env->GetIntField(settings, env->GetFieldID(clazz, "mBitWidthOfLengthField", "I"));
DemuxFilterSectionSettings filterSectionSettings {
.isCheckCrc = isCheckCrc,
.isRepeat = isRepeat,
.isRaw = isRaw,
+ .bitWidthOfLengthField = bitWidthOfLengthField,
};
if (env->IsInstanceOf(
settings,
@@ -4570,10 +4617,14 @@ static const JNINativeMethod gTunerMethods[] = {
(void *)android_media_tv_Tuner_open_frontend_by_handle },
{ "nativeShareFrontend", "(I)I",
(void *)android_media_tv_Tuner_share_frontend },
+ { "nativeUnshareFrontend", "()I",
+ (void *)android_media_tv_Tuner_unshare_frontend },
{ "nativeRegisterFeCbListener", "(J)V",
(void*)android_media_tv_Tuner_register_fe_cb_listener },
{ "nativeUnregisterFeCbListener", "(J)V",
(void*)android_media_tv_Tuner_unregister_fe_cb_listener },
+ { "nativeUpdateFrontend", "(J)V",
+ (void*)android_media_tv_Tuner_update_frontend },
{ "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
(void *)android_media_tv_Tuner_tune },
{ "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index f1b31e3520b1..502bd6b18413 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -178,8 +178,10 @@ struct JTuner : public RefBase {
jobject getFrontendIds();
jobject openFrontendByHandle(int feHandle);
int shareFrontend(int feId);
+ int unshareFrontend();
void registerFeCbListener(JTuner* jtuner);
void unregisterFeCbListener(JTuner* jtuner);
+ void updateFrontend(JTuner* jtuner);
jint closeFrontendById(int id);
jobject getFrontendInfo(int id);
int tune(const FrontendSettings& settings);
diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp
index 773cdc982af7..50bb79ccaa0b 100644
--- a/media/jni/soundpool/Stream.cpp
+++ b/media/jni/soundpool/Stream.cpp
@@ -275,118 +275,104 @@ void Stream::play_l(const std::shared_ptr<Sound>& sound, int32_t nextStreamID,
float leftVolume, float rightVolume, int32_t priority, int32_t loop, float rate,
std::vector<std::any>& garbage)
{
- // oldTrack and newTrack are placeholders to be released by garbage without the lock.
- sp<AudioTrack> oldTrack;
- sp<AudioTrack> newTrack;
- status_t status = NO_ERROR;
-
- {
- ALOGV("%s(%p)(soundID=%d, streamID=%d, leftVolume=%f, rightVolume=%f,"
- " priority=%d, loop=%d, rate=%f)",
- __func__, this, sound->getSoundID(), nextStreamID, leftVolume, rightVolume,
- priority, loop, rate);
-
- // initialize track
- const audio_stream_type_t streamType =
- AudioSystem::attributesToStreamType(*mStreamManager->getAttributes());
- const int32_t channelCount = sound->getChannelCount();
- const auto sampleRate = (uint32_t)lround(double(sound->getSampleRate()) * rate);
- size_t frameCount = 0;
-
- if (loop) {
- const audio_format_t format = sound->getFormat();
- const size_t frameSize = audio_is_linear_pcm(format)
- ? channelCount * audio_bytes_per_sample(format) : 1;
- frameCount = sound->getSizeInBytes() / frameSize;
- }
+ ALOGV("%s(%p)(soundID=%d, streamID=%d, leftVolume=%f, rightVolume=%f,"
+ " priority=%d, loop=%d, rate=%f)",
+ __func__, this, sound->getSoundID(), nextStreamID, leftVolume, rightVolume,
+ priority, loop, rate);
+
+ // initialize track
+ const audio_stream_type_t streamType =
+ AudioSystem::attributesToStreamType(*mStreamManager->getAttributes());
+ const int32_t channelCount = sound->getChannelCount();
+ const auto sampleRate = (uint32_t)lround(double(sound->getSampleRate()) * rate);
+ size_t frameCount = 0;
+
+ if (loop) {
+ const audio_format_t format = sound->getFormat();
+ const size_t frameSize = audio_is_linear_pcm(format)
+ ? channelCount * audio_bytes_per_sample(format) : 1;
+ frameCount = sound->getSizeInBytes() / frameSize;
+ }
- // check if the existing track has the same sound id.
- if (mAudioTrack != nullptr && mSoundID == sound->getSoundID()) {
+ if (mAudioTrack != nullptr) {
+ if (mSoundID == sound->getSoundID()
+ && mAudioTrack->setSampleRate(sampleRate) == NO_ERROR) {
+ // Reuse the old track if the soundID matches.
// the sample rate may fail to change if the audio track is a fast track.
- if (mAudioTrack->setSampleRate(sampleRate) == NO_ERROR) {
- newTrack = mAudioTrack;
- ALOGV("%s: reusing track %p for sound %d",
- __func__, mAudioTrack.get(), sound->getSoundID());
- }
- }
- if (newTrack == nullptr) {
- // mToggle toggles each time a track is started on a given stream.
- // The toggle is concatenated with the Stream address and passed to AudioTrack
- // as callback user data. This enables the detection of callbacks received from the old
- // audio track while the new one is being started and avoids processing them with
- // wrong audio audio buffer size (mAudioBufferSize)
- auto toggle = mToggle ^ 1;
- // NOLINTNEXTLINE(performance-no-int-to-ptr)
- void* userData = reinterpret_cast<void*>((uintptr_t)this | toggle);
- audio_channel_mask_t soundChannelMask = sound->getChannelMask();
- // When sound contains a valid channel mask, use it as is.
- // Otherwise, use stream count to calculate channel mask.
- audio_channel_mask_t channelMask = soundChannelMask != AUDIO_CHANNEL_NONE
- ? soundChannelMask : audio_channel_out_mask_from_count(channelCount);
-
- // do not create a new audio track if current track is compatible with sound parameters
-
- android::content::AttributionSourceState attributionSource;
- attributionSource.packageName = mStreamManager->getOpPackageName();
- attributionSource.token = sp<BBinder>::make();
- // TODO b/182469354 make consistent with AudioRecord, add util for native source
- newTrack = new AudioTrack(streamType, sampleRate, sound->getFormat(),
- channelMask, sound->getIMemory(), AUDIO_OUTPUT_FLAG_FAST,
- staticCallback, userData,
- 0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
- AudioTrack::TRANSFER_DEFAULT,
- nullptr /*offloadInfo*/, attributionSource,
- mStreamManager->getAttributes(),
- false /*doNotReconnect*/, 1.0f /*maxRequiredSpeed*/);
- // Set caller name so it can be logged in destructor.
- // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_SOUNDPOOL
- newTrack->setCallerName("soundpool");
- oldTrack = mAudioTrack;
- status = newTrack->initCheck();
- if (status != NO_ERROR) {
- ALOGE("%s: error creating AudioTrack", __func__);
- // newTrack goes out of scope, so reference count drops to zero
- goto exit;
- }
- // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
- mToggle = toggle;
- mAudioTrack = newTrack;
- ALOGV("%s: using new track %p for sound %d",
- __func__, newTrack.get(), sound->getSoundID());
- }
- if (mMuted) {
- newTrack->setVolume(0.0f, 0.0f);
+ ALOGV("%s: reusing track %p for sound %d",
+ __func__, mAudioTrack.get(), sound->getSoundID());
} else {
- newTrack->setVolume(leftVolume, rightVolume);
+ // If reuse not possible, move mAudioTrack to garbage, set to nullptr.
+ garbage.emplace_back(std::move(mAudioTrack));
+ mAudioTrack.clear(); // move should have cleared the sp<>, but we clear just in case.
}
- newTrack->setLoop(0, frameCount, loop);
- mAudioTrack->start();
- mSound = sound;
- mSoundID = sound->getSoundID();
- mPriority = priority;
- mLoop = loop;
- mLeftVolume = leftVolume;
- mRightVolume = rightVolume;
- mRate = rate;
- mState = PLAYING;
- mStopTimeNs = 0;
- mStreamID = nextStreamID; // prefer this to be the last, as it is an atomic sync point
}
-
-exit:
- ALOGV("%s: delete oldTrack %p", __func__, oldTrack.get());
- if (status != NO_ERROR) {
- // TODO: should we consider keeping the soundID if the old track is OK?
- // Do not attempt to restart this track (should we remove the stream id?)
- mState = IDLE;
- mSoundID = 0;
- mSound.reset();
- mAudioTrack.clear(); // actual release from garbage
+ if (mAudioTrack == nullptr) {
+ // mToggle toggles each time a track is started on a given stream.
+ // The toggle is concatenated with the Stream address and passed to AudioTrack
+ // as callback user data. This enables the detection of callbacks received from the old
+ // audio track while the new one is being started and avoids processing them with
+ // wrong audio audio buffer size (mAudioBufferSize)
+ auto toggle = mToggle ^ 1;
+ // NOLINTNEXTLINE(performance-no-int-to-ptr)
+ void* userData = reinterpret_cast<void*>((uintptr_t)this | toggle);
+ audio_channel_mask_t soundChannelMask = sound->getChannelMask();
+ // When sound contains a valid channel mask, use it as is.
+ // Otherwise, use stream count to calculate channel mask.
+ audio_channel_mask_t channelMask = soundChannelMask != AUDIO_CHANNEL_NONE
+ ? soundChannelMask : audio_channel_out_mask_from_count(channelCount);
+
+ // do not create a new audio track if current track is compatible with sound parameters
+
+ android::content::AttributionSourceState attributionSource;
+ attributionSource.packageName = mStreamManager->getOpPackageName();
+ attributionSource.token = sp<BBinder>::make();
+ // TODO b/182469354 make consistent with AudioRecord, add util for native source
+ mAudioTrack = new AudioTrack(streamType, sampleRate, sound->getFormat(),
+ channelMask, sound->getIMemory(), AUDIO_OUTPUT_FLAG_FAST,
+ staticCallback, userData,
+ 0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
+ AudioTrack::TRANSFER_DEFAULT,
+ nullptr /*offloadInfo*/, attributionSource,
+ mStreamManager->getAttributes(),
+ false /*doNotReconnect*/, 1.0f /*maxRequiredSpeed*/);
+ // Set caller name so it can be logged in destructor.
+ // MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_SOUNDPOOL
+ mAudioTrack->setCallerName("soundpool");
+
+ if (status_t status = mAudioTrack->initCheck();
+ status != NO_ERROR) {
+ ALOGE("%s: error %d creating AudioTrack", __func__, status);
+ // TODO: should we consider keeping the soundID and reusing the old track?
+ mState = IDLE;
+ mSoundID = 0;
+ mSound.reset();
+ garbage.emplace_back(std::move(mAudioTrack)); // remove mAudioTrack.
+ mAudioTrack.clear(); // move should have cleared the sp<>, but we clear just in case.
+ return;
+ }
+ // From now on, AudioTrack callbacks received with previous toggle value will be ignored.
+ mToggle = toggle;
+ ALOGV("%s: using new track %p for sound %d",
+ __func__, mAudioTrack.get(), sound->getSoundID());
}
-
- // move tracks to garbage to be released later outside of lock.
- if (newTrack) garbage.emplace_back(std::move(newTrack));
- if (oldTrack) garbage.emplace_back(std::move(oldTrack));
+ if (mMuted) {
+ mAudioTrack->setVolume(0.f, 0.f);
+ } else {
+ mAudioTrack->setVolume(leftVolume, rightVolume);
+ }
+ mAudioTrack->setLoop(0, frameCount, loop);
+ mAudioTrack->start();
+ mSound = sound;
+ mSoundID = sound->getSoundID();
+ mPriority = priority;
+ mLoop = loop;
+ mLeftVolume = leftVolume;
+ mRightVolume = rightVolume;
+ mRate = rate;
+ mState = PLAYING;
+ mStopTimeNs = 0;
+ mStreamID = nextStreamID; // prefer this to be the last, as it is an atomic sync point
}
/* static */
diff --git a/media/jni/tuner/FilterClient.cpp b/media/jni/tuner/FilterClient.cpp
index 8568383385ac..959e756b8a16 100644
--- a/media/jni/tuner/FilterClient.cpp
+++ b/media/jni/tuner/FilterClient.cpp
@@ -43,6 +43,7 @@ FilterClient::FilterClient(DemuxFilterType type, shared_ptr<ITunerFilter> tunerF
}
FilterClient::~FilterClient() {
+ Mutex::Autolock _l(mLock);
mTunerFilter = nullptr;
mAvSharedHandle = nullptr;
mAvSharedMemSize = 0;
@@ -74,6 +75,7 @@ Result FilterClient::configure(DemuxFilterSettings configure) {
Result res;
checkIsPassthroughFilter(configure);
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configure(configure);
res = ClientHelper::getServiceSpecificErrorCode(s);
@@ -87,6 +89,7 @@ Result FilterClient::configure(DemuxFilterSettings configure) {
}
Result FilterClient::configureMonitorEvent(int32_t monitorEventType) {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configureMonitorEvent(monitorEventType);
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -96,6 +99,7 @@ Result FilterClient::configureMonitorEvent(int32_t monitorEventType) {
}
Result FilterClient::configureIpFilterContextId(int32_t cid) {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configureIpFilterContextId(cid);
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -105,6 +109,7 @@ Result FilterClient::configureIpFilterContextId(int32_t cid) {
}
Result FilterClient::configureAvStreamType(AvStreamType avStreamType) {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->configureAvStreamType(avStreamType);
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -114,6 +119,7 @@ Result FilterClient::configureAvStreamType(AvStreamType avStreamType) {
}
Result FilterClient::start() {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->start();
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -123,6 +129,7 @@ Result FilterClient::start() {
}
Result FilterClient::stop() {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->stop();
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -132,6 +139,7 @@ Result FilterClient::stop() {
}
Result FilterClient::flush() {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->flush();
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -141,6 +149,7 @@ Result FilterClient::flush() {
}
Result FilterClient::getId(int32_t& id) {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->getId(&id);
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -150,6 +159,7 @@ Result FilterClient::getId(int32_t& id) {
}
Result FilterClient::getId64Bit(int64_t& id) {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->getId64Bit(&id);
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -159,6 +169,7 @@ Result FilterClient::getId64Bit(int64_t& id) {
}
Result FilterClient::releaseAvHandle(native_handle_t* handle, uint64_t avDataId) {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->releaseAvHandle(dupToAidl(handle), avDataId);
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -168,6 +179,7 @@ Result FilterClient::releaseAvHandle(native_handle_t* handle, uint64_t avDataId)
}
Result FilterClient::setDataSource(sp<FilterClient> filterClient){
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->setDataSource(filterClient->getAidlFilter());
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -177,6 +189,7 @@ Result FilterClient::setDataSource(sp<FilterClient> filterClient){
}
Result FilterClient::close() {
+ Mutex::Autolock _l(mLock);
if (mFilterMQEventFlag != nullptr) {
EventFlag::deleteEventFlag(&mFilterMQEventFlag);
mFilterMQEventFlag = nullptr;
@@ -197,6 +210,7 @@ Result FilterClient::close() {
}
string FilterClient::acquireSharedFilterToken() {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
string filterToken;
if (mTunerFilter->acquireSharedFilterToken(&filterToken).isOk()) {
@@ -208,6 +222,7 @@ string FilterClient::acquireSharedFilterToken() {
}
Result FilterClient::freeSharedFilterToken(const string& filterToken) {
+ Mutex::Autolock _l(mLock);
if (mTunerFilter != nullptr) {
Status s = mTunerFilter->freeSharedFilterToken(filterToken);
return ClientHelper::getServiceSpecificErrorCode(s);
@@ -237,6 +252,7 @@ Status TunerFilterCallback::onFilterEvent(const vector<DemuxFilterEvent>& filter
}
Result FilterClient::getFilterMq() {
+ Mutex::Autolock _l(mLock);
if (mFilterMQ != nullptr) {
return Result::SUCCESS;
}
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
index 20e56102a909..9e9b2332ac33 100644
--- a/media/jni/tuner/FilterClient.h
+++ b/media/jni/tuner/FilterClient.h
@@ -21,6 +21,7 @@
#include <aidl/android/media/tv/tuner/BnTunerFilterCallback.h>
#include <aidl/android/media/tv/tuner/ITunerFilter.h>
#include <fmq/AidlMessageQueue.h>
+#include <utils/Mutex.h>
#include "ClientHelper.h"
#include "FilterClientCallback.h"
@@ -37,6 +38,7 @@ using ::aidl::android::hardware::tv::tuner::FilterDelayHint;
using ::aidl::android::media::tv::tuner::BnTunerFilterCallback;
using ::aidl::android::media::tv::tuner::ITunerFilter;
using ::android::hardware::EventFlag;
+using ::android::Mutex;
using namespace std;
@@ -179,6 +181,7 @@ private:
uint64_t mAvSharedMemSize;
bool mIsMediaFilter;
bool mIsPassthroughFilter;
+ Mutex mLock;
};
} // namespace android
diff --git a/native/android/libandroid_net.map.txt b/native/android/libandroid_net.map.txt
index a6c1b5098066..32fd734d61a0 100644
--- a/native/android/libandroid_net.map.txt
+++ b/native/android/libandroid_net.map.txt
@@ -18,6 +18,10 @@ LIBANDROID_NET {
android_getprocnetwork; # llndk
android_setprocdns; # llndk
android_getprocdns; # llndk
+ # These functions have been part of the NDK since API 33.
+ android_tag_socket_with_uid; # llndk
+ android_tag_socket; # llndk
+ android_untag_socket; # llndk
local:
*;
};
diff --git a/native/android/net.c b/native/android/net.c
index e2f36a77b7c6..d7c22e1a5741 100644
--- a/native/android/net.c
+++ b/native/android/net.c
@@ -161,3 +161,15 @@ int android_res_nsend(net_handle_t network, const uint8_t *msg, size_t msglen,
void android_res_cancel(int nsend_fd) {
resNetworkCancel(nsend_fd);
}
+
+int android_tag_socket_with_uid(int sockfd, int tag, uid_t uid) {
+ return tagSocket(sockfd, tag, uid);
+}
+
+int android_tag_socket(int sockfd, int tag) {
+ return tagSocket(sockfd, tag, -1);
+}
+
+int android_untag_socket(int sockfd) {
+ return untagSocket(sockfd);
+}
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
index a316b8a617b7..583f7ba8cde5 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -54,6 +54,7 @@ import com.android.net.module.util.NetworkIdentityUtils;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* Provides access to network usage history and statistics. Usage data is collected in
@@ -535,6 +536,31 @@ public class NetworkStatsManager {
return result;
}
+ /**
+ * Query realtime network usage statistics details with interfaces constrains.
+ * Return snapshot of current UID statistics, including any {@link TrafficStats#UID_TETHERING},
+ * video calling data usage and count of network operations that set by
+ * {@link TrafficStats#incrementOperationCount}. The returned data doesn't include any
+ * statistics that is reported by {@link NetworkStatsProvider}.
+ *
+ * @param requiredIfaces A list of interfaces the stats should be restricted to, or
+ * {@link NetworkStats#INTERFACES_ALL}.
+ *
+ * @hide
+ */
+ //@SystemApi
+ @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+ @NonNull public android.net.NetworkStats getDetailedUidStats(
+ @NonNull Set<String> requiredIfaces) {
+ Objects.requireNonNull(requiredIfaces, "requiredIfaces cannot be null");
+ try {
+ return mService.getDetailedUidStats(requiredIfaces.toArray(new String[0]));
+ } catch (RemoteException e) {
+ if (DBG) Log.d(TAG, "Remote exception when get detailed uid stats");
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
/** @hide */
public void registerUsageCallback(NetworkTemplate template, int networkType,
long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
diff --git a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java
index f0ff46522d15..b06d515b3acf 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/DataUsageRequest.java
@@ -75,7 +75,7 @@ public final class DataUsageRequest implements Parcelable {
@Override
public DataUsageRequest createFromParcel(Parcel in) {
int requestId = in.readInt();
- NetworkTemplate template = in.readParcelable(null, android.net.NetworkTemplate.class);
+ NetworkTemplate template = in.readParcelable(null);
long thresholdInBytes = in.readLong();
DataUsageRequest result = new DataUsageRequest(requestId, template,
thresholdInBytes);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java
index 03bb187f119f..575c5ed968f8 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecConfig.java
@@ -267,14 +267,14 @@ public final class IpSecConfig implements Parcelable {
mMode = in.readInt();
mSourceAddress = in.readString();
mDestinationAddress = in.readString();
- mNetwork = (Network) in.readParcelable(Network.class.getClassLoader(), android.net.Network.class);
+ mNetwork = (Network) in.readParcelable(Network.class.getClassLoader());
mSpiResourceId = in.readInt();
mEncryption =
- (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader(), android.net.IpSecAlgorithm.class);
+ (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
mAuthentication =
- (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader(), android.net.IpSecAlgorithm.class);
+ (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
mAuthenticatedEncryption =
- (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader(), android.net.IpSecAlgorithm.class);
+ (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
mEncapType = in.readInt();
mEncapSocketResourceId = in.readInt();
mEncapRemotePort = in.readInt();
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java
index 390af8236696..732cf198a9cc 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecUdpEncapResponse.java
@@ -81,7 +81,7 @@ public final class IpSecUdpEncapResponse implements Parcelable {
status = in.readInt();
resourceId = in.readInt();
port = in.readInt();
- fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader(), android.os.ParcelFileDescriptor.class);
+ fileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
}
@android.annotation.NonNull
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
index d577aa8fba54..39156343924d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStateSnapshot.java
@@ -73,9 +73,9 @@ public final class NetworkStateSnapshot implements Parcelable {
/** @hide */
public NetworkStateSnapshot(@NonNull Parcel in) {
- mNetwork = in.readParcelable(null, android.net.Network.class);
- mNetworkCapabilities = in.readParcelable(null, android.net.NetworkCapabilities.class);
- mLinkProperties = in.readParcelable(null, android.net.LinkProperties.class);
+ mNetwork = in.readParcelable(null);
+ mNetworkCapabilities = in.readParcelable(null);
+ mLinkProperties = in.readParcelable(null);
mSubscriberId = in.readString();
mLegacyType = in.readInt();
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java
index 7ab53b1da856..33f9375c03bf 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/UnderlyingNetworkInfo.java
@@ -60,7 +60,7 @@ public final class UnderlyingNetworkInfo implements Parcelable {
mOwnerUid = in.readInt();
mIface = in.readString();
List<String> underlyingIfaces = new ArrayList<>();
- in.readList(underlyingIfaces, null /*classLoader*/, java.lang.String.class);
+ in.readList(underlyingIfaces, null /*classLoader*/);
mUnderlyingIfaces = Collections.unmodifiableList(underlyingIfaces);
}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
index 97281ed42452..74f31563055d 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
@@ -44,6 +44,7 @@ import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.TrafficStats.KB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.net.TrafficStats.UID_TETHERING;
import static android.net.TrafficStats.UNSUPPORTED;
import static android.os.Trace.TRACE_TAG_NETWORK;
import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
@@ -70,7 +71,7 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport;
-import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
+import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
@@ -89,7 +90,6 @@ import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.DataUsageRequest;
import android.net.INetd;
-import android.net.INetworkManagementEventObserver;
import android.net.INetworkStatsService;
import android.net.INetworkStatsSession;
import android.net.Network;
@@ -106,6 +106,7 @@ import android.net.NetworkStatsCollection;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TelephonyNetworkSpecifier;
+import android.net.TetherStatsParcel;
import android.net.TetheringManager;
import android.net.TrafficStats;
import android.net.UnderlyingNetworkInfo;
@@ -120,12 +121,12 @@ import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
@@ -148,6 +149,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FileRotator;
+import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.BestClock;
import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.CollectionUtils;
@@ -208,7 +210,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private static final String TAG_NETSTATS_ERROR = "netstats_error";
private final Context mContext;
- private final INetworkManagementService mNetworkManager;
private final NetworkStatsFactory mStatsFactory;
private final AlarmManager mAlarmManager;
private final Clock mClock;
@@ -223,6 +224,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final ContentObserver mContentObserver;
private final ContentResolver mContentResolver;
+ protected INetd mNetd;
+ private final AlertObserver mAlertObserver = new AlertObserver();
+
@VisibleForTesting
public static final String ACTION_NETWORK_STATS_POLL =
"com.android.server.action.NETWORK_STATS_POLL";
@@ -405,15 +409,16 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
- public static NetworkStatsService create(Context context,
- INetworkManagementService networkManager) {
+ /** Creates a new NetworkStatsService */
+ public static NetworkStatsService create(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock =
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
final INetd netd = INetd.Stub.asInterface(
(IBinder) context.getSystemService(Context.NETD_SERVICE));
- final NetworkStatsService service = new NetworkStatsService(context, networkManager,
+ final NetworkStatsService service = new NetworkStatsService(context,
+ INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
alarmManager, wakeLock, getDefaultClock(),
new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(netd),
new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(),
@@ -426,14 +431,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// This must not be called outside of tests, even within the same package, as this constructor
// does not register the local service. Use the create() helper above.
@VisibleForTesting
- NetworkStatsService(Context context, INetworkManagementService networkManager,
- AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
- NetworkStatsSettings settings, NetworkStatsFactory factory,
- NetworkStatsObservers statsObservers, File systemDir, File baseDir,
- @NonNull Dependencies deps) {
+ NetworkStatsService(Context context, INetd netd, AlarmManager alarmManager,
+ PowerManager.WakeLock wakeLock, Clock clock, NetworkStatsSettings settings,
+ NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir,
+ File baseDir, @NonNull Dependencies deps) {
mContext = Objects.requireNonNull(context, "missing Context");
- mNetworkManager = Objects.requireNonNull(networkManager,
- "missing INetworkManagementService");
+ mNetd = Objects.requireNonNull(netd, "missing Netd");
mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
mClock = Objects.requireNonNull(clock, "missing Clock");
mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
@@ -506,6 +509,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
new NetworkStatsManagerInternalImpl());
}
+ /**
+ * Observer that watches for {@link INetdUnsolicitedEventListener} alerts.
+ */
+ @VisibleForTesting
+ public class AlertObserver extends BaseNetdUnsolicitedEventListener {
+ @Override
+ public void onQuotaLimitReached(@NonNull String alertName, @NonNull String ifName) {
+ PermissionUtils.enforceNetworkStackPermission(mContext);
+
+ if (LIMIT_GLOBAL_ALERT.equals(alertName)) {
+ // kick off background poll to collect network stats unless there is already
+ // such a call pending; UID stats are handled during normal polling interval.
+ if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
+ mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
+ mSettings.getPollDelay());
+ }
+ }
+ }
+ }
+
public void systemReady() {
synchronized (mStatsLock) {
mSystemReady = true;
@@ -551,9 +574,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
try {
- mNetworkManager.registerObserver(mAlertObserver);
- } catch (RemoteException e) {
- // ignored; service lives in system_server
+ mNetd.registerUnsolicitedEventListener(mAlertObserver);
+ } catch (RemoteException | ServiceSpecificException e) {
+ Log.wtf(TAG, "Error registering event listener :", e);
}
// schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}.
@@ -641,13 +664,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
/**
- * Register for a global alert that is delivered through {@link INetworkManagementEventObserver}
+ * Register for a global alert that is delivered through {@link AlertObserver}
* or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has
* been transferred.
*/
private void registerGlobalAlert() {
try {
- mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
+ mNetd.bandwidthSetGlobalAlert(mGlobalAlertBytes);
} catch (IllegalStateException e) {
Log.w(TAG, "problem registering for global alert: " + e);
} catch (RemoteException e) {
@@ -922,6 +945,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
+ enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
try {
final String[] ifacesToQuery =
mStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
@@ -1226,26 +1250,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
};
/**
- * Observer that watches for {@link INetworkManagementService} alerts.
- */
- private final INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
- @Override
- public void limitReached(String limitName, String iface) {
- // only someone like NMS should be calling us
- PermissionUtils.enforceNetworkStackPermission(mContext);
-
- if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
- // kick off background poll to collect network stats unless there is already
- // such a call pending; UID stats are handled during normal polling interval.
- if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
- mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
- mSettings.getPollDelay());
- }
- }
- }
- };
-
- /**
* Handle collapsed RAT type changed event.
*/
@VisibleForTesting
@@ -1956,13 +1960,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
*/
// TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded
// tethering stats.
- private NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
+ private @NonNull NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
+ // We only need to return per-UID stats. Per-device stats are already counted by
+ // interface counters.
+ if (how != STATS_PER_UID) {
+ return new NetworkStats(SystemClock.elapsedRealtime(), 0);
+ }
+
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
try {
- return mNetworkManager.getNetworkStatsTethering(how);
+ final TetherStatsParcel[] tetherStatsParcels = mNetd.tetherGetStats();
+ for (TetherStatsParcel tetherStats : tetherStatsParcels) {
+ try {
+ stats.combineValues(new NetworkStats.Entry(tetherStats.iface, UID_TETHERING,
+ SET_DEFAULT, TAG_NONE, tetherStats.rxBytes, tetherStats.rxPackets,
+ tetherStats.txBytes, tetherStats.txPackets, 0L));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalStateException("invalid tethering stats " + e);
+ }
+ }
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e);
- return new NetworkStats(0L, 10);
}
+ return stats;
}
// TODO: It is copied from ConnectivityService, consider refactor these check permission
@@ -2044,7 +2064,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@NonNull final INetworkStatsProvider mProvider;
@NonNull private final Semaphore mSemaphore;
- @NonNull final INetworkManagementEventObserver mAlertObserver;
+ @NonNull final AlertObserver mAlertObserver;
@NonNull final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList;
@NonNull private final Object mProviderStatsLock = new Object();
@@ -2058,7 +2078,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
NetworkStatsProviderCallbackImpl(
@NonNull String tag, @NonNull INetworkStatsProvider provider,
@NonNull Semaphore semaphore,
- @NonNull INetworkManagementEventObserver alertObserver,
+ @NonNull AlertObserver alertObserver,
@NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList)
throws RemoteException {
mTag = tag;
@@ -2106,7 +2126,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// This binder object can only have been obtained by a process that holds
// NETWORK_STATS_PROVIDER. Thus, no additional permission check is required.
BinderUtils.withCleanCallingIdentity(() ->
- mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
+ mAlertObserver.onQuotaLimitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
}
@Override
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index 6df6de32da7a..4875f1cf5aaa 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -18,14 +18,16 @@ package com.android.server.net;
import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA;
import static android.net.NetworkTemplate.getCollapsedRatType;
+import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED;
+import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
import android.annotation.NonNull;
import android.content.Context;
import android.telephony.Annotation;
-import android.telephony.NetworkRegistrationInfo;
-import android.telephony.PhoneStateListener;
-import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -63,7 +65,7 @@ public class NetworkStatsSubscriptionsMonitor extends
private final Delegate mDelegate;
/**
- * Receivers that watches for {@link ServiceState} changes for each subscription, to
+ * Receivers that watches for {@link TelephonyDisplayInfo} changes for each subscription, to
* monitor the transitioning between Radio Access Technology(RAT) types for each sub.
*/
@NonNull
@@ -115,13 +117,12 @@ public class NetworkStatsSubscriptionsMonitor extends
continue;
}
- final RatTypeListener listener =
- new RatTypeListener(mExecutor, this, sub.first, sub.second);
+ final RatTypeListener listener = new RatTypeListener(this, sub.first, sub.second);
mRatListeners.add(listener);
// Register listener to the telephony manager that associated with specific sub.
mTeleManager.createForSubscriptionId(sub.first)
- .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
+ .registerTelephonyCallback(mExecutor, listener);
Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + sub.first);
}
@@ -175,7 +176,7 @@ public class NetworkStatsSubscriptionsMonitor extends
private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) {
mTeleManager.createForSubscriptionId(listener.mSubId)
- .listen(listener, PhoneStateListener.LISTEN_NONE);
+ .unregisterTelephonyCallback(listener);
Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId);
mRatListeners.remove(listener);
@@ -185,7 +186,8 @@ public class NetworkStatsSubscriptionsMonitor extends
listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN);
}
- static class RatTypeListener extends PhoneStateListener {
+ static class RatTypeListener extends TelephonyCallback
+ implements TelephonyCallback.DisplayInfoListener {
// Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}.
@NonNull
private final int mSubId;
@@ -199,29 +201,27 @@ public class NetworkStatsSubscriptionsMonitor extends
@NonNull
private final NetworkStatsSubscriptionsMonitor mMonitor;
- RatTypeListener(@NonNull Executor executor,
- @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId,
+ RatTypeListener(@NonNull NetworkStatsSubscriptionsMonitor monitor, int subId,
@NonNull String subscriberId) {
- super(executor);
mSubId = subId;
mSubscriberId = subscriberId;
mMonitor = monitor;
}
@Override
- public void onServiceStateChanged(@NonNull ServiceState ss) {
+ public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) {
// In 5G SA (Stand Alone) mode, the primary cell itself will be 5G hence telephony
// would report RAT = 5G_NR.
// However, in 5G NSA (Non Stand Alone) mode, the primary cell is still LTE and
// network allocates a secondary 5G cell so telephony reports RAT = LTE along with
// NR state as connected. In such case, attributes the data usage to NR.
// See b/160727498.
- final boolean is5GNsa = (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE
- || ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA)
- && ss.getNrState() == NetworkRegistrationInfo.NR_STATE_CONNECTED;
+ final boolean is5GNsa = displayInfo.getNetworkType() == NETWORK_TYPE_LTE
+ && (displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_NSA
+ || displayInfo.getOverrideNetworkType() == OVERRIDE_NETWORK_TYPE_NR_ADVANCED);
final int networkType =
- (is5GNsa ? NETWORK_TYPE_5G_NSA : ss.getDataNetworkType());
+ (is5GNsa ? NETWORK_TYPE_5G_NSA : displayInfo.getNetworkType());
final int collapsedRatType = getCollapsedRatType(networkType);
if (collapsedRatType == mLastCollapsedRatType) return;
diff --git a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
index c20690342c19..3f2b8ac7609d 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-night-v31/colors.xml
@@ -43,4 +43,8 @@
<color name="settingslib_accent_primary_variant">@android:color/system_accent1_300</color>
<color name="settingslib_text_color_primary_device_default">@android:color/system_neutral1_50</color>
+
+ <color name="settingslib_text_color_secondary_device_default">@android:color/system_neutral2_200</color>
+
+ <color name="settingslib_text_color_preference_category_title">@android:color/system_accent1_100</color>
</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
index 04010985fe74..ec3c336eba46 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/colors.xml
@@ -65,4 +65,8 @@
<color name="settingslib_background_device_default_light">@android:color/system_neutral1_50</color>
<color name="settingslib_text_color_primary_device_default">@android:color/system_neutral1_900</color>
+
+ <color name="settingslib_text_color_secondary_device_default">@android:color/system_neutral2_700</color>
+
+ <color name="settingslib_text_color_preference_category_title">@android:color/system_accent1_600</color>
</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml
index 1c33f1a57ea5..11546c8ed3d9 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/dimens.xml
@@ -20,4 +20,9 @@
<dimen name="app_icon_min_width">52dp</dimen>
<dimen name="settingslib_preferred_minimum_touch_target">48dp</dimen>
<dimen name="settingslib_dialogCornerRadius">28dp</dimen>
+
+ <!-- Left padding of the preference -->
+ <dimen name="settingslib_listPreferredItemPaddingStart">24dp</dimen>
+ <!-- Right padding of the preference -->
+ <dimen name="settingslib_listPreferredItemPaddingEnd">24dp</dimen>
</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
index 58006369988e..8e7226b0eb53 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml
@@ -17,13 +17,19 @@
<resources>
<style name="TextAppearance.PreferenceTitle.SettingsLib"
parent="@android:style/TextAppearance.Material.Subhead">
+ <item name="android:textColor">@color/settingslib_text_color_primary_device_default</item>
<item name="android:fontFamily">@string/settingslib_config_headlineFontFamily</item>
<item name="android:textSize">20sp</item>
</style>
+ <style name="TextAppearance.PreferenceSummary.SettingsLib"
+ parent="@android:style/TextAppearance.DeviceDefault.Small">
+ <item name="android:textColor">@color/settingslib_text_color_secondary_device_default</item>
+ </style>
+
<style name="TextAppearance.CategoryTitle.SettingsLib"
parent="@android:style/TextAppearance.DeviceDefault.Medium">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textColor">@color/settingslib_text_color_preference_category_title</item>
<item name="android:textSize">14sp</item>
</style>
diff --git a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml
index 6bf288b74d5a..7bf75bcc8a53 100644
--- a/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values-v31/themes.xml
@@ -19,8 +19,8 @@
<!-- Only using in Settings application -->
<style name="Theme.SettingsBase" parent="@android:style/Theme.DeviceDefault.Settings" >
<item name="android:textAppearanceListItem">@style/TextAppearance.PreferenceTitle.SettingsLib</item>
- <item name="android:listPreferredItemPaddingStart">24dp</item>
- <item name="android:listPreferredItemPaddingLeft">24dp</item>
+ <item name="android:listPreferredItemPaddingStart">@dimen/settingslib_listPreferredItemPaddingStart</item>
+ <item name="android:listPreferredItemPaddingLeft">@dimen/settingslib_listPreferredItemPaddingStart</item>
<item name="android:listPreferredItemPaddingEnd">16dp</item>
<item name="android:listPreferredItemPaddingRight">16dp</item>
<item name="preferenceTheme">@style/PreferenceTheme.SettingsLib</item>
diff --git a/packages/SettingsLib/SettingsTheme/res/values/config.xml b/packages/SettingsLib/SettingsTheme/res/values/config.xml
new file mode 100644
index 000000000000..e73dcc0cc559
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/values/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <bool name="settingslib_config_icon_space_reserved">true</bool>
+</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/SettingsTheme/res/values/dimens.xml b/packages/SettingsLib/SettingsTheme/res/values/dimens.xml
index 18af1f9c15d0..f7e01444f4d4 100644
--- a/packages/SettingsLib/SettingsTheme/res/values/dimens.xml
+++ b/packages/SettingsLib/SettingsTheme/res/values/dimens.xml
@@ -21,4 +21,11 @@
<dimen name="app_icon_min_width">56dp</dimen>
<dimen name="two_target_min_width">72dp</dimen>
<dimen name="settingslib_dialogCornerRadius">8dp</dimen>
+
+ <!-- Left padding of the preference -->
+ <dimen name="settingslib_listPreferredItemPaddingStart">16dp</dimen>
+ <!-- Right padding of the preference -->
+ <dimen name="settingslib_listPreferredItemPaddingEnd">16dp</dimen>
+ <!-- Icon size of the preference -->
+ <dimen name="settingslib_preferenceIconSize">24dp</dimen>
</resources>
diff --git a/packages/SettingsLib/SettingsTheme/res/values/styles.xml b/packages/SettingsLib/SettingsTheme/res/values/styles.xml
new file mode 100644
index 000000000000..aaab0f041fe3
--- /dev/null
+++ b/packages/SettingsLib/SettingsTheme/res/values/styles.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <style name="TextAppearance.PreferenceTitle.SettingsLib"
+ parent="@android:style/TextAppearance.Material.Subhead">
+ </style>
+
+ <style name="TextAppearance.PreferenceSummary.SettingsLib"
+ parent="@style/PreferenceSummaryTextStyle">
+ </style>
+
+ <style name="TextAppearance.CategoryTitle.SettingsLib"
+ parent="@android:style/TextAppearance.DeviceDefault.Medium">
+ </style>
+</resources>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index f3fb48fdfe54..13a5cafc53e4 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vra elke keer"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Totdat jy dit afskakel"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Sopas"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Foonluidspreker"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Hierdie foon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Hierdie foon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kan nie koppel nie. Skakel toestel af en weer aan"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedrade oudiotoestel"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 647d0528b052..7ad455ae3e67 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ሁልጊዜ ጠይቅ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"እስኪያጠፉት ድረስ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ልክ አሁን"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"የስልክ ድምጽ ማጉያ"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ይህ ስልክ"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ይህ ስልክ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"መገናኘት ላይ ችግር። መሳሪያውን ያጥፉት እና እንደገና ያብሩት"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ባለገመድ የኦዲዮ መሣሪያ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 6357f3c0ac2e..a4646f16bd6e 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -556,7 +556,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"السؤال في كل مرة"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"إلى أن يتم إيقاف الوضع"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"للتو"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"مكبر صوت الهاتف"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"هذا الهاتف"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"هذا الهاتف"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index cb74e1f36ff4..c304921f48d7 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"প্ৰতিবাৰতে সোধক"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"আপুনি অফ নকৰা পর্যন্ত"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"এই মাত্ৰ"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ফ’নৰ স্পীকাৰ"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"এই ফ’নটো"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফ’নটো"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"সংযোগ হোৱাত সমস্যা হৈছে। ডিভাইচটো অফ কৰি পুনৰ অন কৰক"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"তাঁৰযুক্ত অডিঅ’ ডিভাইচ"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 979c957fb9d4..6e3947e56b4a 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Həmişə soruşulsun"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Deaktiv edilənə qədər"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"İndicə"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon dinamiki"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Bu telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Qoşulmaqla bağlı problem. Cihazı deaktiv edin, sonra yenidən aktiv edin"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio cihaz"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 5af3006f12d6..a05dae9cfc4c 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -553,7 +553,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pitaj svaki put"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvučnik telefona"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ovaj telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem pri povezivanju. Isključite uređaj, pa ga ponovo uključite"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index d1b6226f40a0..e3b05677bea4 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Заўсёды пытацца"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Пакуль не выключыце"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Толькі што"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Дынамік тэлефона"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Гэты тэлефон"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Гэты тэлефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Праблема з падключэннем. Выключыце і зноў уключыце прыладу"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Правадная аўдыяпрылада"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 375879a881b7..a8eaaf0d4c0b 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Да се пита винаги"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"До изключване"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Току-що"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Високоговорител"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Този телефон"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Този телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"При свързването възникна проблем. Изключете устройството и го включете отново"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Аудиоустройство с кабел"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 89fcbd3ec640..c28e92708542 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"প্রতিবার জিজ্ঞেস করা হবে"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"যতক্ষণ না আপনি বন্ধ করছেন"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"এখনই"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ফোনের স্পিকার"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"এই ফোন"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"এই ফোনটি"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"কানেক্ট করতে সমস্যা হচ্ছে। ডিভাইস বন্ধ করে আবার চালু করুন"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ওয়্যার অডিও ডিভাইস"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index e33978ff27f1..232c22fd939d 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -553,7 +553,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pitaj svaki put"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Upravo"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvučnik telefona"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ovaj telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Došlo je do problema prilikom povezivanja. Isključite, pa ponovo uključite uređaj"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audio uređaj"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 2b10a30dd786..bc393c361392 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pregunta sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Fins que no el desactivis"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Ara mateix"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altaveu del telèfon"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Aquest telèfon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Aquest telèfon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Hi ha hagut un problema amb la connexió. Apaga el dispositiu i torna\'l a encendre."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositiu d\'àudio amb cable"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 7a94bb433c96..f7583659c87f 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pokaždé se zeptat"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dokud funkci nevypnete"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Právě teď"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Reproduktor telefonu"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Tento telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problém s připojením. Vypněte zařízení a znovu jej zapněte"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kabelové audiozařízení"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index ff5c6aed660c..0fd2569881a6 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Spørg hver gang"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Indtil du deaktiverer"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Lige nu"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonens højttaler"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Denne telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Der kunne ikke oprettes forbindelse. Sluk og tænd enheden"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhed med ledning"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index defc22312ab4..f75685b711df 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Jedes Mal fragen"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Bis zur Deaktivierung"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Gerade eben"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Smartphone-Lautsprecher"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Dieses Smartphone"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Dieses Smartphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Verbindung kann nicht hergestellt werden. Schalte das Gerät aus &amp; und wieder ein."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Netzbetriebenes Audiogerät"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 402e4897fab9..51157289b82a 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Να ερωτώμαι κάθε φορά"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Μέχρι την απενεργοποίηση"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Μόλις τώρα"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Ηχείο τηλεφώνου"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Αυτό το τηλέφωνο"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Αυτό το τηλέφωνο"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Πρόβλημα κατά τη σύνδεση. Απενεργοποιήστε τη συσκευή και ενεργοποιήστε την ξανά"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ενσύρματη συσκευή ήχου"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index fb3bc7a335ae..1481ceec7f2b 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ask every time"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"This phone"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index e33af37626c3..b3dd58a1636b 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ask every time"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"This phone"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index fb3bc7a335ae..1481ceec7f2b 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ask every time"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"This phone"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index fb3bc7a335ae..1481ceec7f2b 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ask every time"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Just now"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Phone speaker"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"This phone"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"This phone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem connecting. Turn device off and back on"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired audio device"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 2c58236be394..2a6c82cbc28d 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎Ask every time‎‏‎‎‏‎"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‏‏‎Until you turn off‎‏‎‎‏‎"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎Just now‎‏‎‎‏‎"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‎‎‎Phone speaker‎‏‎‎‏‎"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‎‏‎This phone‎‏‎‎‏‎"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‏‏‏‎‏‎‏‏‎This phone‎‏‎‎‏‎"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‏‎Problem connecting. Turn device off &amp; back on‎‏‎‎‏‎"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎Wired audio device‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 471e71509847..ee0e0bcb8dd8 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -219,7 +219,7 @@
<item msgid="3075292553049300105">"Normal"</item>
<item msgid="1158955023692670059">"Ligera"</item>
<item msgid="5664310435707146591">"Muy ligera"</item>
- <item msgid="5491266922147715962">"A velocidad muy alta"</item>
+ <item msgid="5491266922147715962">"Muy rápida"</item>
<item msgid="7659240015901486196">"Rápida"</item>
<item msgid="7147051179282410945">"Muy rápida"</item>
<item msgid="581904787661470707">"A velocidad máxima"</item>
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Preguntar siempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Hasta que lo desactives"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Recién"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altavoz del teléfono"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este teléfono"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Error al establecer la conexión. Apaga el dispositivo y vuelve a encenderlo."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index bd687e467dba..1f64bad6c45f 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Preguntar siempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Hasta que lo desactives"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"justo ahora"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altavoz del teléfono"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este teléfono"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"No se ha podido conectar; reinicia el dispositivo"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index aaf320122419..ed7b9dc161c0 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Küsi iga kord"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Kuni välja lülitate"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Äsja"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefoni kõlar"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"See telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"See telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem ühendamisel. Lülitage seade välja ja uuesti sisse"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Juhtmega heliseade"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 0f929de91fce..4cdcca7dd389 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -552,9 +552,9 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Galdetu beti"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Zuk desaktibatu arte"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Oraintxe"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonoaren bozgorailua"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Telefono hau"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefono hau"</string>
- <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Arazoren bat izan da konektatzean. Itzali gailua eta pitz ezazu berriro."</string>
+ <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Arazo bat izan da konektatzean. Itzali gailua eta pitz ezazu berriro."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio-gailu kableduna"</string>
<string name="help_label" msgid="3528360748637781274">"Laguntza eta iritziak"</string>
<string name="storage_category" msgid="2287342585424631813">"Biltegiratzea"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 3dce25d3ff7e..1b5f9790633f 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"هربار پرسیده شود"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"تا زمانی‌که آن را خاموش کنید"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"هم‌اکنون"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"بلندگوی تلفن"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"این تلفن"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"این تلفن"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"مشکل در اتصال. دستگاه را خاموش و دوباره روشن کنید"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"دستگاه صوتی سیمی"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 373f6a4f2742..9490ede09ff8 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Kysy aina"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Kunnes laitat pois päältä"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Äsken"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Puhelimen kaiutin"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Tämä puhelin"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Tämä puhelin"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Yhteysvirhe. Sammuta laite ja käynnistä se uudelleen."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Langallinen äänilaite"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index ebaf4b1747a7..ab36e11e03cb 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Toujours demander"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Jusqu\'à la désactivation"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Haut-parleur du téléphone"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ce téléphone"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteingez et rallumez l\'appareil"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio à câble"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 5f635b0a98a9..35f2fcee3de4 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Toujours demander"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Jusqu\'à la désactivation"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"À l\'instant"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Haut-parleur du téléphone"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ce téléphone"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ce téléphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problème de connexion. Éteignez l\'appareil, puis rallumez-le"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Appareil audio filaire"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index cb33a5152961..8d23864d354a 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Preguntar sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Ata a desactivación"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altofalante do teléfono"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este teléfono"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este teléfono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Produciuse un problema coa conexión. Apaga e acende o dispositivo."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de audio con cable"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 79ca4ab52ca8..ac38a64ffcf9 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"દર વખતે પૂછો"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"તમે બંધ ન કરો ત્યાં સુધી"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"હમણાં જ"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ફોન સ્પીકર"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"આ ફોન"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"આ ફોન"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"કનેક્ટ કરવામાં સમસ્યા આવી રહી છે. ડિવાઇસને બંધ કરીને ફરી ચાલુ કરો"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"વાયરવાળો ઑડિયો ડિવાઇસ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index fcf04bc48133..5c008f0bb50f 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"हर बार पूछें"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"जब तक आप इसे बंद नहीं करते"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"अभी-अभी"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"फ़ोन का स्पीकर"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"यह फ़ोन"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"यह फ़ोन"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्ट करने में समस्या हो रही है. डिवाइस को बंद करके चालू करें"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर वाला ऑडियो डिवाइस"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 1ef94fb0981e..d681a1edfbdc 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -553,7 +553,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pitaj svaki put"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Upravo sad"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvučnik telefona"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ovaj telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ovaj telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem s povezivanjem. Isključite i ponovo uključite uređaj"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žičani audiouređaj"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index deb0f81bc5da..57894a0c6377 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Mindig kérdezzen rá"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Kikapcsolásig"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Az imént"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon hangszórója"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ez a telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ez a telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sikertelen csatlakozás. Kapcsolja ki az eszközt, majd kapcsolja be újra."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vezetékes audioeszköz"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 485af5490567..e6ed2b00ee6a 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ամեն անգամ հարցնել"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Մինչև անջատեք"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Հենց նոր"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Հեռախոսի բարձրախոս"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Այս հեռախոսը"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Այս հեռախոսը"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Կապի խնդիր կա: Սարքն անջատեք և նորից միացրեք:"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Լարով աուդիո սարք"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index f82798a4f0e1..6fbab2b8a3df 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Selalu tanya"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Sampai Anda menonaktifkannya"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Baru saja"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Speaker ponsel"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ponsel ini"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ponsel ini"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ada masalah saat menghubungkan. Nonaktifkan perangkat &amp; aktifkan kembali"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Perangkat audio berkabel"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index a43eb14cf063..fa11dfb25649 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Spyrja í hvert skipti"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Þar til þú slekkur"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Rétt í þessu"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Símahátalari"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Þessi sími"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Þessi sími"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Vandamál í tengingu. Slökktu og kveiktu á tækinu"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Snúrutengt hljómtæki"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 0a96f59c8a8a..0db0448d3140 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Chiedi ogni volta"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Fino alla disattivazione"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Adesso"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altoparlante telefono"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Questo telefono"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Questo telefono"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema di connessione. Spegni e riaccendi il dispositivo"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo audio cablato"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 6f3cfb99dc54..7ac591916858 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"יש לשאול בכל פעם"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"עד הכיבוי"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"הרגע"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"הרמקול של הטלפון"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"הטלפון הזה"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"הטלפון הזה"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"יש בעיה בחיבור. עליך לכבות את המכשיר ולהפעיל אותו מחדש"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"התקן אודיו חוטי"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 620aca6edb4d..d82ca5d976bd 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"毎回確認"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"OFF にするまで"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"たった今"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"スマートフォンのスピーカー"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"このスマートフォン"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"このスマートフォン"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"接続エラーです。デバイスを OFF にしてから ON に戻してください"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線オーディオ デバイス"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index daa0faef6046..02c1084a2bd1 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ყოველთვის მკითხეთ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"გამორთვამდე"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ახლახან"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ტელეფონის დინამიკი"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ეს ტელეფონი"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ეს ტელეფონი"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"დაკავშირებისას წარმოიქმნა პრობლემა. გამორთეთ და კვლავ ჩართეთ მოწყობილობა"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"სადენიანი აუდიო მოწყობილობა"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 6305891ea839..6c55b62b19a7 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Әрдайым сұрау"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Өшірілгенге дейін"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Дәл қазір"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Телефон динамигі"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Осы телефон"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Осы телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Байланыс орнату қатесі шығуып жатыр. Құрылғыны өшіріп, қайта қосыңыз."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Сымды аудио құрылғысы"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index fb00aa0bb425..58a2c7cf9e46 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"សួរគ្រប់ពេល"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"រហូតទាល់តែ​អ្នកបិទ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"អម្បាញ់មិញ"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ឧបករណ៍​បំពង​សំឡេង​ទូរសព្ទ"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ទូរសព្ទនេះ"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ទូរសព្ទនេះ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"មាន​បញ្ហា​ក្នុងការ​ភ្ជាប់។ បិទ រួច​បើក​ឧបករណ៍​វិញ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ឧបករណ៍​សំឡេងប្រើខ្សែ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index a1f0825d1e16..91e76e2de3d2 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ಪ್ರತಿ ಬಾರಿ ಕೇಳಿ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೆ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ಇದೀಗ"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ಫೋನ್ ಸ್ಪೀಕರ್"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ಈ ಫೋನ್"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ಈ ಫೋನ್"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ಕನೆಕ್ಟ್ ಮಾಡುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ ಸಾಧನವನ್ನು ಆಫ್ ಮಾಡಿ ಹಾಗೂ ನಂತರ ಪುನಃ ಆನ್ ಮಾಡಿ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ವೈರ್ ಹೊಂದಿರುವ ಆಡಿಯೋ ಸಾಧನ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 1ff18c636876..d47056062085 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"항상 확인"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"사용 중지할 때까지"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"조금 전"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"휴대전화 스피커"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"이 휴대전화"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"이 휴대전화"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"연결 중에 문제가 발생했습니다. 기기를 껐다가 다시 켜 보세요."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"유선 오디오 기기"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 58e31071c5d6..e38bb51a3c44 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Ар дайым суралсын"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Бул функция өчүрүлгөнгө чейин"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Жаңы эле"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Телефондун динамиги"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ушул телефон"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ушул телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Туташууда маселе келип чыкты. Түзмөктү өчүрүп, кайра күйгүзүп көрүңүз"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Зымдуу аудио түзмөк"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index a2b8c6ba5b22..cc0229241527 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ຖາມທຸກເທື່ອ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ຈົນກວ່າທ່ານຈະປິດ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ຕອນນີ້"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ລຳໂພງໂທລະສັບ"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ໂທລະສັບນີ້"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ໂທລະສັບນີ້"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ເກີດບັນຫາໃນການເຊື່ອມຕໍ່. ປິດອຸປະກອນແລ້ວເປີດກັບຄືນມາໃໝ່"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ອຸປະກອນສຽງແບບມີສາຍ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index d8c1a45192ce..fb645a09aa37 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Klausti kaskart"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Kol išjungsite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Ką tik"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefono garsiakalbis"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Šis telefonas"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis telefonas"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Prisijungiant kilo problema. Išjunkite įrenginį ir vėl jį įjunkite"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Laidinis garso įrenginys"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 9ac8c656c5d0..694ff0a52eb8 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -553,7 +553,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vaicāt katru reizi"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Līdz brīdim, kad izslēgsiet"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Tikko"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Tālruņa skaļrunis"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Šis tālrunis"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Šis tālrunis"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Radās problēma ar savienojuma izveidi. Izslēdziet un atkal ieslēdziet ierīci."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Vadu audioierīce"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index c08fd246e959..9d412fcec67d 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Прашувај секогаш"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Додека не го исклучите"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Пред малку"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Телефонски звучник"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Овој телефон"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Овој телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем со поврзување. Исклучете го уредот и повторно вклучете го"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичен аудиоуред"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 27693e68f988..82df16c06c6f 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"എപ്പോഴും ചോദിക്കുക"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"നിങ്ങൾ ഓഫാക്കുന്നത് വരെ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ഇപ്പോൾ"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ഫോൺ സ്‌പീക്കർ"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ഈ ഫോൺ"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ഈ ഫോൺ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"കണക്‌റ്റ് ചെയ്യുന്നതിൽ പ്രശ്‌നമുണ്ടായി. ഉപകരണം ഓഫാക്കി വീണ്ടും ഓണാക്കുക"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"വയർ മുഖേന ബന്ധിപ്പിച്ച ഓഡിയോ ഉപകരണം"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index b62d103c7835..027b7227ef93 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Тухай бүрд асуух"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Таныг унтраах хүртэл"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Дөнгөж сая"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Утасны чанга яригч"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Энэ утас"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Энэ утас"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Холбогдоход асуудал гарлаа. Төхөөрөмжийг унтраагаад дахин асаана уу"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Утастай аудио төхөөрөмж"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index d90c08af1823..176d764dfe23 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"प्रत्येक वेळी विचारा"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"तुम्ही बंद करेपर्यंत"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"आत्ताच"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"फोनचा स्पीकर"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"हा फोन"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"हा फोन"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"कनेक्‍ट करण्‍यात समस्‍या आली. डिव्हाइस बंद करा आणि नंतर सुरू करा"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"वायर असलेले ऑडिओ डिव्हाइस"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 7011aec19665..6bf15fe25f77 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Tanya setiap kali"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Sehingga anda matikan"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Sebentar tadi"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Pembesar suara telefon"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Telefon ini"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Telefon ini"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Masalah penyambungan. Matikan &amp; hidupkan kembali peranti"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Peranti audio berwayar"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 3de8cf928383..13fc6adf55ba 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"အမြဲမေးရန်"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"သင်ပိတ်လိုက်သည် အထိ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ယခုလေးတင်"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ဖုန်းစပီကာ"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ဤဖုန်း"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ဤဖုန်း"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ချိတ်ဆက်ရာတွင် ပြဿနာရှိပါသည်။ စက်ကိုပိတ်ပြီး ပြန်ဖွင့်ပါ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ကြိုးတပ် အသံစက်ပစ္စည်း"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index e7f70d12beb3..c2e449b4850c 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Spør hver gang"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Til du slår av"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Nå nettopp"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonhøyttaler"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Denne telefonen"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Denne telefonen"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Tilkoblingsproblemer. Slå enheten av og på igjen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Lydenhet med kabel"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 8fc329f885d1..85860f0d80e1 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"प्रत्येक पटक सोधियोस्"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"तपाईंले अफ नगरेसम्म"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"अहिले भर्खरै"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"फोनको स्पिकर"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"यो फोन"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"यो फोन"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"जोड्ने क्रममा समस्या भयो। यन्त्रलाई निष्क्रिय पारेर फेरि सक्रिय गर्नुहोस्"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"तारयुक्त अडियो यन्त्र"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 35e651bfb626..2ffa559f4401 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -222,7 +222,7 @@
<item msgid="5491266922147715962">"Nog sneller"</item>
<item msgid="7659240015901486196">"Heel erg snel"</item>
<item msgid="7147051179282410945">"Snelst"</item>
- <item msgid="581904787661470707">"Allerallersnelst"</item>
+ <item msgid="581904787661470707">"Allersnelst"</item>
</string-array>
<string name="choose_profile" msgid="343803890897657450">"Profiel kiezen"</string>
<string name="category_personal" msgid="6236798763159385225">"Persoonlijk"</string>
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vraag altijd"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Totdat je uitzet"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Zojuist"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefoonspeaker"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Deze telefoon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Deze telefoon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Probleem bij verbinding maken. Zet het apparaat uit en weer aan."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Bedraad audioapparaat"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 49018be6c8d2..e2fee1399b25 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ପ୍ରତ୍ୟେକ ଥର ପଚାରନ୍ତୁ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ଆପଣ ବନ୍ଦ ନକରିବା ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ଏହିକ୍ଷଣି"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ଫୋନ୍ ସ୍ପିକର୍"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ଏହି ଫୋନ"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ଏହି ଫୋନ୍"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ସଂଯୋଗ କରିବାରେ ସମସ୍ୟା ହେଉଛି। ଡିଭାଇସ୍ ବନ୍ଦ କରି ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ତାରଯୁକ୍ତ ଅଡିଓ ଡିଭାଇସ୍"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 9efc4c4a4b8f..11cd481703f7 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ਹਰ ਵਾਰ ਪੁੱਛੋ"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਬੰਦ ਨਹੀਂ ਕਰਦੇ"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ਹੁਣੇ ਹੀ"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ਫ਼ੋਨ ਦਾ ਸਪੀਕਰ"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ਇਹ ਫ਼ੋਨ"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ਇਹ ਫ਼ੋਨ"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ। ਡੀਵਾਈਸ ਨੂੰ ਬੰਦ ਕਰਕੇ ਵਾਪਸ ਚਾਲੂ ਕਰੋ"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"ਤਾਰ ਵਾਲਾ ਆਡੀਓ ਡੀਵਾਈਸ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 1eb2dd9bffba..0c670bc7c8ae 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Zawsze pytaj"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dopóki nie wyłączysz"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Przed chwilą"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Głośnik telefonu"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ten telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ten telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem z połączeniem. Wyłącz i ponownie włącz urządzenie"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Przewodowe urządzenie audio"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 38d637f9e893..10568a116689 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Perguntar sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Até você desativar"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Alto-falante do smartphone"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este smartphone"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este smartphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 5a0ec2e36543..54582790ed10 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Perguntar sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Até desativar"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Agora mesmo"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altifalante do telemóvel"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este telemóvel"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este telemóvel"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problema ao ligar. Desligue e volte a ligar o dispositivo."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fios"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 38d637f9e893..10568a116689 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Perguntar sempre"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Até você desativar"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Agora"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Alto-falante do smartphone"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Este smartphone"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Este smartphone"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ocorreu um problema na conexão. Desligue o dispositivo e ligue-o novamente"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispositivo de áudio com fio"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index ce58f1c75cc2..00fc8ffdb34f 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -553,7 +553,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Întreabă de fiecare dată"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Până când dezactivați"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Chiar acum"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Difuzorul telefonului"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Acest telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Acest telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problemă la conectare. Opriți și reporniți dispozitivul."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Dispozitiv audio cu fir"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 14db2252f4dc..15e345619c63 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Всегда спрашивать"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Пока вы не отключите"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Только что"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Встроен. динамик"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Этот смартфон"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Этот смартфон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ошибка подключения. Выключите и снова включите устройство."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Проводное аудиоустройство"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 41f10c94b92d..d56dd34a99cc 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"සෑම විටම ඉල්ලන්න"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ඔබ ක්‍රියාවිරහිත කරන තුරු"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"මේ දැන්"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"දුරකථන ස්පීකරය"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"මෙම දුරකථනය"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"මෙම දුරකථනය"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"සම්බන්ධ කිරීමේ ගැටලුවකි උපාංගය ක්‍රියාවිරහිත කර &amp; ආපසු ක්‍රියාත්මක කරන්න"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"රැහැන්ගත කළ ඕඩියෝ උපාංගය"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 801c213f1e20..e7ea915aa49b 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vždy sa opýtať"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dokým funkciu nevypnete"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Teraz"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Reproduktor telefónu"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Tento telefón"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Tento telefón"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Pri pripájaní sa vyskytol problém. Zariadenie vypnite a znova zapnite."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Audio zariadenie s káblom"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index a33101899406..95a6fb929d59 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Vedno vprašaj"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Dokler ne izklopite"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Pravkar"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Zvočnik telefona"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ta telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ta telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Težava pri povezovanju. Napravo izklopite in znova vklopite."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Žična zvočna naprava"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index cb9bea8cf963..8524164aa78b 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Pyet çdo herë"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Derisa ta çaktivizosh"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Pikërisht tani"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Altoparlanti i telefonit"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ky telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ky telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Problem me lidhjen. Fike dhe ndize përsëri pajisjen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Pajisja audio me tel"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 9e9033341982..b19198aa24ee 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -553,7 +553,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Питај сваки пут"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Док не искључите"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Управо"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Звучник телефона"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Овај телефон"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Овај телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Проблем при повезивању. Искључите уређај, па га поново укључите"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Жичани аудио уређај"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 215d9ade4aab..59cde86f081e 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Fråga varje gång"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Tills du inaktiverar funktionen"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Nyss"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefonhögtalare"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Den här telefonen"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Den här telefonen"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Det gick inte att ansluta. Stäng av enheten och slå på den igen"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Ljudenhet med kabelanslutning"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index f51825b50320..64c2e071e5fc 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Uliza kila wakati"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Hadi utakapoizima"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Sasa hivi"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Spika ya simu"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Simu hii"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Simu hii"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Kuna tatizo la kuunganisha kwenye Intaneti. Zima kisha uwashe kifaa"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kifaa cha sauti kinachotumia waya"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 8128683c824a..ccef6b9682ad 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ஒவ்வொரு முறையும் கேள்"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"ஆஃப் செய்யும் வரை"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"சற்றுமுன்"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"மொபைல் ஸ்பீக்கர்"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"இந்த மொபைல்"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"இந்த மொபைல்"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"இணைப்பதில் சிக்கல். சாதனத்தை ஆஃப் செய்து மீண்டும் ஆன் செய்யவும்"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"வயருடன்கூடிய ஆடியோ சாதனம்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 298f850b7ecb..4013620565df 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ప్రతిసారి అడుగు"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"మీరు ఆఫ్‌ చేసే వరకు"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ఇప్పుడే"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ఫోన్ స్పీకర్"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"ఈ ఫోన్"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"ఈ ఫోన్"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"కనెక్ట్ చేయడంలో సమస్య ఉంది. పరికరాన్ని ఆఫ్ చేసి, ఆపై తిరిగి ఆన్ చేయండి"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"వైర్ గల ఆడియో పరికరం"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index e18c6492d845..c42295fbcdfd 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ถามทุกครั้ง"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"จนกว่าคุณจะปิด"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"เมื่อสักครู่"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"ลำโพงโทรศัพท์"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"โทรศัพท์เครื่องนี้"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"โทรศัพท์เครื่องนี้"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"เกิดปัญหาในการเชื่อมต่อ ปิดอุปกรณ์แล้วเปิดใหม่อีกครั้ง"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"อุปกรณ์เสียงแบบมีสาย"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 628bacc51189..ab36a556156f 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Magtanong palagi"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Hanggang sa i-off mo"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Ngayon lang"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Speaker ng telepono"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Ang teleponong ito"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Ang teleponong ito"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Nagkaproblema sa pagkonekta. I-off at pagkatapos ay i-on ang device"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Wired na audio device"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 3e30d4320bd2..ce71496d82e4 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Her zaman sor"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Siz kapatana kadar"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Az önce"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon hoparlörü"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Bu telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Bu telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Bağlanırken sorun oluştu. Cihazı kapatıp tekrar açın"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Kablolu ses cihazı"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 86839539abb7..b7d370d239f4 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -554,7 +554,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Запитувати щоразу"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Доки не вимкнути"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Щойно"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Динамік"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Цей телефон"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Цей телефон"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Не вдається підключитися. Перезавантажте пристрій."</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Дротовий аудіопристрій"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 09e50f62abc9..c3f4d56d84ce 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"ہر بار پوچھیں"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"یہاں تک کہ آپ آف کر دیں"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"ابھی ابھی"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"فون اسپیکر"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"یہ فون"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"یہ فون"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"منسلک کرنے میں مسئلہ پیش آ گیا۔ آلہ کو آف اور بیک آن کریں"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"وائرڈ آڈیو آلہ"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index d0b9506e79f7..aa3d8826dd22 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Har safar so‘ralsin"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Rejimdan chiqilgunicha"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Hozir"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Telefon karnayi"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Shu telefon"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Shu telefon"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Ulanishda muammo yuz berdi. Qurilmani oʻchiring va yoqing"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Simli audio qurilma"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index bd97cc5804ee..7291d061ddde 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Luôn hỏi"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Cho đến khi bạn tắt"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Vừa xong"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Loa điện thoại"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Điện thoại này"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Điện thoại này"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Sự cố kết nối. Hãy tắt thiết bị rồi bật lại"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Thiết bị âm thanh có dây"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 3ed18600682f..3f1b9ae581eb 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"每次都询问"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"直到您将其关闭"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"刚刚"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"手机扬声器"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"这部手机"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"这部手机"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"连接时遇到问题。请关闭并重新开启设备"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有线音频设备"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 965e78f5bbe4..c91a13f7f56b 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"每次都詢問"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"直至您關閉為止"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"手機喇叭"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"此手機"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"這部手機"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連接,請關閉裝置然後重新開機"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音響裝置"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index e3ca3444ad32..8b469ea2154d 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"每次都詢問"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"直到你關閉為止"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"剛剛"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"手機喇叭"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"這支手機"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"這支手機"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"無法連線,請關閉裝置後再重新開啟"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"有線音訊裝置"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 1af1fa112ae1..9eac12cedc2b 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -552,7 +552,7 @@
<string name="zen_mode_duration_always_prompt_title" msgid="3212996860498119555">"Buza njalo"</string>
<string name="zen_mode_forever" msgid="3339224497605461291">"Uze uvale isikrini"</string>
<string name="time_unit_just_now" msgid="3006134267292728099">"Khona manje"</string>
- <string name="media_transfer_this_device_name" msgid="2716555073132169240">"Isipikha sefoni"</string>
+ <string name="media_transfer_this_device_name" msgid="2357329267148436433">"Le foni"</string>
<string name="media_transfer_this_phone" msgid="7194341457812151531">"Le foni"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"Inkinga yokuxhumeka. Vala idivayisi futhi uphinde uyivule"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"Idivayisi yomsindo enentambo"</string>
diff --git a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
index de45ea536e27..d3fe4a7fcb9f 100644
--- a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
+++ b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
@@ -47,7 +47,7 @@ import javax.tools.Diagnostic.Kind;
* Annotation processor for {@link SearchIndexable} that generates {@link SearchIndexableResources}
* subclasses.
*/
-@SupportedSourceVersion(SourceVersion.RELEASE_8)
+@SupportedSourceVersion(SourceVersion.RELEASE_9)
@SupportedAnnotationTypes({"com.android.settingslib.search.SearchIndexable"})
public class IndexableProcessor extends AbstractProcessor {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 9dd329ed7cd7..b11bbdec191f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -138,13 +138,6 @@ public class HeadsetProfile implements LocalBluetoothProfile {
return mService.getActiveDevice();
}
- public boolean isAudioOn() {
- if (mService == null) {
- return false;
- }
- return mService.isAudioOn();
- }
-
public int getAudioState(BluetoothDevice device) {
if (mService == null) {
return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractConnectivityPreferenceController.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractConnectivityPreferenceController.java
index c6552f77a2b2..d3934bf131ba 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractConnectivityPreferenceController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/AbstractConnectivityPreferenceController.java
@@ -73,7 +73,8 @@ public abstract class AbstractConnectivityPreferenceController
}
mContext.registerReceiver(mConnectivityReceiver, connectivityIntentFilter,
- android.Manifest.permission.CHANGE_NETWORK_STATE, null);
+ android.Manifest.permission.CHANGE_NETWORK_STATE, null,
+ Context.RECEIVER_EXPORTED_UNAUDITED);
}
protected abstract String[] getConnectivityIntents();
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index 011ca0b38e5d..cff45c6be0e0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -16,8 +16,6 @@
package com.android.settingslib.net;
-import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
-import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.telephony.TelephonyManager.SIM_STATE_READY;
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
@@ -27,12 +25,9 @@ import android.app.usage.NetworkStats.Bucket;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate;
-import android.os.ServiceManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
@@ -51,25 +46,20 @@ public class DataUsageController {
private static final String TAG = "DataUsageController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final int FIELDS = FIELD_RX_BYTES | FIELD_TX_BYTES;
private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50);
private static final java.util.Formatter PERIOD_FORMATTER = new java.util.Formatter(
PERIOD_BUILDER, Locale.getDefault());
private final Context mContext;
- private final INetworkStatsService mStatsService;
private final NetworkPolicyManager mPolicyManager;
private final NetworkStatsManager mNetworkStatsManager;
- private INetworkStatsSession mSession;
private Callback mCallback;
private NetworkNameProvider mNetworkController;
private int mSubscriptionId;
public DataUsageController(Context context) {
mContext = context;
- mStatsService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
mPolicyManager = NetworkPolicyManager.from(mContext);
mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -112,8 +102,7 @@ public class DataUsageController {
}
public DataUsageInfo getWifiDataUsageInfo() {
- NetworkTemplate template = NetworkTemplate.buildTemplateWifi(
- NetworkTemplate.WIFI_NETWORKID_ALL, null);
+ NetworkTemplate template = new NetworkTemplate.Builder(NetworkTemplate.MATCH_WIFI).build();
return getDataUsageInfo(template);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index 3f95a07cc750..afd44d5bbc90 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -17,6 +17,7 @@
package com.android.settingslib.net;
import android.content.Context;
+import android.net.NetworkStats;
import android.net.NetworkTemplate;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -26,6 +27,7 @@ import android.util.Log;
import com.android.internal.util.ArrayUtils;
import java.util.List;
+import java.util.Set;
/**
* Utils class for data usage
@@ -73,10 +75,15 @@ public class DataUsageUtils {
private static NetworkTemplate getMobileTemplateForSubId(
TelephonyManager telephonyManager, int subId) {
- // The null subscriberId means that no any mobile/carrier network will be matched.
- // Using old API: buildTemplateMobileAll for the null subscriberId to avoid NPE.
+ // Create template that matches any mobile network when the subscriberId is null.
String subscriberId = telephonyManager.getSubscriberId(subId);
- return subscriberId != null ? NetworkTemplate.buildTemplateCarrierMetered(subscriberId)
- : NetworkTemplate.buildTemplateMobileAll(subscriberId);
+ return subscriberId != null
+ ? new NetworkTemplate.Builder(NetworkTemplate.MATCH_CARRIER)
+ .setSubscriberIds(Set.of(subscriberId))
+ .setMeteredness(NetworkStats.METERED_YES)
+ .build()
+ : new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE)
+ .setMeteredness(NetworkStats.METERED_YES)
+ .build();
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java
index 21a4ac6220fb..fa4ae6712aaa 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtils.java
@@ -60,6 +60,22 @@ public class WifiEnterpriseRestrictionUtils {
return true;
}
+ /**
+ * Confirm Wi-Fi Config is allowed to add according to whether user restriction is set
+ *
+ * @param context A context
+ * @return whether the device is permitted to add new Wi-Fi config
+ */
+ public static boolean isAddWifiConfigAllowed(Context context) {
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ final Bundle restrictions = userManager.getUserRestrictions();
+ if (isAtLeastT() && restrictions.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)) {
+ Log.i(TAG, "Wi-Fi Add network isn't available due to user restriction.");
+ return false;
+ }
+ return true;
+ }
+
@ChecksSdkIntAtLeast(api=Build.VERSION_CODES.TIRAMISU)
private static boolean isAtLeastT() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
index 7e389a19e403..919f602862b4 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
@@ -20,6 +20,7 @@ import static junit.framework.Assert.assertEquals;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
+import android.net.NetworkStats;
import android.net.NetworkTemplate;
import androidx.test.InstrumentationRegistry;
@@ -32,6 +33,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.Set;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class NetworkPolicyEditorTest {
@@ -44,7 +47,9 @@ public class NetworkPolicyEditorTest {
@Before
public void setUp() {
- mNetworkTemplate = NetworkTemplate.buildTemplateCarrierMetered("123456789123456");
+ mNetworkTemplate = new NetworkTemplate.Builder(NetworkTemplate.MATCH_CARRIER)
+ .setMeteredness(NetworkStats.METERED_YES)
+ .setSubscriberIds(Set.of("123456789123456")).build();
NetworkPolicyManager policyManager = NetworkPolicyManager.from(InstrumentationRegistry
.getContext());
mNetworkPolicyEditor = new NetworkPolicyEditor(policyManager);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
index 30182c476855..f5ce6647e531 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HeadsetProfileTest.java
@@ -55,15 +55,6 @@ public class HeadsetProfileTest {
}
@Test
- public void bluetoothProfile_shouldReturnTheAudioStatusFromBlueToothHeadsetService() {
- when(mService.isAudioOn()).thenReturn(true);
- assertThat(mProfile.isAudioOn()).isTrue();
-
- when(mService.isAudioOn()).thenReturn(false);
- assertThat(mProfile.isAudioOn()).isFalse();
- }
-
- @Test
public void testHeadsetProfile_shouldReturnAudioState() {
when(mService.getAudioState(mBluetoothDevice)).
thenReturn(BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
index 9be783d61ea8..f0456b3d51ba 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java
@@ -18,26 +18,21 @@ package com.android.settingslib.net;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.usage.NetworkStats;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.net.INetworkStatsSession;
-import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.os.RemoteException;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.text.format.DateUtils;
import org.junit.Before;
import org.junit.Test;
@@ -47,6 +42,8 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.shadows.ShadowSubscriptionManager;
+import java.util.Set;
+
@RunWith(RobolectricTestRunner.class)
public class DataUsageControllerTest {
@@ -54,8 +51,6 @@ public class DataUsageControllerTest {
private static final String SUB_ID_2 = "Test Subscriber 2";
@Mock
- private INetworkStatsSession mSession;
- @Mock
private TelephonyManager mTelephonyManager;
@Mock
private SubscriptionManager mSubscriptionManager;
@@ -68,7 +63,6 @@ public class DataUsageControllerTest {
private NetworkTemplate mWifiNetworkTemplate;
private DataUsageController mController;
- private NetworkStatsHistory mNetworkStatsHistory;
private final int mDefaultSubscriptionId = 1234;
@Before
@@ -80,17 +74,16 @@ public class DataUsageControllerTest {
.thenReturn(mSubscriptionManager);
when(mContext.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager);
mController = new DataUsageController(mContext);
- mNetworkStatsHistory = spy(
- new NetworkStatsHistory(DateUtils.DAY_IN_MILLIS /* bucketDuration */));
- doReturn(mNetworkStatsHistory)
- .when(mSession).getHistoryForNetwork(any(NetworkTemplate.class), anyInt());
ShadowSubscriptionManager.setDefaultDataSubscriptionId(mDefaultSubscriptionId);
doReturn(SUB_ID).when(mTelephonyManager).getSubscriberId();
- mNetworkTemplate = NetworkTemplate.buildTemplateCarrierMetered(SUB_ID);
- mNetworkTemplate2 = NetworkTemplate.buildTemplateCarrierMetered(SUB_ID_2);
- mWifiNetworkTemplate = NetworkTemplate.buildTemplateWifi(
- NetworkTemplate.WIFI_NETWORKID_ALL, null);
+ mNetworkTemplate = new NetworkTemplate.Builder(NetworkTemplate.MATCH_CARRIER)
+ .setMeteredness(android.net.NetworkStats.METERED_YES)
+ .setSubscriberIds(Set.of(SUB_ID)).build();
+ mNetworkTemplate2 = new NetworkTemplate.Builder(NetworkTemplate.MATCH_CARRIER)
+ .setMeteredness(android.net.NetworkStats.METERED_YES)
+ .setSubscriberIds(Set.of(SUB_ID_2)).build();
+ mWifiNetworkTemplate = new NetworkTemplate.Builder(NetworkTemplate.MATCH_WIFI).build();
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
index e8d584486746..5b0f659e9c7a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
@@ -30,6 +30,7 @@ import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
+import android.net.NetworkStats;
import android.net.NetworkTemplate;
import android.text.format.DateUtils;
@@ -40,6 +41,8 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import java.util.Set;
+
@RunWith(RobolectricTestRunner.class)
public class NetworkCycleDataForUidLoaderTest {
private static final String SUB_ID = "Test Subscriber";
@@ -62,7 +65,9 @@ public class NetworkCycleDataForUidLoaderTest {
when(mContext.getSystemService(Context.NETWORK_POLICY_SERVICE))
.thenReturn(mNetworkPolicyManager);
when(mNetworkPolicyManager.getNetworkPolicies()).thenReturn(new NetworkPolicy[0]);
- mNetworkTemplate = NetworkTemplate.buildTemplateCarrierMetered(SUB_ID);
+ mNetworkTemplate = new NetworkTemplate.Builder(NetworkTemplate.MATCH_CARRIER)
+ .setMeteredness(NetworkStats.METERED_YES)
+ .setSubscriberIds(Set.of(SUB_ID)).build();
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java
index 3c339defbaf4..f6af09a34388 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEnterpriseRestrictionUtilsTest.java
@@ -103,4 +103,30 @@ public class WifiEnterpriseRestrictionUtilsTest {
assertThat(WifiEnterpriseRestrictionUtils.isWifiDirectAllowed(mContext)).isTrue();
}
+
+ @Test
+ public void isAddWifiConfigAllowed_setSDKForS_shouldReturnTrue() {
+ ReflectionHelpers.setStaticField(Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.S);
+ when(mBundle.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
+
+ assertThat(WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(mContext)).isTrue();
+ }
+
+ @Test
+ public void isAddWifiConfigAllowed_setSDKForTAndDisallowForRestriction_shouldReturnFalse() {
+ ReflectionHelpers.setStaticField(
+ Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
+ when(mBundle.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)).thenReturn(true);
+
+ assertThat(WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(mContext)).isFalse();
+ }
+
+ @Test
+ public void isAddWifiConfigAllowed_setSDKForTAndAllowForRestriction_shouldReturnTrue() {
+ ReflectionHelpers.setStaticField(
+ Build.VERSION.class, "SDK_INT", Build.VERSION_CODES.TIRAMISU);
+ when(mBundle.getBoolean(UserManager.DISALLOW_ADD_WIFI_CONFIG)).thenReturn(false);
+
+ assertThat(WifiEnterpriseRestrictionUtils.isAddWifiConfigAllowed(mContext)).isTrue();
+ }
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 71accc416416..00b5f5019485 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -78,6 +78,8 @@ public class SystemSettings {
Settings.System.NOTIFICATION_SOUND,
Settings.System.ACCELEROMETER_ROTATION,
Settings.System.SHOW_BATTERY_PERCENT,
+ Settings.System.ALARM_VIBRATION_INTENSITY,
+ Settings.System.MEDIA_VIBRATION_INTENSITY,
Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
Settings.System.RING_VIBRATION_INTENSITY,
Settings.System.HAPTIC_FEEDBACK_INTENSITY,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 84e9d2809205..6bcb7695cd22 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -118,6 +118,8 @@ public class SystemSettingsValidators {
VALIDATORS.put(System.MUTE_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR);
VALIDATORS.put(System.VIBRATE_ON, BOOLEAN_VALIDATOR);
VALIDATORS.put(System.APPLY_RAMPING_RINGER, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(System.ALARM_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
+ VALIDATORS.put(System.MEDIA_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
VALIDATORS.put(System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
VALIDATORS.put(System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
VALIDATORS.put(System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 00cdc9b0a058..c5f027b829d9 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -2916,6 +2916,18 @@ class SettingsProtoDumpUtil {
dumpSetting(s, p,
Settings.System.VIBRATE_WHEN_RINGING,
SystemSettingsProto.Vibrate.WHEN_RINGING);
+
+ // NOTIFICATION_VIBRATION_INTENSITY is already logged at Notification.vibration_intensity
+ // HAPTIC_FEEDBACK_INTENSITY is already logged at HapticFeedback.intensity
+ dumpSetting(s, p,
+ Settings.System.ALARM_VIBRATION_INTENSITY,
+ SystemSettingsProto.Vibrate.ALARM_INTENSITY);
+ dumpSetting(s, p,
+ Settings.System.MEDIA_VIBRATION_INTENSITY,
+ SystemSettingsProto.Vibrate.MEDIA_INTENSITY);
+ dumpSetting(s, p,
+ Settings.System.RING_VIBRATION_INTENSITY,
+ SystemSettingsProto.Vibrate.RING_INTENSITY);
p.end(vibrateToken);
final long volumeToken = p.start(SystemSettingsProto.VOLUME);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 10252ee3bc60..0c70821527dd 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -23,6 +23,7 @@
>
<!-- Standard permissions granted to the shell. -->
+ <uses-permission android:name="android.permission.LAUNCH_DEVICE_MANAGER_SETUP" />
<uses-permission android:name="android.permission.GET_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
@@ -607,15 +608,14 @@
<!-- Permission required for ATS test - CarDevicePolicyManagerTest -->
<uses-permission android:name="android.permission.LOCK_DEVICE" />
- <!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
+ <!-- Permissions required for CTS test - CtsSafetyCenterTestCases -->
<uses-permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
-
- <!-- Permission required for CTS test - CtsSafetyCenterTestCases -->
<uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" />
+ <uses-permission android:name="android.permission.MANAGE_SAFETY_CENTER" />
+
- <!-- Permission required for CTS test - CommunalManagerTest -->
- <uses-permission android:name="android.permission.WRITE_COMMUNAL_STATE" />
- <uses-permission android:name="android.permission.READ_COMMUNAL_STATE" />
+ <!-- Permission required for CTS test - Notification test suite -->
+ <uses-permission android:name="android.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL" />
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
diff --git a/packages/Shell/res/values-watch/strings.xml b/packages/Shell/res/values-watch/strings.xml
new file mode 100644
index 000000000000..5f7bfcb25d85
--- /dev/null
+++ b/packages/Shell/res/values-watch/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Title for Bug report notification indicating the number of the bug report and the
+ percentage complete. Example: "Bug report #3 is 20% complete" [CHAR LIMIT=50] -->
+ <string name="bugreport_in_progress_title">Bug report <xliff:g id="id" example="#3">#%1$d</xliff:g> is <xliff:g id="percentage" example="20%">%2$s</xliff:g> complete</string>
+</resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index ee9d4301770a..c5a01a1c2b93 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -199,6 +199,15 @@ public class BugreportProgressService extends Service {
*/
private static final String BUGREPORT_DIR = "bugreports";
+ /**
+ * The directory in which System Trace files from the native System Tracing app are stored for
+ * Wear devices.
+ */
+ private static final String WEAR_SYSTEM_TRACES_DIRECTORY_ON_DEVICE = "data/local/traces/";
+
+ /** The directory that contains System Traces in bugreports that include System Traces. */
+ private static final String WEAR_SYSTEM_TRACES_DIRECTORY_IN_BUGREPORT = "systraces/";
+
private static final String NOTIFICATION_CHANNEL_ID = "bugreports";
/**
@@ -724,14 +733,16 @@ public class BugreportProgressService extends Service {
nf.setMaximumFractionDigits(2);
final String percentageText = nf.format((double) info.progress.intValue() / 100);
- String title = mContext.getString(R.string.bugreport_in_progress_title, info.id);
-
- // TODO: Remove this workaround when notification progress is implemented on Wear.
+ final String title;
if (mIsWatch) {
+ // TODO: Remove this workaround when notification progress is implemented on Wear.
nf.setMinimumFractionDigits(0);
nf.setMaximumFractionDigits(0);
final String watchPercentageText = nf.format((double) info.progress.intValue() / 100);
- title = title + "\n" + watchPercentageText;
+ title = mContext.getString(
+ R.string.bugreport_in_progress_title, info.id, watchPercentageText);
+ } else {
+ title = mContext.getString(R.string.bugreport_in_progress_title, info.id);
}
final String name =
@@ -1456,6 +1467,16 @@ public class BugreportProgressService extends Service {
}
}
+ /** Returns an array of the system trace files collected by the System Tracing native app. */
+ private static File[] getSystemTraceFiles() {
+ try {
+ return new File(WEAR_SYSTEM_TRACES_DIRECTORY_ON_DEVICE).listFiles();
+ } catch (SecurityException e) {
+ Log.e(TAG, "Error getting system trace files.", e);
+ return new File[]{};
+ }
+ }
+
/**
* Adds the user-provided info into the bugreport zip file.
* <p>
@@ -1475,8 +1496,17 @@ public class BugreportProgressService extends Service {
Log.wtf(TAG, "addDetailsToZipFile(): no bugreportFile on " + info);
return;
}
- if (TextUtils.isEmpty(info.getTitle()) && TextUtils.isEmpty(info.getDescription())) {
- Log.d(TAG, "Not touching zip file since neither title nor description are set");
+
+ File[] systemTracesToIncludeInBugreport = new File[] {};
+ if (mIsWatch) {
+ systemTracesToIncludeInBugreport = getSystemTraceFiles();
+ Log.d(TAG, "Found " + systemTracesToIncludeInBugreport.length + " system traces.");
+ }
+
+ if (TextUtils.isEmpty(info.getTitle())
+ && TextUtils.isEmpty(info.getDescription())
+ && systemTracesToIncludeInBugreport.length == 0) {
+ Log.d(TAG, "Not touching zip file: no detail to add.");
return;
}
if (info.addedDetailsToZip || info.addingDetailsToZip) {
@@ -1487,7 +1517,10 @@ public class BugreportProgressService extends Service {
// It's not possible to add a new entry into an existing file, so we need to create a new
// zip, copy all entries, then rename it.
- sendBugreportBeingUpdatedNotification(mContext, info.id); // ...and that takes time
+ if (!mIsWatch) {
+ // TODO(b/184854609): re-introduce this notification for Wear.
+ sendBugreportBeingUpdatedNotification(mContext, info.id); // ...and that takes time
+ }
final File dir = info.bugreportFile.getParentFile();
final File tmpZip = new File(dir, "tmp-" + info.bugreportFile.getName());
@@ -1508,6 +1541,13 @@ public class BugreportProgressService extends Service {
}
// Then add the user-provided info.
+ if (systemTracesToIncludeInBugreport.length != 0) {
+ for (File trace : systemTracesToIncludeInBugreport) {
+ addEntry(zos,
+ WEAR_SYSTEM_TRACES_DIRECTORY_IN_BUGREPORT + trace.getName(),
+ new FileInputStream(trace));
+ }
+ }
addEntry(zos, "title.txt", info.getTitle());
addEntry(zos, "description.txt", info.getDescription());
} catch (IOException e) {
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index c805e2d0330a..137a1fd4f299 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -129,8 +129,15 @@ android_library {
}
filegroup {
+ name: "AAA-src",
+ srcs: ["tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java"],
+ path: "tests/src",
+}
+
+filegroup {
name: "SystemUI-tests-utils",
srcs: [
+ "tests/src/com/android/systemui/SysuiBaseFragmentTest.java",
"tests/src/com/android/systemui/SysuiTestCase.java",
"tests/src/com/android/systemui/TestableDependency.java",
"tests/src/com/android/systemui/classifier/FalsingManagerFake.java",
diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp
index 1b15d20d2c52..46adfeba0fb0 100644
--- a/packages/SystemUI/animation/Android.bp
+++ b/packages/SystemUI/animation/Android.bp
@@ -39,5 +39,5 @@ android_library {
],
manifest: "AndroidManifest.xml",
-
+ kotlincflags: ["-Xjvm-default=enable"],
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index a0d335db92d6..08d217d15a5a 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -95,6 +95,9 @@ class ActivityLaunchAnimator(
*/
var callback: Callback? = null
+ /** The set of [Listener] that should be notified of any animation started by this animator. */
+ private val listeners = LinkedHashSet<Listener>()
+
/**
* Start an intent and animate the opening window. The intent will be started by running
* [intentStarter], which should use the provided [RemoteAnimationAdapter] and return the launch
@@ -214,6 +217,16 @@ class ActivityLaunchAnimator(
}
}
+ /** Add a [Listener] that can listen to launch animations. */
+ fun addListener(listener: Listener) {
+ listeners.add(listener)
+ }
+
+ /** Remove a [Listener]. */
+ fun removeListener(listener: Listener) {
+ listeners.remove(listener)
+ }
+
/** Create a new animation [Runner] controlled by [controller]. */
@VisibleForTesting
fun createRunner(controller: Controller): Runner = Runner(controller)
@@ -234,13 +247,27 @@ class ActivityLaunchAnimator(
/** Hide the keyguard and animate using [runner]. */
fun hideKeyguardWithAnimation(runner: IRemoteAnimationRunner)
- /** Enable/disable window blur so they don't overlap with the window launch animation **/
- fun setBlursDisabledForAppLaunch(disabled: Boolean)
-
/* Get the background color of [task]. */
fun getBackgroundColor(task: TaskInfo): Int
}
+ interface Listener {
+ /** Called when an activity launch animation started. */
+ @JvmDefault
+ fun onLaunchAnimationStart() {}
+
+ /**
+ * Called when an activity launch animation is finished. This will be called if and only if
+ * [onLaunchAnimationStart] was called earlier.
+ */
+ @JvmDefault
+ fun onLaunchAnimationEnd() {}
+
+ /** Called when an activity launch animation made progress. */
+ @JvmDefault
+ fun onLaunchAnimationProgress(linearProgress: Float) {}
+ }
+
/**
* A controller that takes care of applying the animation to an expanding view.
*
@@ -396,12 +423,12 @@ class ActivityLaunchAnimator(
val delegate = this.controller
val controller = object : LaunchAnimator.Controller by delegate {
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
- callback.setBlursDisabledForAppLaunch(true)
+ listeners.forEach { it.onLaunchAnimationStart() }
delegate.onLaunchAnimationStart(isExpandingFullyAbove)
}
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
- callback.setBlursDisabledForAppLaunch(false)
+ listeners.forEach { it.onLaunchAnimationEnd() }
iCallback?.invoke()
delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
}
@@ -413,6 +440,7 @@ class ActivityLaunchAnimator(
) {
applyStateToWindow(window, state)
navigationBar?.let { applyStateToNavigationBar(it, state, linearProgress) }
+ listeners.forEach { it.onLaunchAnimationProgress(linearProgress) }
delegate.onLaunchAnimationProgress(state, progress, linearProgress)
}
}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
index 1e142eaeef86..e64b586a3e6f 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
@@ -46,8 +46,6 @@
android:clipChildren="false"
android:clipToPadding="false"
android:paddingTop="@dimen/keyguard_security_view_top_margin"
- android:paddingStart="@dimen/keyguard_security_view_lateral_margin"
- android:paddingEnd="@dimen/keyguard_security_view_lateral_margin"
android:layout_gravity="center"
android:gravity="center">
</com.android.keyguard.KeyguardSecurityViewFlipper>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
index e1550aa0c87c..e77e084c48e8 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -25,6 +25,7 @@
android:layout_height="match_parent"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
androidprv:layout_maxHeight="@dimen/keyguard_security_height"
+ android:layout_gravity="center_horizontal|bottom"
android:gravity="bottom"
>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
index f613a195ea67..231ead8dc273 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
@@ -28,6 +28,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+ android:layout_gravity="center_horizontal|bottom"
android:clipChildren="false"
android:clipToPadding="false">
@@ -65,6 +66,7 @@
android:orientation="vertical"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginTop="@dimen/keyguard_eca_top_margin"
+ android:layout_marginBottom="@dimen/keyguard_eca_bottom_margin"
android:gravity="center_horizontal" />
</com.android.keyguard.KeyguardPatternView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 94566c78cc93..7ce6f0e56b8f 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -25,6 +25,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+ android:layout_gravity="center_horizontal|bottom"
android:orientation="vertical"
>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index 3e34e4b255eb..b765f497f9c4 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -25,7 +25,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
- android:gravity="center_horizontal">
+ android:layout_gravity="center_horizontal|bottom">
<Space
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index d5510e90af29..917ea6b6c518 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -26,7 +26,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
androidprv:layout_maxWidth="@dimen/keyguard_security_width"
- android:gravity="center_horizontal">
+ android:layout_gravity="center_horizontal|bottom">
<Space
android:layout_width="match_parent"
diff --git a/packages/SystemUI/res-keyguard/values/bools.xml b/packages/SystemUI/res-keyguard/values/bools.xml
index 2b83787172d3..c5bf4ce48188 100644
--- a/packages/SystemUI/res-keyguard/values/bools.xml
+++ b/packages/SystemUI/res-keyguard/values/bools.xml
@@ -17,4 +17,5 @@
<resources>
<bool name="kg_show_ime_at_screen_on">true</bool>
<bool name="kg_use_all_caps">true</bool>
+ <bool name="flag_active_unlock">false</bool>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/config.xml b/packages/SystemUI/res-keyguard/values/config.xml
index 6194aa095610..e8244433260d 100644
--- a/packages/SystemUI/res-keyguard/values/config.xml
+++ b/packages/SystemUI/res-keyguard/values/config.xml
@@ -27,6 +27,6 @@
<bool name="can_use_one_handed_bouncer">false</bool>
<!-- Will display the bouncer on one side of the display, and the current user icon and
user switcher on the other side -->
- <bool name="bouncer_display_user_switcher">false</bool>
+ <bool name="config_enableBouncerUserSwitcher">false</bool>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index c8bb8e99be17..cbf4f83daeb5 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -37,7 +37,6 @@
<!-- Margin around the various security views -->
<dimen name="keyguard_security_view_top_margin">8dp</dimen>
- <dimen name="keyguard_security_view_lateral_margin">20dp</dimen>
<dimen name="keyguard_eca_top_margin">18dp</dimen>
<dimen name="keyguard_eca_bottom_margin">12dp</dimen>
diff --git a/packages/SystemUI/res-product/values-zu/strings.xml b/packages/SystemUI/res-product/values-zu/strings.xml
index e6c140a76bdf..8b79a22a72a9 100644
--- a/packages/SystemUI/res-product/values-zu/strings.xml
+++ b/packages/SystemUI/res-product/values-zu/strings.xml
@@ -40,7 +40,7 @@
<string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Uzame ngokungalungile ukuvula ifoni izikhathi ezingu-<xliff:g id="NUMBER">%d</xliff:g>. Iphrofayela yomsebenzi izosuswa, okuzosusa yonke idatha yephrofayela."</string>
<string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Udwebe ngokungalungile iphethini yakho yokuvula ngezikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. Ngemuva kwemizamo engaphumelelanga kaningi engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuthi uvule ithebulethi yakho usebenzisa i-akhawunti ye-imeyili.\n\nZama futhi kumasekhondi angu-<xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
<string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%1$d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google\n\n Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%3$d</xliff:g> imizuzwana."</string>
- <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Vula ifoni yakho ukuthola izinketho ezengeziwe"</string>
- <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Vula ithebulethi yakho ukuthola izinketho ezengeziwe"</string>
- <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Vula idivayisi yakho ukuthola izinketho ezengeziwe"</string>
+ <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"Vula ifoni yakho ukuthola okunye okungakhethwa"</string>
+ <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"Vula ithebulethi yakho ukuthola okunye okungakhethwa"</string>
+ <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"Vula idivayisi yakho ukuthola okunye okungakhethwa"</string>
</resources>
diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml
index 2059490e0456..4b1a5b85d1d2 100644
--- a/packages/SystemUI/res/values-af/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Af"</item>
<item msgid="2075645297847971154">"Aan"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Onbeskikbaar"</item>
<item msgid="9103697205127645916">"Af"</item>
diff --git a/packages/SystemUI/res/values-am/tiles_states_strings.xml b/packages/SystemUI/res/values-am/tiles_states_strings.xml
index 7fdfd11a9310..0f7ee3ecd8d2 100644
--- a/packages/SystemUI/res/values-am/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-am/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"ጠፍቷል"</item>
<item msgid="2075645297847971154">"በርቷል"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"አይገኝም"</item>
<item msgid="9103697205127645916">"ጠፍቷል"</item>
diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
index d7026c7395bf..2da87c467177 100644
--- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"الميزة غير مفعّلة"</item>
<item msgid="2075645297847971154">"الميزة مفعّلة"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"الميزة غير متاحة"</item>
<item msgid="9103697205127645916">"الميزة غير مفعّلة"</item>
diff --git a/packages/SystemUI/res/values-as/tiles_states_strings.xml b/packages/SystemUI/res/values-as/tiles_states_strings.xml
index efb235170486..2ede37473ea5 100644
--- a/packages/SystemUI/res/values-as/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-as/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"অফ আছে"</item>
<item msgid="2075645297847971154">"অন কৰা আছে"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"উপলব্ধ নহয়"</item>
<item msgid="9103697205127645916">"অফ আছে"</item>
diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml
index 7c47203ad0c2..f52a9e1bf6fa 100644
--- a/packages/SystemUI/res/values-az/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Deaktiv"</item>
<item msgid="2075645297847971154">"Aktiv"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Əlçatan deyil"</item>
<item msgid="9103697205127645916">"Deaktiv"</item>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
index 88caf9789d63..d9e0bfca36ff 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Isključeno"</item>
<item msgid="2075645297847971154">"Uključeno"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nedostupno"</item>
<item msgid="9103697205127645916">"Isključeno"</item>
diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml
index ecfde0b5a08e..5c7c40fed7a7 100644
--- a/packages/SystemUI/res/values-be/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Выключана"</item>
<item msgid="2075645297847971154">"Уключана"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Недаступна"</item>
<item msgid="9103697205127645916">"Выключана"</item>
diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
index 7424f8155de1..6839b830283c 100644
--- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Изкл."</item>
<item msgid="2075645297847971154">"Вкл."</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Не е налице"</item>
<item msgid="9103697205127645916">"Изкл."</item>
diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
index eddf8515b207..7a6b3ac1c371 100644
--- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"বন্ধ আছে"</item>
<item msgid="2075645297847971154">"চালু আছে"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"উপলভ্য নেই"</item>
<item msgid="9103697205127645916">"বন্ধ আছে"</item>
diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
index 88caf9789d63..d9e0bfca36ff 100644
--- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Isključeno"</item>
<item msgid="2075645297847971154">"Uključeno"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nedostupno"</item>
<item msgid="9103697205127645916">"Isključeno"</item>
diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
index e3538fad1a6e..28f3da4650eb 100644
--- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Desactivat"</item>
<item msgid="2075645297847971154">"Activat"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"No disponible"</item>
<item msgid="9103697205127645916">"Desactivat"</item>
diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
index 3f40ab6ea7f4..ce64e273dc02 100644
--- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Vyp"</item>
<item msgid="2075645297847971154">"Zap"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nedostupné"</item>
<item msgid="9103697205127645916">"Vyp"</item>
diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml
index b479a44b33f4..9e4c6f4b8459 100644
--- a/packages/SystemUI/res/values-da/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Fra"</item>
<item msgid="2075645297847971154">"Til"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Ikke tilgængelig"</item>
<item msgid="9103697205127645916">"Fra"</item>
diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml
index 81f030cef2f8..e958670b502e 100644
--- a/packages/SystemUI/res/values-de/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Aus"</item>
<item msgid="2075645297847971154">"An"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nicht verfügbar"</item>
<item msgid="9103697205127645916">"Aus"</item>
diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml
index 422f2aa11630..1c9583518595 100644
--- a/packages/SystemUI/res/values-el/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Ανενεργό"</item>
<item msgid="2075645297847971154">"Ενεργό"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Μη διαθέσιμο"</item>
<item msgid="9103697205127645916">"Ανενεργό"</item>
diff --git a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
index 9b00c8b32bf1..13f236b639f0 100644
--- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Off"</item>
<item msgid="2075645297847971154">"On"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Unavailable"</item>
+ <item msgid="1909756493418256167">"Off"</item>
+ <item msgid="4531508423703413340">"On"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Unavailable"</item>
<item msgid="9103697205127645916">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
index 9b00c8b32bf1..13f236b639f0 100644
--- a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Off"</item>
<item msgid="2075645297847971154">"On"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Unavailable"</item>
+ <item msgid="1909756493418256167">"Off"</item>
+ <item msgid="4531508423703413340">"On"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Unavailable"</item>
<item msgid="9103697205127645916">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
index 9b00c8b32bf1..13f236b639f0 100644
--- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Off"</item>
<item msgid="2075645297847971154">"On"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Unavailable"</item>
+ <item msgid="1909756493418256167">"Off"</item>
+ <item msgid="4531508423703413340">"On"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Unavailable"</item>
<item msgid="9103697205127645916">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
index 9b00c8b32bf1..13f236b639f0 100644
--- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Off"</item>
<item msgid="2075645297847971154">"On"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Unavailable"</item>
+ <item msgid="1909756493418256167">"Off"</item>
+ <item msgid="4531508423703413340">"On"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Unavailable"</item>
<item msgid="9103697205127645916">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
index 0012b57522aa..e6baa3127c92 100644
--- a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‎‎‏‎‎Off‎‏‎‎‏‎"</item>
<item msgid="2075645297847971154">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‎On‎‏‎‎‏‎"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎Unavailable‎‏‎‎‏‎"</item>
+ <item msgid="1909756493418256167">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎Off‎‏‎‎‏‎"</item>
+ <item msgid="4531508423703413340">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‎‎‎On‎‏‎‎‏‎"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎Unavailable‎‏‎‎‏‎"</item>
<item msgid="9103697205127645916">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‎‎‎Off‎‏‎‎‏‎"</item>
diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
index afb0e727046f..0d77977fd174 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Desactivado"</item>
<item msgid="2075645297847971154">"Activado"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"No disponible"</item>
<item msgid="9103697205127645916">"Desactivado"</item>
diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml
index dd1ed433a68a..080731a2feb1 100644
--- a/packages/SystemUI/res/values-es/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Desactivado"</item>
<item msgid="2075645297847971154">"Activado"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"No disponible"</item>
<item msgid="9103697205127645916">"Desactivado"</item>
diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml
index 26fbe80c170b..26d71fe07a57 100644
--- a/packages/SystemUI/res/values-et/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Väljas"</item>
<item msgid="2075645297847971154">"Sees"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Pole saadaval"</item>
<item msgid="9103697205127645916">"Väljas"</item>
diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
index a2a08dbb01be..11090458f1f5 100644
--- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Desaktibatuta"</item>
<item msgid="2075645297847971154">"Aktibatuta"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Ez dago erabilgarri"</item>
<item msgid="9103697205127645916">"Desaktibatuta"</item>
diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
index 8c40e716f643..ab755197d0a5 100644
--- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"خاموش"</item>
<item msgid="2075645297847971154">"روشن"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"دردسترس نیست"</item>
<item msgid="9103697205127645916">"خاموش"</item>
diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
index cb9e07c322fc..6fa9466e1313 100644
--- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Poissa päältä"</item>
<item msgid="2075645297847971154">"Päällä"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Ei saatavilla"</item>
<item msgid="9103697205127645916">"Poissa päältä"</item>
diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
index eb38d94425fa..aec8ab87dcfb 100644
--- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Désactivé"</item>
<item msgid="2075645297847971154">"Activé"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Non disponible"</item>
<item msgid="9103697205127645916">"Désactivée"</item>
diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
index 3aefb1d86c88..01d9c1d74dd0 100644
--- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Désactivé"</item>
<item msgid="2075645297847971154">"Activé"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Indisponible"</item>
<item msgid="9103697205127645916">"Désactivée"</item>
diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
index 90dcf7d0074b..9045983425df 100644
--- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Non"</item>
<item msgid="2075645297847971154">"Si"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Non dispoñible"</item>
<item msgid="9103697205127645916">"Non"</item>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
index e50f3cff1328..15b0f9fe7fbe 100644
--- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"બંધ છે"</item>
<item msgid="2075645297847971154">"ચાલુ છે"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"ઉપલબ્ધ નથી"</item>
<item msgid="9103697205127645916">"બંધ છે"</item>
diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
index 769891268e5b..00fa69936dc6 100644
--- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"बंद है"</item>
<item msgid="2075645297847971154">"चालू है"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"उपलब्ध नहीं है"</item>
<item msgid="9103697205127645916">"बंद है"</item>
diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
index ae9ffb353293..730081667113 100644
--- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Isključeno"</item>
<item msgid="2075645297847971154">"Uključeno"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nedostupno"</item>
<item msgid="9103697205127645916">"Isključeno"</item>
diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
index 140f2db0c85c..52450e4b3937 100644
--- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Ki"</item>
<item msgid="2075645297847971154">"Be"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nem áll rendelkezésre"</item>
<item msgid="9103697205127645916">"Ki"</item>
diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
index df69ce7544f4..23a096b194af 100644
--- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Անջատված է"</item>
<item msgid="2075645297847971154">"Միացված է"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Հասանելի չէ"</item>
<item msgid="9103697205127645916">"Անջատված է"</item>
diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml
index 811294f03902..c296e5443190 100644
--- a/packages/SystemUI/res/values-in/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Nonaktif"</item>
<item msgid="2075645297847971154">"Aktif"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Tidak tersedia"</item>
<item msgid="9103697205127645916">"Nonaktif"</item>
diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml
index dd704a74b736..25b3dcc53661 100644
--- a/packages/SystemUI/res/values-is/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Slökkt"</item>
<item msgid="2075645297847971154">"Kveikt"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Ekki í boði"</item>
<item msgid="9103697205127645916">"Slökkt"</item>
diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml
index 159699893513..7e6827a4d8c2 100644
--- a/packages/SystemUI/res/values-it/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Off"</item>
<item msgid="2075645297847971154">"On"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Non disponibile"</item>
<item msgid="9103697205127645916">"Off"</item>
diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
index 28548bcdd656..bf3c2b6ad767 100644
--- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"כבוי"</item>
<item msgid="2075645297847971154">"פועל"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"לא זמין"</item>
<item msgid="9103697205127645916">"כבוי"</item>
diff --git a/packages/SystemUI/res/values-ja/tiles_states_strings.xml b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
index 7fc9c08c2e83..9197aab790b0 100644
--- a/packages/SystemUI/res/values-ja/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"OFF"</item>
<item msgid="2075645297847971154">"ON"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"使用不可"</item>
<item msgid="9103697205127645916">"OFF"</item>
diff --git a/packages/SystemUI/res/values-ka/tiles_states_strings.xml b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
index 40dfd3993d44..485c3de7bdcf 100644
--- a/packages/SystemUI/res/values-ka/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"გამორთულია"</item>
<item msgid="2075645297847971154">"ჩართულია"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"მიუწვდომელია"</item>
<item msgid="9103697205127645916">"გამორთულია"</item>
diff --git a/packages/SystemUI/res/values-kk/tiles_states_strings.xml b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
index 3e9aefa08a22..b143632803cb 100644
--- a/packages/SystemUI/res/values-kk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Өшірулі"</item>
<item msgid="2075645297847971154">"Қосулы"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Қолжетімсіз"</item>
<item msgid="9103697205127645916">"Өшірулі"</item>
diff --git a/packages/SystemUI/res/values-km/tiles_states_strings.xml b/packages/SystemUI/res/values-km/tiles_states_strings.xml
index 32a6e228d9c7..38d3894d07e1 100644
--- a/packages/SystemUI/res/values-km/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-km/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"បិទ"</item>
<item msgid="2075645297847971154">"បើក"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"មិនមានទេ"</item>
<item msgid="9103697205127645916">"បិទ"</item>
diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
index c13e1981837e..022c5cf35f5c 100644
--- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"ಆಫ್ ಮಾಡಿ"</item>
<item msgid="2075645297847971154">"ಆನ್ ಮಾಡಿ"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"ಲಭ್ಯವಿಲ್ಲ"</item>
<item msgid="9103697205127645916">"ಆಫ್ ಮಾಡಿ"</item>
diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
index 28d45cf685de..ae6f148270c5 100644
--- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"꺼짐"</item>
<item msgid="2075645297847971154">"켜짐"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"이용 불가"</item>
<item msgid="9103697205127645916">"꺼짐"</item>
diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
index 139d784e0668..0eadc34e37ba 100644
--- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Өчүк"</item>
<item msgid="2075645297847971154">"Күйүк"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Жеткиликсиз"</item>
<item msgid="9103697205127645916">"Өчүк"</item>
diff --git a/packages/SystemUI/res/values-lo/tiles_states_strings.xml b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
index 74c0f245b653..5fe5cfff03bf 100644
--- a/packages/SystemUI/res/values-lo/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"ປິດ"</item>
<item msgid="2075645297847971154">"ເປີດ"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"ບໍ່ສາມາດໃຊ້ໄດ້"</item>
<item msgid="9103697205127645916">"ປິດ"</item>
diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
index 08e0e6dac711..7a0caa9c9afa 100644
--- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Išjungta"</item>
<item msgid="2075645297847971154">"Įjungta"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nepasiekiama"</item>
<item msgid="9103697205127645916">"Išjungta"</item>
diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
index c5718f8490ac..872dba60ca1d 100644
--- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Izslēgts"</item>
<item msgid="2075645297847971154">"Ieslēgts"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nav pieejama"</item>
<item msgid="9103697205127645916">"Izslēgta"</item>
diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
index fa484ae1c76b..65e94f371e7f 100644
--- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Исклучено"</item>
<item msgid="2075645297847971154">"Вклучено"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Недостапно"</item>
<item msgid="9103697205127645916">"Исклучено"</item>
diff --git a/packages/SystemUI/res/values-ml/tiles_states_strings.xml b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
index 0cca763b8e85..8746c74bd00a 100644
--- a/packages/SystemUI/res/values-ml/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"ഓഫാണ്"</item>
<item msgid="2075645297847971154">"ഓണാണ്"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"ലഭ്യമല്ല"</item>
<item msgid="9103697205127645916">"ഓഫാണ്"</item>
diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
index 41049d851b05..07dde9f76a98 100644
--- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Унтраалттай"</item>
<item msgid="2075645297847971154">"Асаалттай"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Боломжгүй"</item>
<item msgid="9103697205127645916">"Унтраалттай"</item>
diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
index 588c5ad74ba8..f0ca33356bb6 100644
--- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"बंद आहे"</item>
<item msgid="2075645297847971154">"सुरू आहे"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"उपलब्ध नाही"</item>
<item msgid="9103697205127645916">"बंद आहे"</item>
diff --git a/packages/SystemUI/res/values-ms/tiles_states_strings.xml b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
index 60ce1f0a432b..b682df1ca324 100644
--- a/packages/SystemUI/res/values-ms/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Mati"</item>
<item msgid="2075645297847971154">"Hidup"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Tidak tersedia"</item>
<item msgid="9103697205127645916">"Mati"</item>
diff --git a/packages/SystemUI/res/values-my/tiles_states_strings.xml b/packages/SystemUI/res/values-my/tiles_states_strings.xml
index 7d2f20b9526f..af8d55c8cd7f 100644
--- a/packages/SystemUI/res/values-my/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-my/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"ပိတ်"</item>
<item msgid="2075645297847971154">"ဖွင့်"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"မရနိုင်ပါ"</item>
<item msgid="9103697205127645916">"ပိတ်"</item>
diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
index e512a8476ee3..619f6135d56f 100644
--- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Av"</item>
<item msgid="2075645297847971154">"På"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Utilgjengelig"</item>
<item msgid="9103697205127645916">"Av"</item>
diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
index 355df40807fd..808b58d31ea1 100644
--- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"अफ छ"</item>
<item msgid="2075645297847971154">"अन छ"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"उपलब्ध छैन"</item>
<item msgid="9103697205127645916">"अफ छ"</item>
diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
index fa85b886c847..92332ca81f4a 100644
--- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Uit"</item>
<item msgid="2075645297847971154">"Aan"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Niet beschikbaar"</item>
<item msgid="9103697205127645916">"Uit"</item>
diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml
index bb94e0daced3..94b012297f49 100644
--- a/packages/SystemUI/res/values-or/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"ବନ୍ଦ ଅଛି"</item>
<item msgid="2075645297847971154">"ଚାଲୁ ଅଛି"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"ଉପଲବ୍ଧ ନାହିଁ"</item>
<item msgid="9103697205127645916">"ବନ୍ଦ ଅଛି"</item>
diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
index 2403141cf226..a7fc06626636 100644
--- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"ਬੰਦ ਹੈ"</item>
<item msgid="2075645297847971154">"ਚਾਲੂ ਹੈ"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"ਅਣਉਪਲਬਧ ਹੈ"</item>
<item msgid="9103697205127645916">"ਬੰਦ ਹੈ"</item>
diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
index 30026e89d932..94fa858a0abb 100644
--- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Wyłączony"</item>
<item msgid="2075645297847971154">"Włączony"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Niedostępny"</item>
<item msgid="9103697205127645916">"Wyłączony"</item>
diff --git a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
index f874dd40fe63..932ddc034f60 100644
--- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Desativado"</item>
<item msgid="2075645297847971154">"Ativado"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Indisponível"</item>
+ <item msgid="1909756493418256167">"Desativada"</item>
+ <item msgid="4531508423703413340">"Ativada"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Indisponível"</item>
<item msgid="9103697205127645916">"Desativada"</item>
diff --git a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
index 1e426e18e5e6..e6ebea8c1472 100644
--- a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Desligado"</item>
<item msgid="2075645297847971154">"Ligado"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Indisponível"</item>
+ <item msgid="1909756493418256167">"Desativada"</item>
+ <item msgid="4531508423703413340">"Ativada"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Indisponível"</item>
<item msgid="9103697205127645916">"Desligado"</item>
diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
index f874dd40fe63..932ddc034f60 100644
--- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Desativado"</item>
<item msgid="2075645297847971154">"Ativado"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Indisponível"</item>
+ <item msgid="1909756493418256167">"Desativada"</item>
+ <item msgid="4531508423703413340">"Ativada"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Indisponível"</item>
<item msgid="9103697205127645916">"Desativada"</item>
diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
index c63e7fec1492..708c6f03a1d7 100644
--- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Dezactivat"</item>
<item msgid="2075645297847971154">"Activat"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Indisponibilă"</item>
<item msgid="9103697205127645916">"Dezactivată"</item>
diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
index ae31f3227497..3a51c2e1b2b0 100644
--- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Откл."</item>
<item msgid="2075645297847971154">"Вкл."</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Функция недоступна"</item>
<item msgid="9103697205127645916">"Откл."</item>
diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml
index fa78ccc4246b..909d119f2c09 100644
--- a/packages/SystemUI/res/values-si/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"අක්‍රියයි"</item>
<item msgid="2075645297847971154">"සක්‍රියයි"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"නොමැත"</item>
<item msgid="9103697205127645916">"අක්‍රියයි"</item>
diff --git a/packages/SystemUI/res/values-sk/tiles_states_strings.xml b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
index 1920f04610d7..a8c354597a36 100644
--- a/packages/SystemUI/res/values-sk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Vypnuté"</item>
<item msgid="2075645297847971154">"Zapnuté"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Nedostupné"</item>
+ <item msgid="1909756493418256167">"Vypnuté"</item>
+ <item msgid="4531508423703413340">"Zapnuté"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nie je k dispozícii"</item>
<item msgid="9103697205127645916">"Vypnuté"</item>
diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
index 924ec58cbeaa..c09d911bbad7 100644
--- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Izklopljeno"</item>
<item msgid="2075645297847971154">"Vklopljeno"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Ni na voljo"</item>
+ <item msgid="1909756493418256167">"Izklopljeno"</item>
+ <item msgid="4531508423703413340">"Vklopljeno"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Ni na voljo"</item>
<item msgid="9103697205127645916">"Izklopljeno"</item>
diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
index 34879ce320f4..461cd93b3ba9 100644
--- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Joaktive"</item>
<item msgid="2075645297847971154">"Aktive"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Nuk ofrohet"</item>
<item msgid="9103697205127645916">"Joaktiv"</item>
diff --git a/packages/SystemUI/res/values-sr/tiles_states_strings.xml b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
index 855b84b0b8d8..ab10ca1f6881 100644
--- a/packages/SystemUI/res/values-sr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Искључено"</item>
<item msgid="2075645297847971154">"Укључено"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Недоступно"</item>
<item msgid="9103697205127645916">"Искључено"</item>
diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
index b071b917d6b9..cdcf6e6c5f41 100644
--- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Av"</item>
<item msgid="2075645297847971154">"På"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Inte tillgängligt"</item>
<item msgid="9103697205127645916">"Av"</item>
diff --git a/packages/SystemUI/res/values-sw/tiles_states_strings.xml b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
index a92c7f920616..563c07803d12 100644
--- a/packages/SystemUI/res/values-sw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Kimezimwa"</item>
<item msgid="2075645297847971154">"Kimewashwa"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Hakipatikani"</item>
<item msgid="9103697205127645916">"Kimezimwa"</item>
diff --git a/packages/SystemUI/res/values-sw720dp-land/config.xml b/packages/SystemUI/res/values-sw720dp-land/config.xml
index e0b161456aa2..ae89ef4ccc86 100644
--- a/packages/SystemUI/res/values-sw720dp-land/config.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/config.xml
@@ -31,7 +31,7 @@
<bool name="config_use_split_notification_shade">true</bool>
<!-- The number of columns in the QuickSettings -->
- <integer name="quick_settings_num_columns">2</integer>
+ <integer name="quick_settings_num_columns">3</integer>
<!-- Notifications are sized to match the width of two (of 4) qs tiles in landscape. -->
<bool name="config_skinnyNotifsInLandscape">false</bool>
diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
index f3ba1a1515ed..a9e0eabc3d8c 100644
--- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"முடக்கப்பட்டுள்ளது"</item>
<item msgid="2075645297847971154">"இயக்கப்பட்டுள்ளது"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"கிடைக்கவில்லை"</item>
<item msgid="9103697205127645916">"முடக்கப்பட்டுள்ளது"</item>
diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml
index bed919fa7306..4cb7291cafd3 100644
--- a/packages/SystemUI/res/values-te/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"ఆఫ్‌లో ఉంది"</item>
<item msgid="2075645297847971154">"ఆన్‌లో ఉంది"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"అందుబాటులో లేదు"</item>
<item msgid="9103697205127645916">"ఆఫ్‌లో ఉంది"</item>
diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml
index d5591b29a597..67768736afd9 100644
--- a/packages/SystemUI/res/values-th/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"ปิด"</item>
<item msgid="2075645297847971154">"เปิด"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"ไม่พร้อมใช้งาน"</item>
<item msgid="9103697205127645916">"ปิด"</item>
diff --git a/packages/SystemUI/res/values-tl/tiles_states_strings.xml b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
index c601d2ff35c8..62172a4dc907 100644
--- a/packages/SystemUI/res/values-tl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Naka-off"</item>
<item msgid="2075645297847971154">"Naka-on"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Hindi available"</item>
<item msgid="9103697205127645916">"Naka-off"</item>
diff --git a/packages/SystemUI/res/values-tr/tiles_states_strings.xml b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
index 17ce6b32e81b..9f836fc6bc2d 100644
--- a/packages/SystemUI/res/values-tr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Kapalı"</item>
<item msgid="2075645297847971154">"Açık"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Kullanılamıyor"</item>
<item msgid="9103697205127645916">"Kapalı"</item>
diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
index 6f9ef21a8426..34c40d3d2951 100644
--- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Вимкнено"</item>
<item msgid="2075645297847971154">"Увімкнено"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Недоступно"</item>
<item msgid="9103697205127645916">"Вимкнено"</item>
diff --git a/packages/SystemUI/res/values-ur/tiles_states_strings.xml b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
index 3284fc5d8021..02943fa8e272 100644
--- a/packages/SystemUI/res/values-ur/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"آف ہے"</item>
<item msgid="2075645297847971154">"آن ہے"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"دستیاب نہیں ہے"</item>
<item msgid="9103697205127645916">"آف ہے"</item>
diff --git a/packages/SystemUI/res/values-uz/tiles_states_strings.xml b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
index 47bcf4db8392..52a8b0a52e52 100644
--- a/packages/SystemUI/res/values-uz/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
@@ -86,6 +86,11 @@
<item msgid="5715725170633593906">"Oʻchiq"</item>
<item msgid="2075645297847971154">"Yoniq"</item>
</string-array>
+ <string-array name="tile_states_color_correction">
+ <item msgid="2840507878437297682">"Ishlamaydi"</item>
+ <item msgid="1909756493418256167">"Yoqilmagan"</item>
+ <item msgid="4531508423703413340">"Yoniq"</item>
+ </string-array>
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Ishlamaydi"</item>
<item msgid="9103697205127645916">"Oʻchiq"</item>
diff --git a/packages/SystemUI/res/values-vi/tiles_states_strings.xml b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
index ecc32236f928..bff64ab6b6d3 100644
--- a/packages/SystemUI/res/values-vi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Đang tắt"</item>
<item msgid="2075645297847971154">"Đang bật"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Không hoạt động"</item>
<item msgid="9103697205127645916">"Đang tắt"</item>
diff --git a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
index 43de98e7c665..0d72f61092d0 100644
--- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"已关闭"</item>
<item msgid="2075645297847971154">"已开启"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"不可用"</item>
<item msgid="9103697205127645916">"已关闭"</item>
diff --git a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
index 637fb4ccbd61..571cfba728a4 100644
--- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"已關閉"</item>
<item msgid="2075645297847971154">"已開啟"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"無法使用"</item>
<item msgid="9103697205127645916">"已關閉"</item>
diff --git a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
index 266cf5df9321..48896579101a 100644
--- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"已關閉"</item>
<item msgid="2075645297847971154">"已開啟"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"無法使用"</item>
<item msgid="9103697205127645916">"已關閉"</item>
diff --git a/packages/SystemUI/res/values-zu/tiles_states_strings.xml b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
index 9cac4ae184b4..ea40faf4eb56 100644
--- a/packages/SystemUI/res/values-zu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
@@ -86,6 +86,9 @@
<item msgid="5715725170633593906">"Valiwe"</item>
<item msgid="2075645297847971154">"Vuliwe"</item>
</string-array>
+ <!-- no translation found for tile_states_color_correction:0 (2840507878437297682) -->
+ <!-- no translation found for tile_states_color_correction:1 (1909756493418256167) -->
+ <!-- no translation found for tile_states_color_correction:2 (4531508423703413340) -->
<string-array name="tile_states_inversion">
<item msgid="3638187931191394628">"Akutholakali"</item>
<item msgid="9103697205127645916">"Valiwe"</item>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7b8f349777a6..56517ccb873f 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -294,6 +294,7 @@
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.keyguard.KeyguardViewMediator</item>
+ <item>com.android.keyguard.KeyguardBiometricLockoutLogger</item>
<item>com.android.systemui.recents.Recents</item>
<item>com.android.systemui.volume.VolumeUI</item>
<item>com.android.systemui.statusbar.phone.StatusBar</item>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2916c1c9b357..7600eb1ad1d0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1165,7 +1165,7 @@
<string name="wallet_lockscreen_settings_label">Lock screen settings</string>
<!-- QR Code Scanner label, title [CHAR LIMIT=32] -->
- <string name="qr_code_scanner_title">QR Code</string>
+ <string name="qr_code_scanner_title">QR code</string>
<!-- QR Code Scanner description [CHAR LIMIT=NONE] -->
<string name="qr_code_scanner_description">Tap to scan</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/navigationbar/RegionSamplingHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/navigationbar/RegionSamplingHelper.java
index 98083742d707..1d2caf9ab545 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/navigationbar/RegionSamplingHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/navigationbar/RegionSamplingHelper.java
@@ -28,6 +28,8 @@ import android.view.View;
import android.view.ViewRootImpl;
import android.view.ViewTreeObserver;
+import androidx.annotation.VisibleForTesting;
+
import java.io.PrintWriter;
import java.util.concurrent.Executor;
@@ -60,6 +62,7 @@ public class RegionSamplingHelper implements View.OnAttachStateChangeListener,
private final Rect mRegisteredSamplingBounds = new Rect();
private final SamplingCallback mCallback;
private final Executor mBackgroundExecutor;
+ private final SysuiCompositionSamplingListener mCompositionSamplingListener;
private boolean mSamplingEnabled = false;
private boolean mSamplingListenerRegistered = false;
@@ -91,9 +94,17 @@ public class RegionSamplingHelper implements View.OnAttachStateChangeListener,
public RegionSamplingHelper(View sampledView, SamplingCallback samplingCallback,
Executor backgroundExecutor) {
+ this(sampledView, samplingCallback, sampledView.getContext().getMainExecutor(),
+ backgroundExecutor, new SysuiCompositionSamplingListener());
+ }
+
+ @VisibleForTesting
+ RegionSamplingHelper(View sampledView, SamplingCallback samplingCallback,
+ Executor mainExecutor, Executor backgroundExecutor,
+ SysuiCompositionSamplingListener compositionSamplingListener) {
mBackgroundExecutor = backgroundExecutor;
- mSamplingListener = new CompositionSamplingListener(
- sampledView.getContext().getMainExecutor()) {
+ mCompositionSamplingListener = compositionSamplingListener;
+ mSamplingListener = new CompositionSamplingListener(mainExecutor) {
@Override
public void onSampleCollected(float medianLuma) {
if (mSamplingEnabled) {
@@ -136,7 +147,7 @@ public class RegionSamplingHelper implements View.OnAttachStateChangeListener,
public void stopAndDestroy() {
stop();
- mSamplingListener.destroy();
+ mBackgroundExecutor.execute(mSamplingListener::destroy);
mIsDestroyed = true;
}
@@ -189,13 +200,12 @@ public class RegionSamplingHelper implements View.OnAttachStateChangeListener,
// We only want to re-register if something actually changed
unregisterSamplingListener();
mSamplingListenerRegistered = true;
- SurfaceControl wrappedStopLayer = stopLayerControl == null
- ? null : new SurfaceControl(stopLayerControl, "regionSampling");
+ SurfaceControl wrappedStopLayer = wrap(stopLayerControl);
mBackgroundExecutor.execute(() -> {
if (wrappedStopLayer != null && !wrappedStopLayer.isValid()) {
return;
}
- CompositionSamplingListener.register(mSamplingListener, DEFAULT_DISPLAY,
+ mCompositionSamplingListener.register(mSamplingListener, DEFAULT_DISPLAY,
wrappedStopLayer, mSamplingRequestBounds);
});
mRegisteredSamplingBounds.set(mSamplingRequestBounds);
@@ -208,14 +218,21 @@ public class RegionSamplingHelper implements View.OnAttachStateChangeListener,
}
}
+ @VisibleForTesting
+ protected SurfaceControl wrap(SurfaceControl stopLayerControl) {
+ return stopLayerControl == null ? null : new SurfaceControl(stopLayerControl,
+ "regionSampling");
+ }
+
private void unregisterSamplingListener() {
if (mSamplingListenerRegistered) {
mSamplingListenerRegistered = false;
SurfaceControl wrappedStopLayer = mWrappedStopLayer;
mRegisteredStopLayer = null;
+ mWrappedStopLayer = null;
mRegisteredSamplingBounds.setEmpty();
mBackgroundExecutor.execute(() -> {
- CompositionSamplingListener.unregister(mSamplingListener);
+ mCompositionSamplingListener.unregister(mSamplingListener);
if (wrappedStopLayer != null && wrappedStopLayer.isValid()) {
wrappedStopLayer.release();
}
@@ -299,4 +316,19 @@ public class RegionSamplingHelper implements View.OnAttachStateChangeListener,
return true;
}
}
+
+ @VisibleForTesting
+ public static class SysuiCompositionSamplingListener {
+ public void register(CompositionSamplingListener listener,
+ int displayId, SurfaceControl stopLayer, Rect samplingArea) {
+ CompositionSamplingListener.register(listener, displayId, stopLayer, samplingArea);
+ }
+
+ /**
+ * Unregisters a sampling listener.
+ */
+ public void unregister(CompositionSamplingListener listener) {
+ CompositionSamplingListener.unregister(listener);
+ }
+ }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
index e84b552d65eb..8d26ddd5aa23 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
@@ -205,8 +205,10 @@ public class RemoteAnimationAdapterCompat {
@Override
@SuppressLint("NewApi")
public void run() {
- counterLauncher.cleanUp(info.getRootLeash());
- counterWallpaper.cleanUp(info.getRootLeash());
+ final SurfaceControl.Transaction finishTransaction =
+ new SurfaceControl.Transaction();
+ counterLauncher.cleanUp(finishTransaction);
+ counterWallpaper.cleanUp(finishTransaction);
// Release surface references now. This is apparently to free GPU memory
// while doing quick operations (eg. during CTS).
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
@@ -216,7 +218,7 @@ public class RemoteAnimationAdapterCompat {
leashMap.valueAt(i).release();
}
try {
- finishCallback.onTransitionFinished(null /* wct */, null /* sct */);
+ finishCallback.onTransitionFinished(null /* wct */, finishTransaction);
} catch (RemoteException e) {
Log.e("ActivityOptionsCompat", "Failed to call app controlled animation"
+ " finished callback", e);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
index 22698a853726..a274b74f336b 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
@@ -89,6 +89,7 @@ class ScopedUnfoldTransitionProgressProvider @JvmOverloads constructor(
override fun destroy() {
source?.removeCallback(this)
+ source?.destroy()
}
override fun onTransitionStarted() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
new file mode 100644
index 000000000000..214b284ac4b9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard
+
+import android.content.Context
+import android.hardware.biometrics.BiometricSourceType
+import com.android.internal.annotations.VisibleForTesting
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.widget.LockPatternUtils
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE
+import com.android.keyguard.KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import javax.inject.Inject
+
+/**
+ * Logs events when primary authentication requirements change. Primary authentication is considered
+ * authentication using pin/pattern/password input.
+ *
+ * See [PrimaryAuthRequiredEvent] for all the events and their descriptions.
+ */
+@SysUISingleton
+class KeyguardBiometricLockoutLogger @Inject constructor(
+ context: Context?,
+ private val uiEventLogger: UiEventLogger,
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ private val dumpManager: DumpManager
+) : CoreStartable(context) {
+ private var fingerprintLockedOut = false
+ private var faceLockedOut = false
+ private var encryptedOrLockdown = false
+ private var unattendedUpdate = false
+ private var timeout = false
+
+ override fun start() {
+ dumpManager.registerDumpable(this)
+ mKeyguardUpdateMonitorCallback.onStrongAuthStateChanged(
+ KeyguardUpdateMonitor.getCurrentUser())
+ keyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback)
+ }
+
+ private val mKeyguardUpdateMonitorCallback: KeyguardUpdateMonitorCallback =
+ object : KeyguardUpdateMonitorCallback() {
+ override fun onLockedOutStateChanged(biometricSourceType: BiometricSourceType) {
+ if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
+ val lockedOut = keyguardUpdateMonitor.isFingerprintLockedOut
+ if (lockedOut && !fingerprintLockedOut) {
+ uiEventLogger.log(
+ PrimaryAuthRequiredEvent.PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT)
+ } else if (!lockedOut && fingerprintLockedOut) {
+ uiEventLogger.log(
+ PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT_RESET)
+ }
+ fingerprintLockedOut = lockedOut
+ } else if (biometricSourceType == BiometricSourceType.FACE) {
+ val lockedOut = keyguardUpdateMonitor.isFaceLockedOut
+ if (lockedOut && !faceLockedOut) {
+ uiEventLogger.log(
+ PrimaryAuthRequiredEvent.PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT)
+ } else if (!lockedOut && faceLockedOut) {
+ uiEventLogger.log(
+ PrimaryAuthRequiredEvent.PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT_RESET)
+ }
+ faceLockedOut = lockedOut
+ }
+ }
+
+ override fun onStrongAuthStateChanged(userId: Int) {
+ if (userId != KeyguardUpdateMonitor.getCurrentUser()) {
+ return
+ }
+ val strongAuthFlags = keyguardUpdateMonitor.strongAuthTracker
+ .getStrongAuthForUser(userId)
+
+ val newEncryptedOrLockdown = keyguardUpdateMonitor.isEncryptedOrLockdown(userId)
+ if (newEncryptedOrLockdown && !encryptedOrLockdown) {
+ uiEventLogger.log(
+ PrimaryAuthRequiredEvent.PRIMARY_AUTH_REQUIRED_ENCRYPTED_OR_LOCKDOWN)
+ }
+ encryptedOrLockdown = newEncryptedOrLockdown
+
+ val newUnattendedUpdate = isUnattendedUpdate(strongAuthFlags)
+ if (newUnattendedUpdate && !unattendedUpdate) {
+ uiEventLogger.log(PrimaryAuthRequiredEvent.PRIMARY_AUTH_REQUIRED_UNATTENDED_UPDATE)
+ }
+ unattendedUpdate = newUnattendedUpdate
+
+ val newTimeout = isStrongAuthTimeout(strongAuthFlags)
+ if (newTimeout && !timeout) {
+ uiEventLogger.log(PrimaryAuthRequiredEvent.PRIMARY_AUTH_REQUIRED_TIMEOUT)
+ }
+ timeout = newTimeout
+ }
+ }
+
+ private fun isUnattendedUpdate(
+ @LockPatternUtils.StrongAuthTracker.StrongAuthFlags flags: Int
+ ) = containsFlag(flags, STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE)
+
+ private fun isStrongAuthTimeout(
+ @LockPatternUtils.StrongAuthTracker.StrongAuthFlags flags: Int
+ ) = containsFlag(flags, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) ||
+ containsFlag(flags, STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT)
+
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
+ pw.println(" mFingerprintLockedOut=$fingerprintLockedOut")
+ pw.println(" mFaceLockedOut=$faceLockedOut")
+ pw.println(" mIsEncryptedOrLockdown=$encryptedOrLockdown")
+ pw.println(" mIsUnattendedUpdate=$unattendedUpdate")
+ pw.println(" mIsTimeout=$timeout")
+ }
+
+ /**
+ * Events pertaining to whether primary authentication (pin/pattern/password input) is required
+ * for device entry.
+ */
+ @VisibleForTesting
+ enum class PrimaryAuthRequiredEvent(private val mId: Int) : UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "Fingerprint cannot be used to authenticate for device entry. This" +
+ "can persist until the next primary auth or may timeout.")
+ PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT(924),
+
+ @UiEvent(doc = "Fingerprint can be used to authenticate for device entry.")
+ PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT_RESET(925),
+
+ @UiEvent(doc = "Face cannot be used to authenticate for device entry.")
+ PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT(926),
+
+ @UiEvent(doc = "Face can be used to authenticate for device entry.")
+ PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT_RESET(927),
+
+ @UiEvent(doc = "Device is encrypted (ie: after reboot) or device is locked down by DPM " +
+ "or a manual user lockdown.")
+ PRIMARY_AUTH_REQUIRED_ENCRYPTED_OR_LOCKDOWN(928),
+
+ @UiEvent(doc = "Primary authentication is required because it hasn't been used for a " +
+ "time required by a device admin or because primary auth hasn't been used for a " +
+ "time after a non-strong biometric (weak or convenience) is used to unlock the " +
+ "device.")
+ PRIMARY_AUTH_REQUIRED_TIMEOUT(929),
+
+ @UiEvent(doc = "Strong authentication is required to prepare for unattended upgrade.")
+ PRIMARY_AUTH_REQUIRED_UNATTENDED_UPDATE(931);
+
+ override fun getId(): Int {
+ return mId
+ }
+ }
+
+ companion object {
+ private fun containsFlag(strongAuthFlags: Int, flagCheck: Int): Boolean {
+ return strongAuthFlags and flagCheck != 0
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
index 03f04d3a2cde..36fe5ba1a851 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
@@ -64,3 +64,19 @@ data class KeyguardFaceListenModel(
val secureCameraLaunched: Boolean,
val switchingUser: Boolean
) : KeyguardListenModel()
+/**
+ * Verbose debug information associated with [KeyguardUpdateMonitor.shouldTriggerActiveUnlock].
+ */
+data class KeyguardActiveUnlockModel(
+ @CurrentTimeMillisLong override val timeMillis: Long,
+ override val userId: Int,
+ override val listening: Boolean,
+ // keep sorted
+ val authInterruptActive: Boolean,
+ val encryptedOrTimedOut: Boolean,
+ val fpLockout: Boolean,
+ val lockDown: Boolean,
+ val switchingUser: Boolean,
+ val triggerActiveUnlockForAssistant: Boolean,
+ val userCanDismissLockScreen: Boolean
+) : KeyguardListenModel()
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
index f13a59a84811..210f5e763911 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
@@ -32,15 +32,17 @@ class KeyguardListenQueue(
) {
private val faceQueue = ArrayDeque<KeyguardFaceListenModel>()
private val fingerprintQueue = ArrayDeque<KeyguardFingerprintListenModel>()
+ private val activeUnlockQueue = ArrayDeque<KeyguardActiveUnlockModel>()
@get:VisibleForTesting val models: List<KeyguardListenModel>
- get() = faceQueue + fingerprintQueue
+ get() = faceQueue + fingerprintQueue + activeUnlockQueue
/** Push a [model] to the queue (will be logged until the queue exceeds [sizePerModality]). */
fun add(model: KeyguardListenModel) {
val queue = when (model) {
is KeyguardFaceListenModel -> faceQueue.apply { add(model) }
is KeyguardFingerprintListenModel -> fingerprintQueue.apply { add(model) }
+ is KeyguardActiveUnlockModel -> activeUnlockQueue.apply { add(model) }
}
if (queue.size > sizePerModality) {
@@ -63,5 +65,9 @@ class KeyguardListenQueue(
for (model in fingerprintQueue) {
writer.println(stringify(model))
}
+ writer.println(" Active unlock triggers (last ${activeUnlockQueue.size} calls):")
+ for (model in activeUnlockQueue) {
+ writer.println(stringify(model))
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index b5ea498f185d..3fab72441c89 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -616,9 +616,13 @@ public class KeyguardSecurityContainer extends FrameLayout {
final View view = getChildAt(i);
if (view.getVisibility() != GONE) {
int updatedWidthMeasureSpec = mViewMode.getChildWidthMeasureSpec(widthMeasureSpec);
+ final LayoutParams lp = (LayoutParams) view.getLayoutParams();
+
+ // When using EXACTLY spec, measure will use the layout width if > 0. Set before
+ // measuring the child
+ lp.width = MeasureSpec.getSize(updatedWidthMeasureSpec);
measureChildWithMargins(view, updatedWidthMeasureSpec, 0, heightMeasureSpec, 0);
- final LayoutParams lp = (LayoutParams) view.getLayoutParams();
maxWidth = Math.max(maxWidth,
view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
maxHeight = Math.max(maxHeight,
@@ -969,7 +973,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
public int getChildWidthMeasureSpec(int parentWidthMeasureSpec) {
return MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(parentWidthMeasureSpec) / 2,
- MeasureSpec.getMode(parentWidthMeasureSpec));
+ MeasureSpec.EXACTLY);
}
@Override
@@ -1026,7 +1030,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
public int getChildWidthMeasureSpec(int parentWidthMeasureSpec) {
return MeasureSpec.makeMeasureSpec(
MeasureSpec.getSize(parentWidthMeasureSpec) / 2,
- MeasureSpec.getMode(parentWidthMeasureSpec));
+ MeasureSpec.EXACTLY);
}
private void updateSecurityViewGravity() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 2fb2211150ec..49a802235619 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -51,6 +51,8 @@ import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -83,6 +85,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
private final FalsingManager mFalsingManager;
private final UserSwitcherController mUserSwitcherController;
private final GlobalSettings mGlobalSettings;
+ private final FeatureFlags mFeatureFlags;
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
@@ -238,6 +241,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
FalsingCollector falsingCollector,
FalsingManager falsingManager,
UserSwitcherController userSwitcherController,
+ FeatureFlags featureFlags,
GlobalSettings globalSettings) {
super(view);
mLockPatternUtils = lockPatternUtils;
@@ -255,6 +259,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mFalsingCollector = falsingCollector;
mFalsingManager = falsingManager;
mUserSwitcherController = userSwitcherController;
+ mFeatureFlags = featureFlags;
mGlobalSettings = globalSettings;
}
@@ -510,7 +515,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
}
private boolean canDisplayUserSwitcher() {
- return getResources().getBoolean(R.bool.bouncer_display_user_switcher);
+ return mFeatureFlags.isEnabled(Flags.BOUNCER_USER_SWITCHER);
}
private void configureMode() {
@@ -615,6 +620,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
private final FalsingCollector mFalsingCollector;
private final FalsingManager mFalsingManager;
private final GlobalSettings mGlobalSettings;
+ private final FeatureFlags mFeatureFlags;
private final UserSwitcherController mUserSwitcherController;
@Inject
@@ -632,6 +638,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
FalsingCollector falsingCollector,
FalsingManager falsingManager,
UserSwitcherController userSwitcherController,
+ FeatureFlags featureFlags,
GlobalSettings globalSettings) {
mView = view;
mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;
@@ -645,6 +652,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mConfigurationController = configurationController;
mFalsingCollector = falsingCollector;
mFalsingManager = falsingManager;
+ mFeatureFlags = featureFlags;
mGlobalSettings = globalSettings;
mUserSwitcherController = userSwitcherController;
}
@@ -656,8 +664,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
mKeyguardStateController, securityCallback, mSecurityViewFlipperController,
mConfigurationController, mFalsingCollector, mFalsingManager,
- mUserSwitcherController, mGlobalSettings);
+ mUserSwitcherController, mFeatureFlags, mGlobalSettings);
}
-
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 98721fd78a93..5276679ea104 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -37,6 +37,8 @@ import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.UserSwitchObserver;
import android.app.admin.DevicePolicyManager;
@@ -102,6 +104,8 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
@@ -109,6 +113,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.Assert;
+import com.android.systemui.util.NotificationChannels;
import com.android.systemui.util.RingerModeTracker;
import com.google.android.collect.Lists;
@@ -143,8 +148,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
private static final boolean DEBUG_FACE = Build.IS_DEBUGGABLE;
private static final boolean DEBUG_FINGERPRINT = Build.IS_DEBUGGABLE;
+ private static final boolean DEBUG_ACTIVE_UNLOCK = Build.IS_DEBUGGABLE;
private static final boolean DEBUG_SPEW = false;
private static final int BIOMETRIC_LOCKOUT_RESET_DELAY_MS = 600;
+ private int mNumActiveUnlockTriggers = 0;
private static final String ACTION_FACE_UNLOCK_STARTED
= "com.android.facelock.FACE_UNLOCK_STARTED";
@@ -183,7 +190,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private static final int MSG_USER_STOPPED = 340;
private static final int MSG_USER_REMOVED = 341;
private static final int MSG_KEYGUARD_GOING_AWAY = 342;
- private static final int MSG_LOCK_SCREEN_MODE = 343;
private static final int MSG_TIME_FORMAT_UPDATE = 344;
private static final int MSG_REQUIRE_NFC_UNLOCK = 345;
@@ -221,7 +227,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;
- private static final int DEFAULT_CHARGING_VOLTAGE_MICRO_VOLT = 5000000;
/**
* If no cancel signal has been received after this amount of time, set the biometric running
* state to stopped to allow Keyguard to retry authentication.
@@ -231,7 +236,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private static final ComponentName FALLBACK_HOME_COMPONENT = new ComponentName(
"com.android.settings", "com.android.settings.FallbackHome");
-
/**
* If true, the system is in the half-boot-to-decryption-screen state.
* Prudently disable lockscreen.
@@ -334,6 +338,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private final Executor mBackgroundExecutor;
private SensorPrivacyManager mSensorPrivacyManager;
+ private FeatureFlags mFeatureFlags;
private int mFaceAuthUserId;
/**
@@ -1250,7 +1255,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
}
- private boolean isEncryptedOrLockdown(int userId) {
+ /**
+ * Returns true if primary authentication is required for the given user due to lockdown
+ * or encryption after reboot.
+ */
+ public boolean isEncryptedOrLockdown(int userId) {
final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(userId);
final boolean isLockDown =
containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
@@ -1311,6 +1320,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
void setAssistantVisible(boolean assistantVisible) {
mAssistantVisible = assistantVisible;
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
+ if (mAssistantVisible) {
+ requestActiveUnlock();
+ }
}
static class DisplayClientState {
@@ -1650,6 +1662,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp");
Assert.isMainThread();
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
+ requestActiveUnlock();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1777,7 +1790,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
AuthController authController,
TelephonyListenerManager telephonyListenerManager,
InteractionJankMonitor interactionJankMonitor,
- LatencyTracker latencyTracker) {
+ LatencyTracker latencyTracker,
+ FeatureFlags featureFlags) {
mContext = context;
mSubscriptionManager = SubscriptionManager.from(context);
mTelephonyListenerManager = telephonyListenerManager;
@@ -1795,6 +1809,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mAuthController = authController;
dumpManager.registerDumpable(getClass().getName(), this);
mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
+ mFeatureFlags = featureFlags;
mHandler = new Handler(mainLooper) {
@Override
@@ -2180,6 +2195,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
mAuthInterruptActive = active;
updateFaceListeningState(BIOMETRIC_ACTION_UPDATE);
+ requestActiveUnlock();
}
/**
@@ -2228,6 +2244,97 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
+ /**
+ * Attempts to trigger active unlock.
+ */
+ public void requestActiveUnlock() {
+ // If this message exists, FP has already authenticated, so wait until that is handled
+ if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
+ return;
+ }
+
+ if (shouldTriggerActiveUnlock() && mFeatureFlags.isEnabled(Flags.ACTIVE_UNLOCK)) {
+ // TODO (b/192405661): call new TrustManager API
+ mNumActiveUnlockTriggers++;
+ Log.d("ActiveUnlock", "would have triggered times=" + mNumActiveUnlockTriggers);
+ showActiveUnlockNotification(mNumActiveUnlockTriggers);
+ }
+ }
+
+ /**
+ * TODO (b/192405661): Only for testing. Remove before release.
+ */
+ private void showActiveUnlockNotification(int times) {
+ final String message = "Active unlock triggered " + times + " times.";
+ final Notification.Builder nb =
+ new Notification.Builder(mContext, NotificationChannels.GENERAL)
+ .setSmallIcon(R.drawable.ic_volume_ringer)
+ .setContentTitle(message)
+ .setStyle(new Notification.BigTextStyle().bigText(message));
+ mContext.getSystemService(NotificationManager.class).notifyAsUser(
+ "active_unlock",
+ 0,
+ nb.build(),
+ UserHandle.ALL);
+ }
+
+ private boolean shouldTriggerActiveUnlock() {
+ // TODO: check if active unlock is ENABLED / AVAILABLE
+
+ // Triggers:
+ final boolean triggerActiveUnlockForAssistant = shouldTriggerActiveUnlockForAssistant();
+ final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep
+ && mStatusBarState != StatusBarState.SHADE_LOCKED;
+
+ // Gates:
+ final int user = getCurrentUser();
+
+ // No need to trigger active unlock if we're already unlocked or don't have
+ // pin/pattern/password setup
+ final boolean userCanDismissLockScreen = getUserCanSkipBouncer(user)
+ || !mLockPatternUtils.isSecure(user);
+
+ // Don't trigger active unlock if fp is locked out TODO: confirm this one
+ final boolean fpLockedout = mFingerprintLockedOut || mFingerprintLockedOutPermanent;
+
+ // Don't trigger active unlock if primary auth is required
+ final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user);
+ final boolean isLockDown =
+ containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
+ || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+ final boolean isEncryptedOrTimedOut =
+ containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
+ || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
+
+ final boolean shouldTriggerActiveUnlock =
+ (mAuthInterruptActive || triggerActiveUnlockForAssistant || awakeKeyguard)
+ && !mSwitchingUser
+ && !userCanDismissLockScreen
+ && !fpLockedout
+ && !isLockDown
+ && !isEncryptedOrTimedOut
+ && !mKeyguardGoingAway
+ && !mSecureCameraLaunched;
+
+ // Aggregate relevant fields for debug logging.
+ if (DEBUG_ACTIVE_UNLOCK || DEBUG_SPEW) {
+ maybeLogListenerModelData(
+ new KeyguardActiveUnlockModel(
+ System.currentTimeMillis(),
+ user,
+ shouldTriggerActiveUnlock,
+ mAuthInterruptActive,
+ isEncryptedOrTimedOut,
+ fpLockedout,
+ isLockDown,
+ mSwitchingUser,
+ triggerActiveUnlockForAssistant,
+ userCanDismissLockScreen));
+ }
+
+ return shouldTriggerActiveUnlock;
+ }
+
private boolean shouldListenForFingerprintAssistant() {
BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(getCurrentUser());
return mAssistantVisible && mKeyguardOccluded
@@ -2242,6 +2349,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
&& !mUserHasTrust.get(getCurrentUser(), false);
}
+ private boolean shouldTriggerActiveUnlockForAssistant() {
+ return mAssistantVisible && mKeyguardOccluded
+ && !mUserHasTrust.get(getCurrentUser(), false);
+ }
+
@VisibleForTesting
protected boolean shouldListenForFingerprint(boolean isUdfps) {
final int user = getCurrentUser();
@@ -2406,6 +2518,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
Log.v(TAG, model.toString());
}
+ if (DEBUG_ACTIVE_UNLOCK
+ && model instanceof KeyguardActiveUnlockModel
+ && model.getListening()) {
+ mListenModels.add(model);
+ return;
+ }
+
// Add model data to the historical buffer.
final boolean notYetRunning =
(DEBUG_FACE
@@ -2514,6 +2633,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return mFingerprintLockedOut || mFingerprintLockedOutPermanent;
}
+ public boolean isFaceLockedOut() {
+ return mFaceLockedOutPermanent;
+ }
+
/**
* If biometrics hardware is available, not disabled, and user has enrolled templates.
* This does NOT check if the device is encrypted or in lockdown.
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 33538ec25fcd..a100cb8caf98 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -342,7 +342,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable {
mDisplayManager.getDisplay(DEFAULT_DISPLAY).getMetrics(metrics);
mDensity = metrics.density;
- mExecutor.execute(() -> mTunerService.addTunable(this, SIZE));
+ mMainExecutor.execute(() -> mTunerService.addTunable(this, SIZE));
// Watch color inversion and invert the overlay as needed.
if (mColorInversionSetting == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index fd7ae323e88f..d20844143ad6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -53,6 +53,7 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
@@ -130,6 +131,7 @@ public class UdfpsController implements DozeReceiver {
// 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;
+ @NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator;
// Tracks the velocity of a touch to help filter out the touches that move too fast.
@Nullable private VelocityTracker mVelocityTracker;
@@ -198,7 +200,8 @@ public class UdfpsController implements DozeReceiver {
mLockscreenShadeTransitionController, mConfigurationController,
mSystemClock, mKeyguardStateController,
mUnlockedScreenOffAnimationController, mSensorProps, mHbmProvider,
- reason, callback, UdfpsController.this::onTouch)));
+ reason, callback, UdfpsController.this::onTouch,
+ mActivityLaunchAnimator)));
}
@Override
@@ -487,7 +490,8 @@ public class UdfpsController implements DozeReceiver {
@NonNull SystemClock systemClock,
@NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
@NonNull SystemUIDialogManager dialogManager,
- @NonNull LatencyTracker latencyTracker) {
+ @NonNull LatencyTracker latencyTracker,
+ @NonNull ActivityLaunchAnimator activityLaunchAnimator) {
mContext = context;
mExecution = execution;
mVibrator = vibrator;
@@ -516,6 +520,7 @@ public class UdfpsController implements DozeReceiver {
mSystemClock = systemClock;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
mLatencyTracker = latencyTracker;
+ mActivityLaunchAnimator = activityLaunchAnimator;
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index e0912508d178..590963b2ff48 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -41,6 +41,7 @@ import android.view.accessibility.AccessibilityManager.TouchExplorationStateChan
import androidx.annotation.LayoutRes
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.R
+import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -81,7 +82,8 @@ class UdfpsControllerOverlay(
private var hbmProvider: UdfpsHbmProvider,
@ShowReason val requestReason: Int,
private val controllerCallback: IUdfpsOverlayControllerCallback,
- private val onTouch: (View, MotionEvent, Boolean) -> Boolean
+ private val onTouch: (View, MotionEvent, Boolean) -> Boolean,
+ private val activityLaunchAnimator: ActivityLaunchAnimator
) {
/** The view, when [isShowing], or null. */
var overlayView: UdfpsView? = null
@@ -200,7 +202,8 @@ class UdfpsControllerOverlay(
keyguardStateController,
unlockedScreenOffAnimationController,
dialogManager,
- controller
+ controller,
+ activityLaunchAnimator
)
}
BiometricOverlayConstants.REASON_AUTH_BP -> {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index d90a746b0f79..8b7aa093600c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -25,6 +25,7 @@ import android.view.MotionEvent;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
@@ -55,6 +56,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@NonNull private final UdfpsController mUdfpsController;
@NonNull private final UnlockedScreenOffAnimationController
mUnlockedScreenOffAnimationController;
+ @NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator;
private boolean mShowingUdfpsBouncer;
private boolean mUdfpsRequested;
@@ -66,6 +68,8 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
private long mLastUdfpsBouncerShowTime = -1;
private float mStatusBarExpansion;
private boolean mLaunchTransitionFadingAway;
+ private boolean mIsLaunchingActivity;
+ private float mActivityLaunchProgress;
/**
* hidden amount of pin/pattern/password bouncer
@@ -88,7 +92,8 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@NonNull KeyguardStateController keyguardStateController,
@NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
@NonNull SystemUIDialogManager systemUIDialogManager,
- @NonNull UdfpsController udfpsController) {
+ @NonNull UdfpsController udfpsController,
+ @NonNull ActivityLaunchAnimator activityLaunchAnimator) {
super(view, statusBarStateController, panelExpansionStateManager, systemUIDialogManager,
dumpManager);
mKeyguardViewManager = statusBarKeyguardViewManager;
@@ -99,6 +104,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
mKeyguardStateController = keyguardStateController;
mUdfpsController = udfpsController;
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+ mActivityLaunchAnimator = activityLaunchAnimator;
}
@Override
@@ -136,6 +142,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(this);
mUnlockedScreenOffAnimationController.addCallback(mUnlockedScreenOffCallback);
+ mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener);
}
@Override
@@ -153,6 +160,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
mLockScreenShadeTransitionController.setUdfpsKeyguardViewController(null);
}
mUnlockedScreenOffAnimationController.removeCallback(mUnlockedScreenOffCallback);
+ mActivityLaunchAnimator.removeListener(mActivityLaunchAnimatorListener);
}
@Override
@@ -294,6 +302,12 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
0f, 255f);
if (!mShowingUdfpsBouncer) {
alpha *= (1.0f - mTransitionToFullShadeProgress);
+
+ // Fade out the icon if we are animating an activity launch over the lockscreen and the
+ // activity didn't request the UDFPS.
+ if (mIsLaunchingActivity && !mUdfpsRequested) {
+ alpha *= (1.0f - mActivityLaunchProgress);
+ }
}
mView.setUnpausedAlpha(alpha);
}
@@ -426,4 +440,26 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
private final UnlockedScreenOffAnimationController.Callback mUnlockedScreenOffCallback =
(linear, eased) -> mStateListener.onDozeAmountChanged(linear, eased);
+
+ private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener =
+ new ActivityLaunchAnimator.Listener() {
+ @Override
+ public void onLaunchAnimationStart() {
+ mIsLaunchingActivity = true;
+ mActivityLaunchProgress = 0f;
+ updateAlpha();
+ }
+
+ @Override
+ public void onLaunchAnimationEnd() {
+ mIsLaunchingActivity = false;
+ updateAlpha();
+ }
+
+ @Override
+ public void onLaunchAnimationProgress(float linearProgress) {
+ mActivityLaunchProgress = linearProgress;
+ updateAlpha();
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 977e46ac3b44..d2ded71487dc 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -131,6 +131,12 @@ class ControlsProviderLifecycleManager(
wrapper = null
bindService(false)
}
+
+ override fun onNullBinding(name: ComponentName?) {
+ if (DEBUG) Log.d(TAG, "onNullBinding $name")
+ wrapper = null
+ context.unbindService(this)
+ }
}
private fun handlePendingServiceMethods() {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index cffb2f79ebfb..b23569241f59 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -28,6 +28,8 @@ import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerR
import com.android.systemui.media.taptotransfer.sender.MediaTttChipControllerSender;
import com.android.systemui.people.PeopleProvider;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.unfold.FoldStateLogger;
+import com.android.systemui.unfold.FoldStateLoggingProvider;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.unfold.UnfoldLatencyTracker;
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
@@ -139,6 +141,8 @@ public interface SysUIComponent {
getMediaTttChipControllerReceiver();
getMediaTttCommandLineHelper();
getUnfoldLatencyTracker().init();
+ getFoldStateLoggingProvider().ifPresent(FoldStateLoggingProvider::init);
+ getFoldStateLogger().ifPresent(FoldStateLogger::init);
}
/**
@@ -166,6 +170,18 @@ public interface SysUIComponent {
UnfoldLatencyTracker getUnfoldLatencyTracker();
/**
+ * Creates a FoldStateLoggingProvider.
+ */
+ @SysUISingleton
+ Optional<FoldStateLoggingProvider> getFoldStateLoggingProvider();
+
+ /**
+ * Creates a FoldStateLogger.
+ */
+ @SysUISingleton
+ Optional<FoldStateLogger> getFoldStateLogger();
+
+ /**
* Main dependency providing module.
*/
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 9dddbb1d67c6..c0da57f58043 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -16,6 +16,7 @@
package com.android.systemui.dagger;
+import com.android.keyguard.KeyguardBiometricLockoutLogger;
import com.android.systemui.CoreStartable;
import com.android.systemui.LatencyTester;
import com.android.systemui.ScreenDecorations;
@@ -90,6 +91,13 @@ public abstract class SystemUIBinder {
@ClassKey(KeyguardViewMediator.class)
public abstract CoreStartable bindKeyguardViewMediator(KeyguardViewMediator sysui);
+ /** Inject into KeyguardBiometricLockoutLogger. */
+ @Binds
+ @IntoMap
+ @ClassKey(KeyguardBiometricLockoutLogger.class)
+ public abstract CoreStartable bindKeyguardBiometricLockoutLogger(
+ KeyguardBiometricLockoutLogger sysui);
+
/** Inject into LatencyTests. */
@Binds
@IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index c4a58db4f41a..9bc3f176e91a 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -59,6 +59,7 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
@@ -208,6 +209,7 @@ public abstract class SystemUIModule {
NotificationInterruptStateProvider interruptionStateProvider,
ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager,
NotificationGroupManagerLegacy groupManager, NotificationEntryManager entryManager,
+ CommonNotifCollection notifCollection,
NotifPipeline notifPipeline, SysUiState sysUiState,
NotifPipelineFlags notifPipelineFlags, DumpManager dumpManager,
@Main Executor sysuiMainExecutor) {
@@ -216,7 +218,7 @@ public abstract class SystemUIModule {
configurationController, statusBarService, notificationManager,
visibilityProvider,
interruptionStateProvider, zenModeController, notifUserManager,
- groupManager, entryManager, notifPipeline, sysUiState, notifPipelineFlags,
- dumpManager, sysuiMainExecutor));
+ groupManager, entryManager, notifCollection, notifPipeline, sysUiState,
+ notifPipelineFlags, dumpManager, sysuiMainExecutor));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 726f8656767c..5d6c2a247df3 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -57,8 +57,10 @@ public class Flags {
/***************************************/
// 200 - keyguard/lockscreen
- public static final BooleanFlag KEYGUARD_LAYOUT =
- new BooleanFlag(200, true);
+
+ // ** Flag retired **
+ // public static final BooleanFlag KEYGUARD_LAYOUT =
+ // new BooleanFlag(200, true);
public static final BooleanFlag LOCKSCREEN_ANIMATIONS =
new BooleanFlag(201, true);
@@ -69,6 +71,12 @@ public class Flags {
public static final ResourceBooleanFlag CHARGING_RIPPLE =
new ResourceBooleanFlag(203, R.bool.flag_charging_ripple);
+ public static final ResourceBooleanFlag BOUNCER_USER_SWITCHER =
+ new ResourceBooleanFlag(204, R.bool.config_enableBouncerUserSwitcher);
+
+ public static final ResourceBooleanFlag ACTIVE_UNLOCK =
+ new ResourceBooleanFlag(205, R.bool.flag_active_unlock);
+
/***************************************/
// 300 - power menu
public static final BooleanFlag POWER_MENU_LITE =
@@ -123,7 +131,8 @@ public class Flags {
/***************************************/
// 900 - media
public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, false);
- public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, false);
+ public static final BooleanFlag MEDIA_SESSION_ACTIONS = new BooleanFlag(901, true);
+ public static final BooleanFlag MEDIA_SESSION_LAYOUT = new BooleanFlag(902, false);
// Pay no attention to the reflection behind the curtain.
// ========================== Curtain ==========================
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4658a745b680..094b1927480d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -100,6 +100,7 @@ import com.android.keyguard.KeyguardViewController;
import com.android.keyguard.ViewMediatorCallback;
import com.android.keyguard.mediator.ScreenOnCoordinator;
import com.android.systemui.CoreStartable;
+import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -2345,16 +2346,20 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// Block the panel from expanding, in case we were doing a swipe to dismiss gesture.
mKeyguardViewControllerLazy.get().blockPanelExpansionFromCurrentTouch();
final boolean wasShowing = mShowing;
- onKeyguardExitFinished();
+ InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
- if (mKeyguardStateController.isDismissingFromSwipe() || wasShowing) {
- mKeyguardUnlockAnimationControllerLazy.get().hideKeyguardViewAfterRemoteAnimation();
- }
+ // Post layout changes to the next frame, so we don't hang at the end of the animation.
+ DejankUtils.postAfterTraversal(() -> {
+ onKeyguardExitFinished();
- finishSurfaceBehindRemoteAnimation(cancelled);
- mSurfaceBehindRemoteAnimationRequested = false;
- mKeyguardUnlockAnimationControllerLazy.get().notifyFinishedKeyguardExitAnimation();
- InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
+ if (mKeyguardStateController.isDismissingFromSwipe() || wasShowing) {
+ mKeyguardUnlockAnimationControllerLazy.get().hideKeyguardViewAfterRemoteAnimation();
+ }
+
+ finishSurfaceBehindRemoteAnimation(cancelled);
+ mSurfaceBehindRemoteAnimationRequested = false;
+ mKeyguardUnlockAnimationControllerLazy.get().notifyFinishedKeyguardExitAnimation();
+ });
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 29321b46328a..c404f7aa0fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -418,7 +418,7 @@ class MediaCarouselController @Inject constructor(
.elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
if (existingPlayer == null) {
var newPlayer = mediaControlPanelFactory.get()
- if (mediaFlags.areMediaSessionActionsEnabled()) {
+ if (mediaFlags.useMediaSessionLayout()) {
newPlayer.attachPlayer(
PlayerSessionViewHolder.create(LayoutInflater.from(context), mediaContent),
MediaViewController.TYPE.PLAYER_SESSION)
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 3c237223e31a..69a7ec3447aa 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -61,6 +61,7 @@ import com.android.systemui.util.animation.TransitionLayout;
import com.android.systemui.util.time.SystemClock;
import java.net.URISyntaxException;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
@@ -480,6 +481,24 @@ public class MediaControlPanel {
List<MediaAction> actionIcons = data.getActions();
List<Integer> actionsWhenCollapsed = data.getActionsToShowInCompact();
+ // If the session actions flag is enabled, but we're still using the regular layout, use
+ // the session actions anyways
+ if (mMediaFlags.areMediaSessionActionsEnabled() && data.getSemanticActions() != null) {
+ MediaButton semanticActions = data.getSemanticActions();
+
+ actionIcons = new ArrayList<MediaAction>();
+ actionIcons.add(semanticActions.getStartCustom());
+ actionIcons.add(semanticActions.getPrevOrCustom());
+ actionIcons.add(semanticActions.getPlayOrPause());
+ actionIcons.add(semanticActions.getNextOrCustom());
+ actionIcons.add(semanticActions.getEndCustom());
+
+ actionsWhenCollapsed = new ArrayList<Integer>();
+ actionsWhenCollapsed.add(1);
+ actionsWhenCollapsed.add(2);
+ actionsWhenCollapsed.add(3);
+ }
+
int i = 0;
for (; i < actionIcons.size() && i < ACTION_IDS.length; i++) {
int actionId = ACTION_IDS[i];
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
index b4a4b42d1509..b9795f1265fa 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
@@ -29,4 +29,12 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlags) {
fun areMediaSessionActionsEnabled(): Boolean {
return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS)
}
+
+ /**
+ * Check whether media controls should use the new session-based layout
+ */
+ fun useMediaSessionLayout(): Boolean {
+ return featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS) &&
+ featureFlags.isEnabled(Flags.MEDIA_SESSION_LAYOUT)
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 5fbdd88b9f66..ac816ba9e8d5 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -16,6 +16,7 @@
package com.android.systemui.navigationbar;
+import static android.inputmethodservice.InputMethodService.canImeRenderGesturalNavButtons;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
@@ -185,6 +186,17 @@ public class NavigationBarView extends FrameLayout implements
@Nullable
private Rect mOrientedHandleSamplingRegion;
+ /**
+ * {@code true} if the IME can render the back button and the IME switcher button.
+ *
+ * <p>The value must be used when and only when
+ * {@link com.android.systemui.shared.system.QuickStepContract#isGesturalMode(int)} returns
+ * {@code true}</p>
+ *
+ * <p>Cache the value here for better performance.</p>
+ */
+ private final boolean mImeCanRenderGesturalNavButtons = canImeRenderGesturalNavButtons();
+
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
private boolean mHomeAppearing;
@@ -760,9 +772,14 @@ public class NavigationBarView extends FrameLayout implements
updateRecentsIcon();
+ boolean isImeRenderingNavButtons = isGesturalMode(mNavBarMode)
+ && mImeCanRenderGesturalNavButtons;
+
// Update IME button visibility, a11y and rotate button always overrides the appearance
- mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher,
- (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
+ boolean disableImeSwitcher =
+ (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0
+ || isImeRenderingNavButtons;
+ mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher, !disableImeSwitcher);
mBarTransitions.reapplyDarkIntensity();
@@ -777,7 +794,8 @@ public class NavigationBarView extends FrameLayout implements
&& ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
boolean disableBack = !useAltBack && (mEdgeBackGestureHandler.isHandlingGestures()
- || ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0));
+ || ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0))
+ || isImeRenderingNavButtons;
// When screen pinning, don't hide back and home when connected service or back and
// recents buttons when disconnected from launcher service in screen pinning mode,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt b/packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
index 11c49496fc1d..bd2f64bb9874 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
@@ -59,6 +59,7 @@ class TileRequestDialog(
R.dimen.qs_tile_service_request_tile_width),
context.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size)
)
+ isSelected = true
}
val spacing = 0
setView(ll, spacing, spacing, spacing, spacing / 2)
@@ -68,12 +69,17 @@ class TileRequestDialog(
val tile = QSTileViewImpl(context, QSIconViewImpl(context), true)
val state = QSTile.BooleanState().apply {
label = tileData.label
+ handlesLongClick = false
icon = tileData.icon?.loadDrawable(context)?.let {
QSTileImpl.DrawableIcon(it)
} ?: ResourceIcon.get(R.drawable.android)
}
tile.onStateChanged(state)
- tile.isSelected = true
+ tile.post {
+ tile.stateDescription = ""
+ tile.isClickable = false
+ tile.isSelected = true
+ }
return tile
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 7cf0583206e1..2a21f421869b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -238,7 +238,7 @@ public abstract class AlertingNotificationManager implements NotificationLifetim
* @param key the key to check if removable
* @return true if the alert entry can be removed
*/
- protected boolean canRemoveImmediately(String key) {
+ public boolean canRemoveImmediately(String key) {
AlertEntry alertEntry = mAlertEntries.get(key);
return alertEntry == null || alertEntry.wasShownLongEnough()
|| alertEntry.mEntry.isRowDismissed();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt
index 73d3e2afac7c..8dc01f014192 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.charging
-import android.graphics.Color
import android.graphics.PointF
import android.graphics.RuntimeShader
import android.util.MathUtils
@@ -40,7 +39,7 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
uniform float in_time;
uniform float in_radius;
uniform float in_blur;
- uniform vec4 in_color;
+ layout(color) uniform vec4 in_color;
uniform float in_phase1;
uniform float in_phase2;
uniform float in_distortion_strength;"""
@@ -98,7 +97,7 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
var origin: PointF = PointF()
set(value) {
field = value
- setUniform("in_origin", floatArrayOf(value.x, value.y))
+ setFloatUniform("in_origin", value.x, value.y)
}
/**
@@ -107,9 +106,9 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
var progress: Float = 0.0f
set(value) {
field = value
- setUniform("in_radius",
+ setFloatUniform("in_radius",
(1 - (1 - value) * (1 - value) * (1 - value))* maxRadius)
- setUniform("in_blur", MathUtils.lerp(1f, 0.7f, value))
+ setFloatUniform("in_blur", MathUtils.lerp(1f, 0.7f, value))
}
/**
@@ -118,7 +117,7 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
var distortionStrength: Float = 0.0f
set(value) {
field = value
- setUniform("in_distortion_strength", value)
+ setFloatUniform("in_distortion_strength", value)
}
/**
@@ -127,9 +126,9 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
var time: Float = 0.0f
set(value) {
field = value * 0.001f
- setUniform("in_time", field)
- setUniform("in_phase1", field * 3f + 0.367f)
- setUniform("in_phase2", field * 7.2f * 1.531f)
+ setFloatUniform("in_time", field)
+ setFloatUniform("in_phase1", field * 3f + 0.367f)
+ setFloatUniform("in_phase2", field * 7.2f * 1.531f)
}
/**
@@ -138,8 +137,6 @@ class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
var color: Int = 0xffffff.toInt()
set(value) {
field = value
- val color = Color.valueOf(value)
- setUniform("in_color", floatArrayOf(color.red(),
- color.green(), color.blue(), color.alpha()))
+ setColorUniform("in_color", value)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt
index 5175977d4e81..22fbf9139f1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt
@@ -15,7 +15,6 @@
*/
package com.android.systemui.statusbar.charging
-import android.graphics.Color
import android.graphics.PointF
import android.graphics.RuntimeShader
import android.util.MathUtils
@@ -43,7 +42,7 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
uniform float in_fadeRing;
uniform float in_blur;
uniform float in_pixelDensity;
- uniform vec4 in_color;
+ layout(color) uniform vec4 in_color;
uniform float in_sparkle_strength;"""
private const val SHADER_LIB = """float triangleNoise(vec2 n) {
n = fract(n * vec2(5.3987, 5.4421));
@@ -122,7 +121,7 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
var radius: Float = 0.0f
set(value) {
field = value
- setUniform("in_maxRadius", value)
+ setFloatUniform("in_maxRadius", value)
}
/**
@@ -131,7 +130,7 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
var origin: PointF = PointF()
set(value) {
field = value
- setUniform("in_origin", floatArrayOf(value.x, value.y))
+ setFloatUniform("in_origin", value.x, value.y)
}
/**
@@ -140,10 +139,10 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
var progress: Float = 0.0f
set(value) {
field = value
- setUniform("in_progress", value)
- setUniform("in_radius",
+ setFloatUniform("in_progress", value)
+ setFloatUniform("in_radius",
(1 - (1 - value) * (1 - value) * (1 - value))* radius)
- setUniform("in_blur", MathUtils.lerp(1.25f, 0.5f, value))
+ setFloatUniform("in_blur", MathUtils.lerp(1.25f, 0.5f, value))
val fadeIn = subProgress(0f, 0.1f, value)
val fadeOutNoise = subProgress(0.4f, 1f, value)
@@ -153,9 +152,9 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
fadeCircle = subProgress(0f, 0.2f, value)
fadeOutRipple = subProgress(0.3f, 1f, value)
}
- setUniform("in_fadeSparkle", Math.min(fadeIn, 1 - fadeOutNoise))
- setUniform("in_fadeCircle", 1 - fadeCircle)
- setUniform("in_fadeRing", Math.min(fadeIn, 1 - fadeOutRipple))
+ setFloatUniform("in_fadeSparkle", Math.min(fadeIn, 1 - fadeOutNoise))
+ setFloatUniform("in_fadeCircle", 1 - fadeCircle)
+ setFloatUniform("in_fadeRing", Math.min(fadeIn, 1 - fadeOutRipple))
}
/**
@@ -164,7 +163,7 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
var time: Float = 0.0f
set(value) {
field = value
- setUniform("in_time", value)
+ setFloatUniform("in_time", value)
}
/**
@@ -173,9 +172,7 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
var color: Int = 0xffffff.toInt()
set(value) {
field = value
- val color = Color.valueOf(value)
- setUniform("in_color", floatArrayOf(color.red(),
- color.green(), color.blue(), color.alpha()))
+ setColorUniform("in_color", value)
}
/**
@@ -186,7 +183,7 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
var sparkleStrength: Float = 0.0f
set(value) {
field = value
- setUniform("in_sparkle_strength", value)
+ setFloatUniform("in_sparkle_strength", value)
}
/**
@@ -195,14 +192,14 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) {
var distortionStrength: Float = 0.0f
set(value) {
field = value
- setUniform("in_distort_radial", 75 * progress * value)
- setUniform("in_distort_xy", 75 * value)
+ setFloatUniform("in_distort_radial", 75 * progress * value)
+ setFloatUniform("in_distort_xy", 75 * value)
}
var pixelDensity: Float = 1.0f
set(value) {
field = value
- setUniform("in_pixelDensity", value)
+ setFloatUniform("in_pixelDensity", value)
}
var shouldFadeOutRipple: Boolean = true
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
index ed9663e9c672..f9f0b9da8778 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
@@ -179,23 +179,26 @@ public class HeadsUpCoordinator implements Coordinator {
@Override
public boolean shouldExtendLifetime(@NonNull NotificationEntry entry, int reason) {
- boolean isShowingHun = isCurrentlyShowingHun(entry);
- if (isShowingHun) {
+ boolean extend = !mHeadsUpManager.canRemoveImmediately(entry.getKey());
+ if (extend) {
if (isSticky(entry)) {
long removeAfterMillis = mHeadsUpManager.getEarliestRemovalTime(entry.getKey());
- if (removeAfterMillis <= 0) return false;
mExecutor.executeDelayed(() -> {
- // make sure that the entry was not updated
- long removeAfterMillis2 =
- mHeadsUpManager.getEarliestRemovalTime(entry.getKey());
- if (mNotifsExtendingLifetime.contains(entry) && removeAfterMillis2 <= 0) {
- mHeadsUpManager.removeNotification(entry.getKey(), true);
+ if (mNotifsExtendingLifetime.contains(entry)
+ && mHeadsUpManager.canRemoveImmediately(entry.getKey())) {
+ mHeadsUpManager.removeNotification(
+ entry.getKey(), /* releaseImmediately */ true);
}
}, removeAfterMillis);
+ } else {
+ // remove as early as possible
+ mExecutor.execute(
+ () -> mHeadsUpManager.removeNotification(
+ entry.getKey(), /* releaseImmediately */ false));
}
mNotifsExtendingLifetime.add(entry);
}
- return isShowingHun;
+ return extend;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
index 43a75a5d5da8..ad973927f21e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
@@ -24,16 +24,18 @@ import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.util.traceSection
-import javax.inject.Inject
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
/**
* Responsible for building and applying the "shade node spec": the list (tree) of things that
* currently populate the notification shade.
*/
-class ShadeViewManager constructor(
+class ShadeViewManager @AssistedInject constructor(
context: Context,
- listContainer: NotificationListContainer,
- private val stackController: NotifStackController,
+ @Assisted listContainer: NotificationListContainer,
+ @Assisted private val stackController: NotifStackController,
mediaContainerController: MediaContainerController,
featureManager: NotificationSectionsFeatureManager,
logger: ShadeViewDifferLogger,
@@ -68,20 +70,10 @@ class ShadeViewManager constructor(
}
}
-class ShadeViewManagerFactory @Inject constructor(
- private val context: Context,
- private val logger: ShadeViewDifferLogger,
- private val mediaContainerController: MediaContainerController,
- private val sectionsFeatureManager: NotificationSectionsFeatureManager,
- private val viewBarn: NotifViewBarn
-) {
- fun create(listContainer: NotificationListContainer, stackController: NotifStackController) =
- ShadeViewManager(
- context,
- listContainer,
- stackController,
- mediaContainerController,
- sectionsFeatureManager,
- logger,
- viewBarn)
+@AssistedFactory
+interface ShadeViewManagerFactory {
+ fun create(
+ listContainer: NotificationListContainer,
+ stackController: NotifStackController
+ ): ShadeViewManager
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 6218c7708020..624e7416d3ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -550,41 +550,32 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
public void removeFromTransientContainerForAdditionTo(ViewGroup newParent) {
final ViewParent parent = getParent();
final ViewGroup transientContainer = getTransientContainer();
- if (parent == null) {
- // If this view has no parent, the add will succeed, so just make sure the tracked
- // transient container is in sync with the lack of a parent.
- if (transientContainer != null) {
+ if (parent == null || parent == newParent) {
+ // If this view's current parent is null or the same as the new parent, the add will
+ // succeed, so just make sure the tracked transient container is in sync with the
+ // current parent.
+ if (transientContainer != null && transientContainer != parent) {
Log.w(TAG, "Expandable view " + this
+ " has transient container " + transientContainer
- + " but no parent");
+ + " but different parent" + parent);
setTransientContainer(null);
}
return;
}
if (transientContainer == null) {
- throw new IllegalStateException(
- "Can't add view " + this + " to container " + newParent + "; current parent "
- + parent + " is not a transient container");
+ throw new IllegalStateException("Can't add view " + this + " to container " + newParent
+ + "; current parent " + parent + " is not a transient container");
}
if (transientContainer != parent) {
- String transientContainerOutOfSyncError = "Expandable view " + this
+ // Crash with details before addView() crashes without any; the view is being added
+ // to a different parent, and the transient container isn't the parent, so we can't
+ // even (safely) clean that up.
+ throw new IllegalStateException("Expandable view " + this
+ " has transient container " + transientContainer
- + " but different parent " + parent;
- if (parent != newParent) {
- // Crash with details before addView() crashes without any; the view is being added
- // to a different parent, and the transient container isn't the parent, so we can't
- // even (safely) clean that up.
- throw new IllegalStateException(transientContainerOutOfSyncError);
- } else {
- Log.w(TAG, transientContainerOutOfSyncError);
- setTransientContainer(null);
- return;
- }
- }
- if (parent != newParent) {
- Log.w(TAG, "Moving view " + this + " from transient container "
- + transientContainer + " to parent " + newParent);
+ + " but different parent " + parent);
}
+ Log.w(TAG, "Removing view " + this + " from transient container "
+ + transientContainer + " in preparation for moving to parent " + newParent);
transientContainer.removeTransientView(this);
setTransientContainer(null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index bfa4a245070c..dee1b334182a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.statusbar.phone;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 01acce302b30..2824ab85152f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -412,7 +412,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
}
@Override
- protected boolean canRemoveImmediately(@NonNull String key) {
+ public boolean canRemoveImmediately(@NonNull String key) {
if (mSwipedOutKeys.contains(key)) {
// We always instantly dismiss views being manually swiped out.
mSwipedOutKeys.remove(key);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index ec2d0364a3a6..571c10b3800f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -54,6 +54,7 @@ class KeyguardLiftController constructor(
isListening = false
updateListeningState()
keyguardUpdateMonitor.requestFaceAuth(true)
+ keyguardUpdateMonitor.requestActiveUnlock()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt
index 4de78f5d6190..868efa027f40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt
@@ -34,7 +34,7 @@ class LSShadeTransitionLogger @Inject constructor(
private val displayMetrics: DisplayMetrics
) {
fun logUnSuccessfulDragDown(startingChild: View?) {
- val entry = (startingChild as ExpandableNotificationRow?)?.entry
+ val entry = (startingChild as? ExpandableNotificationRow)?.entry
buffer.log(TAG, LogLevel.INFO, {
str1 = entry?.key ?: "no entry"
}, {
@@ -49,7 +49,7 @@ class LSShadeTransitionLogger @Inject constructor(
}
fun logDragDownStarted(startingChild: ExpandableView?) {
- val entry = (startingChild as ExpandableNotificationRow?)?.entry
+ val entry = (startingChild as? ExpandableNotificationRow)?.entry
buffer.log(TAG, LogLevel.INFO, {
str1 = entry?.key ?: "no entry"
}, {
@@ -58,7 +58,7 @@ class LSShadeTransitionLogger @Inject constructor(
}
fun logDraggedDownLockDownShade(startingChild: View?) {
- val entry = (startingChild as ExpandableNotificationRow?)?.entry
+ val entry = (startingChild as? ExpandableNotificationRow)?.entry
buffer.log(TAG, LogLevel.INFO, {
str1 = entry?.key ?: "no entry"
}, {
@@ -67,7 +67,7 @@ class LSShadeTransitionLogger @Inject constructor(
}
fun logDraggedDown(startingChild: View?, dragLengthY: Int) {
- val entry = (startingChild as ExpandableNotificationRow?)?.entry
+ val entry = (startingChild as? ExpandableNotificationRow)?.entry
buffer.log(TAG, LogLevel.INFO, {
str1 = entry?.key ?: "no entry"
}, {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 1cc5e12a4102..a9b3927acc88 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1412,7 +1412,8 @@ public class StatusBar extends CoreStartable implements
private void setUpPresenter() {
// Set up the initial notification state.
- mActivityLaunchAnimator.setCallback(mKeyguardHandler);
+ mActivityLaunchAnimator.setCallback(mActivityLaunchAnimatorCallback);
+ mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener);
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
mNotificationShadeWindowViewController,
mStackScrollerController.getNotificationListContainer(),
@@ -4393,7 +4394,7 @@ public class StatusBar extends CoreStartable implements
}
};
- private final ActivityLaunchAnimator.Callback mKeyguardHandler =
+ private final ActivityLaunchAnimator.Callback mActivityLaunchAnimatorCallback =
new ActivityLaunchAnimator.Callback() {
@Override
public boolean isOnKeyguard() {
@@ -4412,11 +4413,6 @@ public class StatusBar extends CoreStartable implements
}
@Override
- public void setBlursDisabledForAppLaunch(boolean disabled) {
- mKeyguardViewMediator.setBlursDisabledForAppLaunch(disabled);
- }
-
- @Override
public int getBackgroundColor(TaskInfo task) {
if (!mStartingSurfaceOptional.isPresent()) {
Log.w(TAG, "No starting surface, defaulting to SystemBGColor");
@@ -4427,6 +4423,19 @@ public class StatusBar extends CoreStartable implements
}
};
+ private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener =
+ new ActivityLaunchAnimator.Listener() {
+ @Override
+ public void onLaunchAnimationStart() {
+ mKeyguardViewMediator.setBlursDisabledForAppLaunch(true);
+ }
+
+ @Override
+ public void onLaunchAnimationEnd() {
+ mKeyguardViewMediator.setBlursDisabledForAppLaunch(false);
+ }
+ };
+
private final DemoMode mDemoModeCallback = new DemoMode() {
@Override
public void onDemoModeFinished() {
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
new file mode 100644
index 000000000000..1451c03fefa0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.unfold
+
+import com.android.internal.util.FrameworkStatsLog
+
+/** Logs fold state changes. */
+class FoldStateLogger(private val foldStateLoggingProvider: FoldStateLoggingProvider) :
+ FoldStateLoggingProvider.FoldStateLoggingListener {
+
+ fun init() {
+ foldStateLoggingProvider.addCallback(this)
+ }
+
+ override fun onFoldUpdate(foldStateUpdate: FoldStateChange) {
+ FrameworkStatsLog.write(
+ FrameworkStatsLog.FOLD_STATE_DURATION_REPORTED,
+ foldStateUpdate.previous,
+ foldStateUpdate.current,
+ foldStateUpdate.dtMillis)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
index f2c156108ac6..c2fd34c719a0 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
@@ -102,6 +102,15 @@ class UnfoldTransitionModule {
@Provides
@Singleton
+ fun providesFoldStateLogger(
+ optionalFoldStateLoggingProvider: Optional<FoldStateLoggingProvider>
+ ): Optional<FoldStateLogger> =
+ optionalFoldStateLoggingProvider.map { FoldStateLoggingProvider ->
+ FoldStateLogger(FoldStateLoggingProvider)
+ }
+
+ @Provides
+ @Singleton
fun provideUnfoldTransitionConfig(context: Context): UnfoldTransitionConfig =
createConfig(context)
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 5e9579cb6a83..20c8bf38692b 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -74,6 +74,7 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.coordinator.BubbleCoordinator;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
@@ -88,6 +89,7 @@ import com.android.wm.shell.bubbles.Bubbles;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
@@ -111,8 +113,10 @@ public class BubblesManager implements Dumpable {
private final INotificationManager mNotificationManager;
private final NotificationVisibilityProvider mVisibilityProvider;
private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
+ private final NotificationLockscreenUserManager mNotifUserManager;
private final NotificationGroupManagerLegacy mNotificationGroupManager;
private final NotificationEntryManager mNotificationEntryManager;
+ private final CommonNotifCollection mCommonNotifCollection;
private final NotifPipeline mNotifPipeline;
private final Executor mSysuiMainExecutor;
@@ -139,6 +143,7 @@ public class BubblesManager implements Dumpable {
NotificationLockscreenUserManager notifUserManager,
NotificationGroupManagerLegacy groupManager,
NotificationEntryManager entryManager,
+ CommonNotifCollection notifCollection,
NotifPipeline notifPipeline,
SysUiState sysUiState,
NotifPipelineFlags notifPipelineFlags,
@@ -150,8 +155,8 @@ public class BubblesManager implements Dumpable {
configurationController, statusBarService, notificationManager,
visibilityProvider,
interruptionStateProvider, zenModeController, notifUserManager,
- groupManager, entryManager, notifPipeline, sysUiState, notifPipelineFlags,
- dumpManager, sysuiMainExecutor);
+ groupManager, entryManager, notifCollection, notifPipeline, sysUiState,
+ notifPipelineFlags, dumpManager, sysuiMainExecutor);
} else {
return null;
}
@@ -172,6 +177,7 @@ public class BubblesManager implements Dumpable {
NotificationLockscreenUserManager notifUserManager,
NotificationGroupManagerLegacy groupManager,
NotificationEntryManager entryManager,
+ CommonNotifCollection notifCollection,
NotifPipeline notifPipeline,
SysUiState sysUiState,
NotifPipelineFlags notifPipelineFlags,
@@ -184,8 +190,10 @@ public class BubblesManager implements Dumpable {
mNotificationManager = notificationManager;
mVisibilityProvider = visibilityProvider;
mNotificationInterruptStateProvider = interruptionStateProvider;
+ mNotifUserManager = notifUserManager;
mNotificationGroupManager = groupManager;
mNotificationEntryManager = entryManager;
+ mCommonNotifCollection = notifCollection;
mNotifPipeline = notifPipeline;
mSysuiMainExecutor = sysuiMainExecutor;
@@ -264,8 +272,7 @@ public class BubblesManager implements Dumpable {
@Override
public void getPendingOrActiveEntry(String key, Consumer<BubbleEntry> callback) {
sysuiMainExecutor.execute(() -> {
- NotificationEntry entry =
- mNotificationEntryManager.getPendingOrActiveNotif(key);
+ final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
callback.accept(entry == null ? null : notifToBubbleEntry(entry));
});
}
@@ -275,11 +282,11 @@ public class BubblesManager implements Dumpable {
Consumer<List<BubbleEntry>> callback) {
sysuiMainExecutor.execute(() -> {
List<BubbleEntry> result = new ArrayList<>();
- List<NotificationEntry> activeEntries =
- mNotificationEntryManager.getActiveNotificationsForCurrentUser();
- for (int i = 0; i < activeEntries.size(); i++) {
- NotificationEntry entry = activeEntries.get(i);
- if (savedBubbleKeys.contains(entry.getKey())
+ final Collection<NotificationEntry> activeEntries =
+ mCommonNotifCollection.getAllNotifs();
+ for (NotificationEntry entry : activeEntries) {
+ if (mNotifUserManager.isCurrentProfile(entry.getSbn().getUserId())
+ && savedBubbleKeys.contains(entry.getKey())
&& mNotificationInterruptStateProvider.shouldBubbleUp(entry)
&& entry.isBubble()) {
result.add(notifToBubbleEntry(entry));
@@ -292,8 +299,7 @@ public class BubblesManager implements Dumpable {
@Override
public void setNotificationInterruption(String key) {
sysuiMainExecutor.execute(() -> {
- final NotificationEntry entry =
- mNotificationEntryManager.getPendingOrActiveNotif(key);
+ final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
if (entry != null
&& entry.getImportance() >= NotificationManager.IMPORTANCE_HIGH) {
entry.setInterruption();
@@ -311,8 +317,7 @@ public class BubblesManager implements Dumpable {
@Override
public void notifyRemoveNotification(String key, int reason) {
sysuiMainExecutor.execute(() -> {
- final NotificationEntry entry =
- mNotificationEntryManager.getPendingOrActiveNotif(key);
+ final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
if (entry != null) {
for (NotifCallback cb : mCallbacks) {
cb.removeNotification(entry, getDismissedByUserStats(entry, true),
@@ -334,8 +339,7 @@ public class BubblesManager implements Dumpable {
@Override
public void notifyMaybeCancelSummary(String key) {
sysuiMainExecutor.execute(() -> {
- final NotificationEntry entry =
- mNotificationEntryManager.getPendingOrActiveNotif(key);
+ final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
if (entry != null) {
for (NotifCallback cb : mCallbacks) {
cb.maybeCancelSummary(entry);
@@ -347,8 +351,7 @@ public class BubblesManager implements Dumpable {
@Override
public void removeNotificationEntry(String key) {
sysuiMainExecutor.execute(() -> {
- final NotificationEntry entry =
- mNotificationEntryManager.getPendingOrActiveNotif(key);
+ final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
if (entry != null) {
mNotificationGroupManager.onEntryRemoved(entry);
}
@@ -358,8 +361,7 @@ public class BubblesManager implements Dumpable {
@Override
public void updateNotificationBubbleButton(String key) {
sysuiMainExecutor.execute(() -> {
- final NotificationEntry entry =
- mNotificationEntryManager.getPendingOrActiveNotif(key);
+ final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
if (entry != null && entry.getRow() != null) {
entry.getRow().updateBubbleButton();
}
@@ -369,8 +371,7 @@ public class BubblesManager implements Dumpable {
@Override
public void updateNotificationSuppression(String key) {
sysuiMainExecutor.execute(() -> {
- final NotificationEntry entry =
- mNotificationEntryManager.getPendingOrActiveNotif(key);
+ final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
if (entry != null) {
mNotificationGroupManager.updateSuppression(entry);
}
@@ -402,8 +403,7 @@ public class BubblesManager implements Dumpable {
@Override
public void onUnbubbleConversation(String key) {
sysuiMainExecutor.execute(() -> {
- final NotificationEntry entry =
- mNotificationEntryManager.getPendingOrActiveNotif(key);
+ final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
if (entry != null) {
onUserChangedBubble(entry, false /* shouldBubble */);
}
@@ -580,7 +580,7 @@ public class BubblesManager implements Dumpable {
HashMap<String, Pair<BubbleEntry, Boolean>> pendingOrActiveNotif = new HashMap<>();
for (int i = 0; i < orderedKeys.length; i++) {
String key = orderedKeys[i];
- NotificationEntry entry = mNotificationEntryManager.getPendingOrActiveNotif(key);
+ final NotificationEntry entry = mCommonNotifCollection.getEntry(key);
BubbleEntry bubbleEntry = entry != null
? notifToBubbleEntry(entry)
: null;
diff --git a/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java b/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
index cbd6e8659e69..0369d5b32883 100644
--- a/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
+++ b/packages/SystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java
@@ -110,6 +110,17 @@ public class AAAPlusPlusVerifySysuiRequiredTestPropertiesTest extends SysuiTestC
private Collection<String> getClassNamesFromClassPath() {
ClassPathScanner scanner = new ClassPathScanner(mContext.getPackageCodePath());
+ ChainedClassNameFilter filter = makeClassNameFilter();
+
+ try {
+ return scanner.getClassPathEntries(filter);
+ } catch (IOException e) {
+ Log.e(getTag(), "Failed to scan classes", e);
+ }
+ return Collections.emptyList();
+ }
+
+ protected ChainedClassNameFilter makeClassNameFilter() {
ChainedClassNameFilter filter = new ChainedClassNameFilter();
filter.add(new ExternalClassNameFilter());
@@ -122,13 +133,7 @@ public class AAAPlusPlusVerifySysuiRequiredTestPropertiesTest extends SysuiTestC
// the main SystemUI process. Therefore, exclude this package
// from the base class whitelist.
filter.add(s -> !s.startsWith("com.android.systemui.screenshot"));
-
- try {
- return scanner.getClassPathEntries(filter);
- } catch (IOException e) {
- Log.e(TAG, "Failed to scan classes", e);
- }
- return Collections.emptyList();
+ return filter;
}
private String getClsStr() {
@@ -212,8 +217,12 @@ public class AAAPlusPlusVerifySysuiRequiredTestPropertiesTest extends SysuiTestC
* as loggable to limit log spam during normal use.
*/
private void logDebug(String msg) {
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, msg);
+ if (Log.isLoggable(getTag(), Log.DEBUG)) {
+ Log.d(getTag(), msg);
}
}
+
+ protected String getTag() {
+ return TAG;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
new file mode 100644
index 000000000000..6bc65054d830
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.keyguard
+
+import android.hardware.biometrics.BiometricSourceType
+import org.mockito.Mockito.verify
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT
+import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class KeyguardBiometricLockoutLoggerTest : SysuiTestCase() {
+ @Mock
+ lateinit var uiEventLogger: UiEventLogger
+ @Mock
+ lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ @Mock
+ lateinit var dumpManager: DumpManager
+ @Mock
+ lateinit var strongAuthTracker: KeyguardUpdateMonitor.StrongAuthTracker
+
+ @Captor
+ lateinit var updateMonitorCallbackCaptor: ArgumentCaptor<KeyguardUpdateMonitorCallback>
+ lateinit var updateMonitorCallback: KeyguardUpdateMonitorCallback
+
+ lateinit var keyguardBiometricLockoutLogger: KeyguardBiometricLockoutLogger
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(keyguardUpdateMonitor.strongAuthTracker).thenReturn(strongAuthTracker)
+ keyguardBiometricLockoutLogger = KeyguardBiometricLockoutLogger(
+ mContext,
+ uiEventLogger,
+ keyguardUpdateMonitor,
+ dumpManager)
+ }
+
+ @Test
+ fun test_logsOnStart() {
+ // GIVEN is encrypted / lockdown before start
+ whenever(keyguardUpdateMonitor.isEncryptedOrLockdown(anyInt()))
+ .thenReturn(true)
+
+ // WHEN start
+ keyguardBiometricLockoutLogger.start()
+
+ // THEN encrypted / lockdown state is logged
+ verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_ENCRYPTED_OR_LOCKDOWN)
+ }
+
+ @Test
+ fun test_logTimeoutChange() {
+ keyguardBiometricLockoutLogger.start()
+ captureUpdateMonitorCallback()
+
+ // GIVEN primary auth required b/c timeout
+ whenever(strongAuthTracker.getStrongAuthForUser(anyInt()))
+ .thenReturn(STRONG_AUTH_REQUIRED_AFTER_TIMEOUT)
+
+ // WHEN primary auth requirement changes
+ updateMonitorCallback.onStrongAuthStateChanged(0)
+
+ // THEN primary auth required state is logged
+ verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_TIMEOUT)
+ }
+
+ @Test
+ fun test_logUnattendedUpdate() {
+ keyguardBiometricLockoutLogger.start()
+ captureUpdateMonitorCallback()
+
+ // GIVEN primary auth required b/c unattended update
+ whenever(strongAuthTracker.getStrongAuthForUser(anyInt()))
+ .thenReturn(STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE)
+
+ // WHEN primary auth requirement changes
+ updateMonitorCallback.onStrongAuthStateChanged(0)
+
+ // THEN primary auth required state is logged
+ verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_UNATTENDED_UPDATE)
+ }
+
+ @Test
+ fun test_logMultipleChanges() {
+ keyguardBiometricLockoutLogger.start()
+ captureUpdateMonitorCallback()
+
+ // GIVEN primary auth required b/c timeout
+ whenever(strongAuthTracker.getStrongAuthForUser(anyInt()))
+ .thenReturn(STRONG_AUTH_REQUIRED_AFTER_TIMEOUT
+ or STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE)
+
+ // WHEN primary auth requirement changes
+ updateMonitorCallback.onStrongAuthStateChanged(0)
+
+ // THEN primary auth required state is logged with all the reasons
+ verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_TIMEOUT)
+ verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_UNATTENDED_UPDATE)
+
+ // WHEN onStrongAuthStateChanged is called again
+ updateMonitorCallback.onStrongAuthStateChanged(0)
+
+ // THEN no more events are sent since there haven't been any changes
+ verifyNoMoreInteractions(uiEventLogger)
+ }
+
+ @Test
+ fun test_logFaceLockout() {
+ keyguardBiometricLockoutLogger.start()
+ captureUpdateMonitorCallback()
+
+ // GIVEN primary auth required b/c face lock
+ whenever(keyguardUpdateMonitor.isFaceLockedOut).thenReturn(true)
+
+ // WHEN lockout state changes
+ updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FACE)
+
+ // THEN primary auth required state is logged
+ verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT)
+
+ // WHEN face lockout is reset
+ whenever(keyguardUpdateMonitor.isFaceLockedOut).thenReturn(false)
+ updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FACE)
+
+ // THEN primary auth required state is logged
+ verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT_RESET)
+ }
+
+ @Test
+ fun test_logFingerprintLockout() {
+ keyguardBiometricLockoutLogger.start()
+ captureUpdateMonitorCallback()
+
+ // GIVEN primary auth required b/c fingerprint lock
+ whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(true)
+
+ // WHEN lockout state changes
+ updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT)
+
+ // THEN primary auth required state is logged
+ verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT)
+
+ // WHEN fingerprint lockout is reset
+ whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false)
+ updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT)
+
+ // THEN primary auth required state is logged
+ verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent
+ .PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT_RESET)
+ }
+
+ fun captureUpdateMonitorCallback() {
+ verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallbackCaptor.capture())
+ updateMonitorCallback = updateMonitorCallbackCaptor.value
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index c873804bc82c..599e5474c564 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -48,6 +48,7 @@ import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -116,6 +117,8 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
@Mock
private GlobalSettings mGlobalSettings;
@Mock
+ private FeatureFlags mFeatureFlags;
+ @Mock
private UserSwitcherController mUserSwitcherController;
private Configuration mConfiguration;
@@ -151,7 +154,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
mKeyguardStateController, mKeyguardSecurityViewFlipperController,
mConfigurationController, mFalsingCollector, mFalsingManager,
- mUserSwitcherController, mGlobalSettings).create(mSecurityCallback);
+ mUserSwitcherController, mFeatureFlags, mGlobalSettings).create(mSecurityCallback);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 70792cfee301..7266e41ad7ca 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -88,6 +88,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -173,6 +174,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private InteractionJankMonitor mInteractionJankMonitor;
@Mock
private LatencyTracker mLatencyTracker;
+ @Mock
+ private FeatureFlags mFeatureFlags;
@Captor
private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
// Direct executor
@@ -1105,7 +1108,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mRingerModeTracker, mBackgroundExecutor, mMainExecutor,
mStatusBarStateController, mLockPatternUtils,
mAuthController, mTelephonyListenerManager,
- mInteractionJankMonitor, mLatencyTracker);
+ mInteractionJankMonitor, mLatencyTracker, mFeatureFlags);
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
index 40549d69dc74..8c20b248d02c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
@@ -29,8 +29,10 @@ import com.android.systemui.utils.leaks.LeakCheckedTest;
import com.android.systemui.utils.leaks.LeakCheckedTest.SysuiLeakCheck;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Rule;
+import org.mockito.Mockito;
public abstract class SysuiBaseFragmentTest extends BaseFragmentTest {
@@ -78,6 +80,11 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest {
SystemUIFactory.cleanup();
}
+ @AfterClass
+ public static void mockitoTeardown() {
+ Mockito.framework().clearInlineMocks();
+ }
+
@Override
protected SysuiTestableContext getContext() {
return new SysuiTestableContext(InstrumentationRegistry.getContext(), mLeakCheck);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index 1fe3d4417730..589eeb5e0761 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -21,13 +21,12 @@ import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.eq
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertNotNull
import junit.framework.Assert.assertNull
import junit.framework.Assert.assertTrue
import junit.framework.AssertionFailedError
-import kotlin.concurrent.thread
+import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@@ -40,6 +39,7 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
+import kotlin.concurrent.thread
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -48,6 +48,7 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
private val launchContainer = LinearLayout(mContext)
private val launchAnimator = LaunchAnimator(TEST_TIMINGS, TEST_INTERPOLATORS)
@Mock lateinit var callback: ActivityLaunchAnimator.Callback
+ @Mock lateinit var listener: ActivityLaunchAnimator.Listener
@Spy private val controller = TestLaunchAnimatorController(launchContainer)
@Mock lateinit var iCallback: IRemoteAnimationFinishedCallback
@Mock lateinit var failHandler: Log.TerribleFailureHandler
@@ -59,6 +60,12 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
fun setup() {
activityLaunchAnimator = ActivityLaunchAnimator(launchAnimator)
activityLaunchAnimator.callback = callback
+ activityLaunchAnimator.addListener(listener)
+ }
+
+ @After
+ fun tearDown() {
+ activityLaunchAnimator.removeListener(listener)
}
private fun startIntentWithAnimation(
@@ -177,7 +184,7 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
val runner = activityLaunchAnimator.createRunner(controller)
runner.onAnimationStart(0, arrayOf(fakeWindow()), emptyArray(), emptyArray(), iCallback)
waitForIdleSync()
- verify(callback).setBlursDisabledForAppLaunch(eq(true))
+ verify(listener).onLaunchAnimationStart()
verify(controller).onLaunchAnimationStart(anyBoolean())
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 84eb93556c86..066a866118dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -37,6 +37,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.animation.ActivityLaunchAnimator
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -89,6 +90,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
@Mock private lateinit var udfpsController: UdfpsController
@Mock private lateinit var udfpsView: UdfpsView
@Mock private lateinit var udfpsEnrollView: UdfpsEnrollView
+ @Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
private val sensorProps = SensorLocationInternal("", 10, 100, 20)
.asFingerprintSensorProperties()
@@ -118,7 +120,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
keyguardUpdateMonitor, dialogManager, dumpManager, transitionController,
configurationController, systemClock, keyguardStateController,
unlockedScreenOffAnimationController, sensorProps, hbmProvider, reason,
- controllerCallback, onTouch)
+ controllerCallback, onTouch, activityLaunchAnimator)
block()
}
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 2afcbda64fb5..159bdbab6d8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -58,6 +58,7 @@ import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.plugins.FalsingManager;
@@ -180,6 +181,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
private TypedArray mBrightnessBacklight;
@Mock
private SystemUIDialogManager mSystemUIDialogManager;
+ @Mock
+ private ActivityLaunchAnimator mActivityLaunchAnimator;
// Capture listeners so that they can be used to send events
@Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor;
@@ -252,7 +255,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
mSystemClock,
mUnlockedScreenOffAnimationController,
mSystemUIDialogManager,
- mLatencyTracker);
+ mLatencyTracker,
+ mActivityLaunchAnimator);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
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 0ae3c39e659b..e9a4e15b9773 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -36,6 +36,7 @@ import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -96,6 +97,8 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
private SystemUIDialogManager mDialogManager;
@Mock
private UdfpsController mUdfpsController;
+ @Mock
+ private ActivityLaunchAnimator mActivityLaunchAnimator;
private FakeSystemClock mSystemClock = new FakeSystemClock();
private UdfpsKeyguardViewController mController;
@@ -134,7 +137,8 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
mKeyguardStateController,
mUnlockedScreenOffAnimationController,
mDialogManager,
- mUdfpsController);
+ mUdfpsController,
+ mActivityLaunchAnimator);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
index 2d3757c29ebf..12096bc06748 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
@@ -17,6 +17,9 @@
package com.android.systemui.controls.controller
import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
import android.os.UserHandle
import android.service.controls.IControlsActionCallback
import android.service.controls.IControlsProvider
@@ -43,6 +46,8 @@ import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -57,8 +62,6 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
private lateinit var subscriberService: IControlsSubscriber.Stub
@Mock
private lateinit var service: IControlsProvider.Stub
- @Mock
- private lateinit var loadCallback: ControlsBindingController.LoadCallback
@Captor
private lateinit var wrapperCaptor: ArgumentCaptor<ControlActionWrapper>
@@ -75,7 +78,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
- mContext.addMockService(componentName, service)
+ context.addMockService(componentName, service)
executor = FakeExecutor(FakeSystemClock())
`when`(service.asBinder()).thenCallRealMethod()
`when`(service.queryLocalInterface(ArgumentMatchers.anyString())).thenReturn(service)
@@ -98,7 +101,36 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
fun testBindService() {
manager.bindService()
executor.runAllReady()
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
+ }
+
+ @Test
+ fun testNullBinding() {
+ val mockContext = mock(Context::class.java)
+ lateinit var serviceConnection: ServiceConnection
+ `when`(mockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer {
+ val component = (it.arguments[0] as Intent).component
+ if (component == componentName) {
+ serviceConnection = it.arguments[1] as ServiceConnection
+ serviceConnection.onNullBinding(component)
+ true
+ } else {
+ false
+ }
+ }
+
+ val nullManager = ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ UserHandle.of(0),
+ componentName
+ )
+
+ nullManager.bindService()
+ executor.runAllReady()
+
+ verify(mockContext).unbindService(serviceConnection)
}
@Test
@@ -109,7 +141,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
manager.unbindService()
executor.runAllReady()
- assertFalse(mContext.isBound(componentName))
+ assertFalse(context.isBound(componentName))
}
@Test
@@ -119,7 +151,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
verify(service).load(subscriberService)
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
}
@Test
@@ -129,7 +161,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
manager.unbindService()
executor.runAllReady()
- assertFalse(mContext.isBound(componentName))
+ assertFalse(context.isBound(componentName))
}
@Test
@@ -162,7 +194,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
manager.maybeBindAndSubscribe(list, subscriberService)
executor.runAllReady()
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
verify(service).subscribe(list, subscriberService)
}
@@ -173,7 +205,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
manager.maybeBindAndSendAction(controlId, action)
executor.runAllReady()
- assertTrue(mContext.isBound(componentName))
+ assertTrue(context.isBound(componentName))
verify(service).action(eq(controlId), capture(wrapperCaptor),
eq(actionCallbackService))
assertEquals(action, wrapperCaptor.getValue().getWrappedAction())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index 8cd8e4d7382d..c0b7271c6de7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -16,12 +16,15 @@
package com.android.systemui.dreams;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Intent;
import android.os.IBinder;
+import android.service.dreams.DreamService;
import android.service.dreams.IDreamOverlay;
import android.service.dreams.IDreamOverlayCallback;
import android.testing.AndroidTestingRunner;
@@ -195,4 +198,22 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
mService.onDestroy();
verify(mDreamOverlayStateController).removeCallback(callbackCapture.getValue());
}
+
+ @Test
+ public void testShouldShowComplicationsTrueByDefault() {
+ assertThat(mService.shouldShowComplications()).isTrue();
+
+ mService.onBind(new Intent());
+
+ assertThat(mService.shouldShowComplications()).isTrue();
+ }
+
+ @Test
+ public void testShouldShowComplicationsSetByIntentExtra() {
+ final Intent intent = new Intent();
+ intent.putExtra(DreamService.EXTRA_SHOW_COMPLICATIONS, false);
+ mService.onBind(intent);
+
+ assertThat(mService.shouldShowComplications()).isFalse();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index 7763e75ae40b..140a395f1e27 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -202,6 +202,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
resumeAction = null)
whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(false)
+ whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false)
}
/** Mock view holder for the notification player */
@@ -301,8 +302,47 @@ public class MediaControlPanelTest : SysuiTestCase() {
}
@Test
- fun bindSemanticActions() {
+ fun bindSemanticActionsOldLayout() {
whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+ whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false)
+
+ val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
+ val semanticActions = MediaButton(
+ playOrPause = MediaAction(icon, Runnable {}, "play"),
+ nextOrCustom = MediaAction(icon, Runnable {}, "next"),
+ startCustom = MediaAction(icon, null, "custom 1"),
+ endCustom = MediaAction(icon, null, "custom 2")
+ )
+ val state = mediaData.copy(semanticActions = semanticActions)
+
+ player.attachPlayer(holder, MediaViewController.TYPE.PLAYER)
+ player.bindPlayer(state, PACKAGE)
+
+ verify(expandedSet).setVisibility(R.id.action0, ConstraintSet.VISIBLE)
+ assertThat(action0.contentDescription).isEqualTo("custom 1")
+ assertThat(action0.isEnabled()).isFalse()
+
+ verify(expandedSet).setVisibility(R.id.action1, ConstraintSet.INVISIBLE)
+ assertThat(action1.isEnabled()).isFalse()
+
+ verify(expandedSet).setVisibility(R.id.action2, ConstraintSet.VISIBLE)
+ assertThat(action2.isEnabled()).isTrue()
+ assertThat(action2.contentDescription).isEqualTo("play")
+
+ verify(expandedSet).setVisibility(R.id.action3, ConstraintSet.VISIBLE)
+ assertThat(action3.isEnabled()).isTrue()
+ assertThat(action3.contentDescription).isEqualTo("next")
+
+ verify(expandedSet).setVisibility(R.id.action4, ConstraintSet.VISIBLE)
+ assertThat(action4.contentDescription).isEqualTo("custom 2")
+ assertThat(action4.isEnabled()).isFalse()
+ }
+
+ @Test
+ fun bindSemanticActionsNewLayout() {
+ whenever(mediaFlags.areMediaSessionActionsEnabled()).thenReturn(true)
+ whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true)
+
val icon = Icon.createWithResource(context, android.R.drawable.ic_media_play)
val semanticActions = MediaButton(
playOrPause = MediaAction(icon, Runnable {}, "play"),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogTest.kt
index f56a185a19a5..2ad9c9400f65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogTest.kt
@@ -130,4 +130,37 @@ class TileRequestDialogTest : SysuiTestCase() {
val tile = content.getChildAt(1) as QSTileView
assertThat((tile.icon.iconView as ImageView).drawable).isNotNull()
}
+
+ @Test
+ fun setTileData_hasNoStateDescription() {
+ val icon = Icon.createWithResource(mContext, R.drawable.cloud)
+ val tileData = TileRequestDialog.TileData(APP_NAME, LABEL, icon)
+
+ dialog.setTileData(tileData)
+ dialog.show()
+
+ TestableLooper.get(this).processAllMessages()
+
+ val content = dialog.requireViewById<ViewGroup>(TileRequestDialog.CONTENT_ID)
+ val tile = content.getChildAt(1) as QSTileView
+
+ assertThat(tile.stateDescription).isEqualTo("")
+ }
+
+ @Test
+ fun setTileData_tileNotClickable() {
+ val icon = Icon.createWithResource(mContext, R.drawable.cloud)
+ val tileData = TileRequestDialog.TileData(APP_NAME, LABEL, icon)
+
+ dialog.setTileData(tileData)
+ dialog.show()
+
+ TestableLooper.get(this).processAllMessages()
+
+ val content = dialog.requireViewById<ViewGroup>(TileRequestDialog.CONTENT_ID)
+ val tile = content.getChildAt(1) as QSTileView
+
+ assertThat(tile.isClickable).isFalse()
+ assertThat(tile.isLongClickable).isFalse()
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
new file mode 100644
index 000000000000..8bc438bce5cc
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.navigationbar
+import android.graphics.Rect
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.SurfaceControl
+import android.view.View
+import android.view.ViewRootImpl
+import androidx.concurrent.futures.DirectExecutor
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.*
+import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+@RunWithLooper
+class RegionSamplingHelperTest : SysuiTestCase() {
+
+ @Mock
+ lateinit var sampledView: View
+ @Mock
+ lateinit var samplingCallback: RegionSamplingHelper.SamplingCallback
+ @Mock
+ lateinit var compositionListener: RegionSamplingHelper.SysuiCompositionSamplingListener
+ @Mock
+ lateinit var viewRootImpl: ViewRootImpl
+ @Mock
+ lateinit var surfaceControl: SurfaceControl
+ @Mock
+ lateinit var wrappedSurfaceControl: SurfaceControl
+ @JvmField @Rule
+ var rule = MockitoJUnit.rule()
+ lateinit var regionSamplingHelper: RegionSamplingHelper
+
+ @Before
+ fun setup() {
+ whenever(sampledView.isAttachedToWindow).thenReturn(true)
+ whenever(sampledView.viewRootImpl).thenReturn(viewRootImpl)
+ whenever(viewRootImpl.surfaceControl).thenReturn(surfaceControl)
+ whenever(surfaceControl.isValid).thenReturn(true)
+ whenever(wrappedSurfaceControl.isValid).thenReturn(true)
+ whenever(samplingCallback.isSamplingEnabled).thenReturn(true)
+ regionSamplingHelper = object : RegionSamplingHelper(sampledView, samplingCallback,
+ DirectExecutor.INSTANCE, DirectExecutor.INSTANCE, compositionListener) {
+ override fun wrap(stopLayerControl: SurfaceControl?): SurfaceControl {
+ return wrappedSurfaceControl
+ }
+ }
+ regionSamplingHelper.setWindowVisible(true)
+ }
+
+ @Test
+ fun testStart_register() {
+ regionSamplingHelper.start(Rect(0, 0, 100, 100))
+ verify(compositionListener).register(any(), anyInt(), eq(wrappedSurfaceControl), any())
+ }
+
+ @Test
+ fun testStart_unregister() {
+ regionSamplingHelper.start(Rect(0, 0, 100, 100))
+ regionSamplingHelper.setWindowVisible(false)
+ verify(compositionListener).unregister(any())
+ }
+
+ @Test
+ fun testStart_hasBlur_neverRegisters() {
+ regionSamplingHelper.setWindowHasBlurs(true)
+ regionSamplingHelper.start(Rect(0, 0, 100, 100))
+ verify(compositionListener, never())
+ .register(any(), anyInt(), eq(wrappedSurfaceControl), any())
+ }
+
+ @Test
+ fun testStart_stopAndDestroy() {
+ regionSamplingHelper.start(Rect(0, 0, 100, 100))
+ regionSamplingHelper.stopAndDestroy()
+ verify(compositionListener).unregister(any())
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
new file mode 100644
index 000000000000..6971c63ed6d4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
@@ -0,0 +1,44 @@
+package com.android.systemui.statusbar
+
+import android.testing.AndroidTestingRunner
+import android.util.DisplayMetrics
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.statusbar.notification.row.ExpandableView
+import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger
+import com.android.systemui.util.mockito.mock
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class LSShadeTransitionLoggerTest : SysuiTestCase() {
+ lateinit var logger: LSShadeTransitionLogger
+ @Mock
+ lateinit var gestureLogger: LockscreenGestureLogger
+ @Mock
+ lateinit var displayMetrics: DisplayMetrics
+ @JvmField @Rule
+ val mockito = MockitoJUnit.rule()
+
+ @Before
+ fun setup() {
+ logger = LSShadeTransitionLogger(
+ LogBuffer("Test", 10, 10, mock()),
+ gestureLogger,
+ displayMetrics)
+ }
+
+ @Test
+ fun testLogDragDownStarted() {
+ val view: ExpandableView = mock()
+ // log a non-null, non row, ensure no crash
+ logger.logDragDownStarted(view)
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
index a11b46df1218..b3ee5f8373e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java
@@ -140,10 +140,13 @@ public class HeadsUpCoordinatorTest extends SysuiTestCase {
public void testCancelStickyNotification() {
when(mHeadsUpManager.isSticky(anyString())).thenReturn(true);
addHUN(mEntry);
+ when(mHeadsUpManager.canRemoveImmediately(anyString())).thenReturn(false, true);
when(mHeadsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L, 0L);
assertTrue(mNotifLifetimeExtender.shouldExtendLifetime(mEntry, 0));
mClock.advanceTime(1000L);
mExecutor.runAllReady();
+ verify(mHeadsUpManager, times(0))
+ .removeNotification(anyString(), eq(false));
verify(mHeadsUpManager, times(1))
.removeNotification(anyString(), eq(true));
}
@@ -157,6 +160,22 @@ public class HeadsUpCoordinatorTest extends SysuiTestCase {
mClock.advanceTime(1000L);
mExecutor.runAllReady();
verify(mHeadsUpManager, times(0))
+ .removeNotification(anyString(), eq(false));
+ verify(mHeadsUpManager, times(0))
+ .removeNotification(anyString(), eq(true));
+ }
+
+ @Test
+ public void testCancelNotification() {
+ when(mHeadsUpManager.isSticky(anyString())).thenReturn(false);
+ addHUN(mEntry);
+ when(mHeadsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L, 500L);
+ assertTrue(mNotifLifetimeExtender.shouldExtendLifetime(mEntry, 0));
+ mClock.advanceTime(1000L);
+ mExecutor.runAllReady();
+ verify(mHeadsUpManager, times(1))
+ .removeNotification(anyString(), eq(false));
+ verify(mHeadsUpManager, times(0))
.removeNotification(anyString(), eq(true));
}
@@ -189,6 +208,13 @@ public class HeadsUpCoordinatorTest extends SysuiTestCase {
// GIVEN there is a HUN, mEntry
addHUN(mEntry);
+ given(mHeadsUpManager.canRemoveImmediately(anyString())).willAnswer(i -> {
+ String key = i.getArgument(0);
+ for (NotificationEntry entry : mHuns) {
+ if (entry.getKey().equals(key)) return false;
+ }
+ return true;
+ });
// THEN only the current HUN, mEntry, should be lifetimeExtended
assertTrue(mNotifLifetimeExtender.shouldExtendLifetime(mEntry, /* cancellationReason */ 0));
assertFalse(mNotifLifetimeExtender.shouldExtendLifetime(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index d27a57077c9c..07351cf386ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -92,6 +92,7 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
@@ -111,6 +112,7 @@ import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.TaskViewTransitions;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.bubbles.Bubble;
+import com.android.wm.shell.bubbles.BubbleBadgeIconFactory;
import com.android.wm.shell.bubbles.BubbleData;
import com.android.wm.shell.bubbles.BubbleDataRepository;
import com.android.wm.shell.bubbles.BubbleEntry;
@@ -152,6 +154,8 @@ public class BubblesTest extends SysuiTestCase {
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
+ private CommonNotifCollection mCommonNotifCollection;
+ @Mock
private NotificationGroupManagerLegacy mNotificationGroupManager;
@Mock
private WindowManager mWindowManager;
@@ -299,9 +303,8 @@ public class BubblesTest extends SysuiTestCase {
mBubbleEntry2User11 = BubblesManager.notifToBubbleEntry(
mNotificationTestHelper.createBubble(handle));
- // Return non-null notification data from the NEM
- when(mNotificationEntryManager
- .getActiveNotificationUnfiltered(mRow.getKey())).thenReturn(mRow);
+ // Return non-null notification data from the CommonNotifCollection
+ when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
mZenModeConfig.suppressedVisualEffects = 0;
when(mZenModeController.getConfig()).thenReturn(mZenModeConfig);
@@ -371,12 +374,14 @@ public class BubblesTest extends SysuiTestCase {
mLockscreenUserManager,
mNotificationGroupManager,
mNotificationEntryManager,
+ mCommonNotifCollection,
mNotifPipeline,
mSysUiState,
mNotifPipelineFlags,
mDumpManager,
syncExecutor);
+ // XXX: Does *this* need to be changed?
// Get a reference to the BubbleController's entry listener
verify(mNotificationEntryManager, atLeastOnce())
.addNotificationEntryListener(mEntryListenerCaptor.capture());
@@ -421,10 +426,8 @@ public class BubblesTest extends SysuiTestCase {
public void testPromoteBubble_autoExpand() throws Exception {
mBubbleController.updateBubble(mBubbleEntry2);
mBubbleController.updateBubble(mBubbleEntry);
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getKey()))
- .thenReturn(mRow);
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getKey()))
- .thenReturn(mRow2);
+ when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
+ when(mCommonNotifCollection.getEntry(mRow2.getKey())).thenReturn(mRow2);
mBubbleController.removeBubble(
mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
@@ -452,10 +455,8 @@ public class BubblesTest extends SysuiTestCase {
mBubbleController.updateBubble(mBubbleEntry2);
mBubbleController.updateBubble(mBubbleEntry, /* suppressFlyout */
false, /* showInShade */ true);
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getKey()))
- .thenReturn(mRow);
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getKey()))
- .thenReturn(mRow2);
+ when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
+ when(mCommonNotifCollection.getEntry(mRow2.getKey())).thenReturn(mRow2);
mBubbleController.removeBubble(
mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
@@ -958,12 +959,9 @@ public class BubblesTest extends SysuiTestCase {
mBubbleEntry2, /* suppressFlyout */ false, /* showInShade */ false);
mBubbleController.updateBubble(
mBubbleEntry3, /* suppressFlyout */ false, /* showInShade */ false);
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getKey()))
- .thenReturn(mRow);
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getKey()))
- .thenReturn(mRow2);
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow3.getKey()))
- .thenReturn(mRow3);
+ when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
+ when(mCommonNotifCollection.getEntry(mRow2.getKey())).thenReturn(mRow2);
+ when(mCommonNotifCollection.getEntry(mRow3.getKey())).thenReturn(mRow3);
assertEquals(mBubbleData.getBubbles().size(), 3);
mBubbleData.setMaxOverflowBubbles(1);
@@ -1021,7 +1019,7 @@ public class BubblesTest extends SysuiTestCase {
// GIVEN a group summary with a bubble child
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
- when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ when(mCommonNotifCollection.getEntry(groupedBubble.getEntry().getKey()))
.thenReturn(groupedBubble.getEntry());
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
@@ -1046,7 +1044,7 @@ public class BubblesTest extends SysuiTestCase {
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
- when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ when(mCommonNotifCollection.getEntry(groupedBubble.getEntry().getKey()))
.thenReturn(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
@@ -1069,7 +1067,7 @@ public class BubblesTest extends SysuiTestCase {
// GIVEN a group summary with two (non-bubble) children and one bubble child
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
- when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ when(mCommonNotifCollection.getEntry(groupedBubble.getEntry().getKey()))
.thenReturn(groupedBubble.getEntry());
mEntryListener.onPendingEntryAdded(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
@@ -1220,6 +1218,7 @@ public class BubblesTest extends SysuiTestCase {
mBubbleController,
mBubbleController.getStackView(),
new BubbleIconFactory(mContext),
+ new BubbleBadgeIconFactory(mContext),
bubble,
true /* skipInflation */);
verify(userContext, times(1)).getPackageManager();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
index ad26f0112a8e..9eee83ccb6e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
@@ -77,6 +77,7 @@ import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -133,6 +134,8 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
@Mock
private NotificationEntryManager mNotificationEntryManager;
@Mock
+ private CommonNotifCollection mCommonNotifCollection;
+ @Mock
private NotificationGroupManagerLegacy mNotificationGroupManager;
@Mock
private BubblesManager.NotifCallback mNotifCallback;
@@ -336,6 +339,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
mLockscreenUserManager,
mNotificationGroupManager,
mNotificationEntryManager,
+ mCommonNotifCollection,
mNotifPipeline,
mSysUiState,
mNotifPipelineFlags,
@@ -404,8 +408,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
public void testRemoveBubble_withDismissedNotif_notInOverflow() {
mEntryListener.onEntryAdded(mRow);
mBubbleController.updateBubble(mBubbleEntry);
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getKey()))
- .thenReturn(mRow);
+ when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
assertTrue(mBubbleController.hasBubbles());
assertBubbleNotificationNotSuppressedFromShade(mBubbleEntry);
@@ -887,7 +890,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onEntryAdded(groupedBubble.getEntry());
- when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ when(mCommonNotifCollection.getEntry(groupedBubble.getEntry().getKey()))
.thenReturn(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
@@ -911,7 +914,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(0);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onEntryAdded(groupedBubble.getEntry());
- when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ when(mCommonNotifCollection.getEntry(groupedBubble.getEntry().getKey()))
.thenReturn(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
assertTrue(mBubbleData.hasBubbleInStackWithKey(groupedBubble.getEntry().getKey()));
@@ -935,7 +938,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
ExpandableNotificationRow groupSummary = mNotificationTestHelper.createGroup(2);
ExpandableNotificationRow groupedBubble = mNotificationTestHelper.createBubbleInGroup();
mEntryListener.onEntryAdded(groupedBubble.getEntry());
- when(mNotificationEntryManager.getPendingOrActiveNotif(groupedBubble.getEntry().getKey()))
+ when(mCommonNotifCollection.getEntry(groupedBubble.getEntry().getKey()))
.thenReturn(groupedBubble.getEntry());
groupSummary.addChildNotification(groupedBubble);
@@ -1011,10 +1014,9 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
*/
@Test
public void testOverflowLoadedOnce() {
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow.getKey()))
- .thenReturn(mRow);
- when(mNotificationEntryManager.getPendingOrActiveNotif(mRow2.getKey()))
- .thenReturn(mRow2);
+ // XXX
+ when(mCommonNotifCollection.getEntry(mRow.getKey())).thenReturn(mRow);
+ when(mCommonNotifCollection.getEntry(mRow2.getKey())).thenReturn(mRow2);
mEntryListener.onEntryAdded(mRow);
mEntryListener.onEntryAdded(mRow2);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 09485d179e60..aba32ec465b5 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -667,6 +667,10 @@ public class AccessibilityWindowManager {
return null;
}
+ // Don't need to add the embedded hierarchy windows into the accessibility windows list.
+ if (mHostEmbeddedMap.size() > 0 && isEmbeddedHierarchyWindowsLocked(windowId)) {
+ return null;
+ }
final AccessibilityWindowInfo reportedWindow = AccessibilityWindowInfo.obtain();
reportedWindow.setId(windowId);
@@ -699,6 +703,21 @@ public class AccessibilityWindowManager {
return reportedWindow;
}
+ private boolean isEmbeddedHierarchyWindowsLocked(int windowId) {
+ final IBinder leashToken = mWindowIdMap.get(windowId);
+ if (leashToken == null) {
+ return false;
+ }
+
+ for (int i = 0; i < mHostEmbeddedMap.size(); i++) {
+ if (mHostEmbeddedMap.keyAt(i).equals(leashToken)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private int getTypeForWindowManagerWindowType(int windowType) {
switch (windowType) {
case WindowManager.LayoutParams.TYPE_APPLICATION:
@@ -735,8 +754,7 @@ public class AccessibilityWindowManager {
case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
case WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:
- case WindowManager.LayoutParams.TYPE_SCREENSHOT:
- case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY: {
+ case WindowManager.LayoutParams.TYPE_SCREENSHOT: {
return AccessibilityWindowInfo.TYPE_SYSTEM;
}
@@ -748,6 +766,10 @@ public class AccessibilityWindowManager {
return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
}
+ case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY: {
+ return AccessibilityWindowInfo.TYPE_MAGNIFICATION_OVERLAY;
+ }
+
default: {
return -1;
}
diff --git a/services/companion/java/com/android/server/companion/AssociationCleanUpService.java b/services/companion/java/com/android/server/companion/AssociationCleanUpService.java
new file mode 100644
index 000000000000..f1d98f09aba3
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/AssociationCleanUpService.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.companion;
+
+import static com.android.server.companion.CompanionDeviceManagerService.LOG_TAG;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.companion.AssociationRequest;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.util.Slog;
+
+import com.android.server.LocalServices;
+
+/**
+ * A Job Service responsible for clean up the Association.
+ * The job will be executed only if the device is charging and in idle mode due to the application
+ * will be killed if association/role are revoked.
+ */
+public class AssociationCleanUpService extends JobService {
+ private static final String TAG = LOG_TAG + ".AssociationCleanUpService";
+ private static final int JOB_ID = AssociationCleanUpService.class.hashCode();
+ private static final long ONE_DAY_INTERVAL = 3 * 24 * 60 * 60 * 1000; // 1 Day
+ private CompanionDeviceManagerServiceInternal mCdmServiceInternal = LocalServices.getService(
+ CompanionDeviceManagerServiceInternal.class);
+
+ @Override
+ public boolean onStartJob(final JobParameters params) {
+ Slog.i(LOG_TAG, "Execute the Association CleanUp job");
+ // Special policy for APP_STREAMING role that need to revoke associations if the device
+ // does not connect for 3 months.
+ AsyncTask.execute(() -> {
+ mCdmServiceInternal.associationCleanUp(AssociationRequest.DEVICE_PROFILE_APP_STREAMING);
+ jobFinished(params, false);
+ });
+ return true;
+ }
+
+ @Override
+ public boolean onStopJob(final JobParameters params) {
+ Slog.d(TAG, "Association cleanup job stopped; id=" + params.getJobId()
+ + ", reason="
+ + JobParameters.getInternalReasonCodeDescription(
+ params.getInternalStopReasonCode()));
+ return false;
+ }
+
+ static void schedule(Context context) {
+ Slog.i(LOG_TAG, "Scheduling the Association Cleanup job");
+ final JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);
+ final JobInfo job = new JobInfo.Builder(JOB_ID,
+ new ComponentName(context, AssociationCleanUpService.class))
+ .setRequiresCharging(true)
+ .setRequiresDeviceIdle(true)
+ .setPeriodic(ONE_DAY_INTERVAL)
+ .build();
+ jobScheduler.schedule(job);
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index c18f5fa2c782..94a97d864f58 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -149,6 +149,9 @@ public class CompanionDeviceManagerService extends SystemService
private static final String PREF_FILE_NAME = "companion_device_preferences.xml";
private static final String PREF_KEY_AUTO_REVOKE_GRANTS_DONE = "auto_revoke_grants_done";
+ private static final long ASSOCIATION_CLEAN_UP_TIME_WINDOW =
+ 90L * 24 * 60 * 60 * 1000; // 3 months
+
private static DateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static {
sDateFormat.setTimeZone(TimeZone.getDefault());
@@ -179,6 +182,7 @@ public class CompanionDeviceManagerService extends SystemService
new ArrayMap<>();
private final RemoteCallbackList<IOnAssociationsChangedListener> mListeners =
new RemoteCallbackList<>();
+ private final CompanionDeviceManagerServiceInternal mLocalService = new LocalService(this);
final Handler mMainHandler = Handler.getMain();
private CompanionDevicePresenceController mCompanionDevicePresenceController;
@@ -208,6 +212,8 @@ public class CompanionDeviceManagerService extends SystemService
mPermissionControllerManager = requireNonNull(
context.getSystemService(PermissionControllerManager.class));
mUserManager = context.getSystemService(UserManager.class);
+
+ LocalServices.addService(CompanionDeviceManagerServiceInternal.class, mLocalService);
}
@Override
@@ -250,6 +256,9 @@ public class CompanionDeviceManagerService extends SystemService
} else {
Slog.w(LOG_TAG, "No BluetoothAdapter available");
}
+ } else if (phase == PHASE_BOOT_COMPLETED) {
+ // Run the Association CleanUp job service daily.
+ AssociationCleanUpService.schedule(getContext());
}
}
@@ -294,6 +303,24 @@ public class CompanionDeviceManagerService extends SystemService
return association;
}
+ // Revoke associations if the selfManaged companion device does not connect for 3
+ // months for specific profile.
+ private void associationCleanUp(String profile) {
+ for (AssociationInfo ai : mAssociationStore.getAssociations()) {
+ if (ai.isSelfManaged()
+ && profile.equals(ai.getDeviceProfile())
+ && System.currentTimeMillis() - ai.getLastTimeConnectedMs()
+ >= ASSOCIATION_CLEAN_UP_TIME_WINDOW) {
+ Slog.d(LOG_TAG, "Removing the association for associationId: "
+ + ai.getId()
+ + " due to the device does not connect for 3 months."
+ + " Current time: "
+ + new Date(System.currentTimeMillis()));
+ disassociateInternal(ai.getId());
+ }
+ }
+ }
+
void maybeGrantAutoRevokeExemptions() {
Slog.d(LOG_TAG, "maybeGrantAutoRevokeExemptions()");
PackageManager pm = getContext().getPackageManager();
@@ -573,6 +600,9 @@ public class CompanionDeviceManagerService extends SystemService
return;
}
+ association.setLastTimeConnected(System.currentTimeMillis());
+ mAssociationStore.updateAssociation(association);
+
mCompanionDevicePresenceController.onDeviceNotifyAppeared(
association, getContext(), mMainHandler);
}
@@ -735,7 +765,8 @@ public class CompanionDeviceManagerService extends SystemService
final long timestamp = System.currentTimeMillis();
final AssociationInfo association = new AssociationInfo(id, userId, packageName,
- macAddress, displayName, deviceProfile, selfManaged, false, timestamp);
+ macAddress, displayName, deviceProfile, selfManaged, false, timestamp,
+ Long.MAX_VALUE);
Slog.i(LOG_TAG, "New CDM association created=" + association);
mAssociationStore.addAssociation(association);
@@ -1297,4 +1328,17 @@ public class CompanionDeviceManagerService extends SystemService
return Collections.unmodifiableMap(copy);
}
+
+ private final class LocalService extends CompanionDeviceManagerServiceInternal {
+ private final CompanionDeviceManagerService mService;
+
+ LocalService(CompanionDeviceManagerService service) {
+ mService = service;
+ }
+
+ @Override
+ public void associationCleanUp(String profile) {
+ mService.associationCleanUp(profile);
+ }
+ }
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerServiceInternal.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerServiceInternal.java
new file mode 100644
index 000000000000..326fefe1f8ea
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerServiceInternal.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.companion;
+
+/**
+ * Companion Device Manager Local System Service Interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class CompanionDeviceManagerServiceInternal {
+ /**
+ * @see CompanionDeviceManagerService#associationCleanUp
+ */
+ public abstract void associationCleanUp(String profile);
+}
diff --git a/services/companion/java/com/android/server/companion/PersistentDataStore.java b/services/companion/java/com/android/server/companion/PersistentDataStore.java
index 97ec3bb7127d..ef3aa7fea1b5 100644
--- a/services/companion/java/com/android/server/companion/PersistentDataStore.java
+++ b/services/companion/java/com/android/server/companion/PersistentDataStore.java
@@ -168,6 +168,7 @@ final class PersistentDataStore {
private static final String XML_ATTR_SELF_MANAGED = "self_managed";
private static final String XML_ATTR_NOTIFY_DEVICE_NEARBY = "notify_device_nearby";
private static final String XML_ATTR_TIME_APPROVED = "time_approved";
+ private static final String XML_ATTR_LAST_TIME_CONNECTED = "last_time_connected";
private static final String LEGACY_XML_ATTR_DEVICE = "device";
@@ -378,7 +379,7 @@ final class PersistentDataStore {
out.add(new AssociationInfo(associationId, userId, appPackage,
MacAddress.fromString(deviceAddress), null, profile,
- /* managedByCompanionApp */false, notify, timeApproved));
+ /* managedByCompanionApp */false, notify, timeApproved, Long.MAX_VALUE));
}
private static void readAssociationsV1(@NonNull TypedXmlPullParser parser,
@@ -408,9 +409,12 @@ final class PersistentDataStore {
final boolean selfManaged = readBooleanAttribute(parser, XML_ATTR_SELF_MANAGED);
final boolean notify = readBooleanAttribute(parser, XML_ATTR_NOTIFY_DEVICE_NEARBY);
final long timeApproved = readLongAttribute(parser, XML_ATTR_TIME_APPROVED, 0L);
+ final long lastTimeConnected = readLongAttribute(
+ parser, XML_ATTR_LAST_TIME_CONNECTED, Long.MAX_VALUE);
final AssociationInfo associationInfo = createAssociationInfoNoThrow(associationId, userId,
- appPackage, macAddress, displayName, profile, selfManaged, notify, timeApproved);
+ appPackage, macAddress, displayName, profile, selfManaged, notify, timeApproved,
+ lastTimeConnected);
if (associationInfo != null) {
out.add(associationInfo);
}
@@ -464,6 +468,8 @@ final class PersistentDataStore {
writeBooleanAttribute(
serializer, XML_ATTR_NOTIFY_DEVICE_NEARBY, a.isNotifyOnDeviceNearby());
writeLongAttribute(serializer, XML_ATTR_TIME_APPROVED, a.getTimeApprovedMs());
+ writeLongAttribute(
+ serializer, XML_ATTR_LAST_TIME_CONNECTED, a.getLastTimeConnectedMs());
serializer.endTag(null, XML_TAG_ASSOCIATION);
}
@@ -512,11 +518,11 @@ final class PersistentDataStore {
private static AssociationInfo createAssociationInfoNoThrow(int associationId,
@UserIdInt int userId, @NonNull String appPackage, @Nullable MacAddress macAddress,
@Nullable CharSequence displayName, @Nullable String profile, boolean selfManaged,
- boolean notify, long timeApproved) {
+ boolean notify, long timeApproved, long lastTimeConnected) {
AssociationInfo associationInfo = null;
try {
associationInfo = new AssociationInfo(associationId, userId, appPackage, macAddress,
- displayName, profile, selfManaged, notify, timeApproved);
+ displayName, profile, selfManaged, notify, timeApproved, lastTimeConnected);
} catch (Exception e) {
if (DEBUG) Slog.w(LOG_TAG, "Could not create AssociationInfo", e);
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index bc8da8443a7d..262933dea27f 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -45,6 +45,7 @@ import android.bluetooth.IBluetoothManager;
import android.bluetooth.IBluetoothManagerCallback;
import android.bluetooth.IBluetoothProfileServiceConnection;
import android.bluetooth.IBluetoothStateChangeCallback;
+import android.bluetooth.IBluetoothLeCallControl;
import android.content.ActivityNotFoundException;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
@@ -1323,11 +1324,15 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
+ bluetoothProfile);
}
- if (bluetoothProfile != BluetoothProfile.HEADSET) {
+ Intent intent;
+ if (bluetoothProfile == BluetoothProfile.HEADSET) {
+ intent = new Intent(IBluetoothHeadset.class.getName());
+ } else if (bluetoothProfile== BluetoothProfile.LE_CALL_CONTROL) {
+ intent = new Intent(IBluetoothLeCallControl.class.getName());
+ } else {
return false;
}
- Intent intent = new Intent(IBluetoothHeadset.class.getName());
psc = new ProfileServiceConnections(intent);
if (!psc.bindService()) {
return false;
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index a2c2dbd407a5..39516802e93b 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -39,6 +39,8 @@ import static android.net.NetworkStats.STATS_PER_UID;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.TrafficStats.UID_TETHERING;
+import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
+
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.Context;
@@ -133,12 +135,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
private static final int MAX_UID_RANGES_PER_COMMAND = 10;
- /**
- * Name representing {@link #setGlobalAlert(long)} limit when delivered to
- * {@link INetworkManagementEventObserver#limitReached(String, String)}.
- */
- public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
-
static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
static final boolean MODIFY_OPERATION_ADD = true;
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 1208cb7e3813..e7f4de2a0588 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -26,6 +26,7 @@ import android.os.Environment;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
+import android.util.ArraySet;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -45,6 +46,9 @@ import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -91,7 +95,8 @@ public final class SystemServiceManager implements Dumpable {
private long mRuntimeStartUptime;
// Services that should receive lifecycle events.
- private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
+ private List<SystemService> mServices;
+ private Set<String> mServiceClassnames;
private int mCurrentPhase = -1;
@@ -113,11 +118,13 @@ public final class SystemServiceManager implements Dumpable {
SystemServiceManager(Context context) {
mContext = context;
+ mServices = new ArrayList<>();
+ mServiceClassnames = new ArraySet<>();
// Disable using the thread pool for low ram devices
sUseLifecycleThreadPool = sUseLifecycleThreadPool
- && !ActivityManager.isLowRamDeviceStatic();
+ && !ActivityManager.isLowRamDeviceStatic();
mNumUserPoolThreads = Math.min(Runtime.getRuntime().availableProcessors(),
- DEFAULT_MAX_USER_POOL_THREADS);
+ DEFAULT_MAX_USER_POOL_THREADS);
}
/**
@@ -207,8 +214,17 @@ public final class SystemServiceManager implements Dumpable {
}
public void startService(@NonNull final SystemService service) {
+ // Check if already started
+ String className = service.getClass().getName();
+ if (mServiceClassnames.contains(className)) {
+ Slog.i(TAG, "Not starting an already started service " + className);
+ return;
+ }
+ mServiceClassnames.add(className);
+
// Register it.
mServices.add(service);
+
// Start it.
long time = SystemClock.elapsedRealtime();
try {
@@ -220,11 +236,17 @@ public final class SystemServiceManager implements Dumpable {
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}
+ /** Disallow starting new services after this call. */
+ void sealStartedServices() {
+ mServiceClassnames = Collections.emptySet();
+ mServices = Collections.unmodifiableList(mServices);
+ }
+
/**
* Starts the specified boot phase for all system services that have been started up to
* this point.
*
- * @param t trace logger
+ * @param t trace logger
* @param phase The boot phase to start.
*/
public void startBootPhase(@NonNull TimingsTraceAndSlog t, int phase) {
@@ -398,8 +420,8 @@ public final class SystemServiceManager implements Dumpable {
// Limit the lifecycle parallelization to all users other than the system user
// and only for the user start lifecycle phase for now.
final boolean useThreadPool = sUseLifecycleThreadPool
- && curUserId != UserHandle.USER_SYSTEM
- && onWhat.equals(USER_STARTING);
+ && curUserId != UserHandle.USER_SYSTEM
+ && onWhat.equals(USER_STARTING);
final ExecutorService threadPool =
useThreadPool ? Executors.newFixedThreadPool(mNumUserPoolThreads) : null;
for (int i = 0; i < serviceLen; i++) {
@@ -419,7 +441,7 @@ public final class SystemServiceManager implements Dumpable {
+ serviceName + " because it's not supported (curUser: "
+ curUser + ", prevUser:" + prevUser + ")");
} else {
- Slog.i(TAG, "Skipping " + onWhat + "User-" + curUserId + " on "
+ Slog.i(TAG, "Skipping " + onWhat + "User-" + curUserId + " on "
+ serviceName);
}
continue;
@@ -516,6 +538,7 @@ public final class SystemServiceManager implements Dumpable {
/**
* Returns whether we are booting into safe mode.
+ *
* @return safe mode flag
*/
public boolean isSafeMode() {
@@ -559,9 +582,10 @@ public final class SystemServiceManager implements Dumpable {
/**
* Ensures that the system directory exist creating one if needed.
+ *
+ * @return The system directory.
* @deprecated Use {@link Environment#getDataSystemCeDirectory()}
* or {@link Environment#getDataSystemDeDirectory()} instead.
- * @return The system directory.
*/
@Deprecated
public static File ensureSystemDir() {
@@ -578,7 +602,9 @@ public final class SystemServiceManager implements Dumpable {
pw.printf("Current phase: %d\n", mCurrentPhase);
synchronized (mTargetUsers) {
if (mCurrentUser != null) {
- pw.print("Current user: "); mCurrentUser.dump(pw); pw.println();
+ pw.print("Current user: ");
+ mCurrentUser.dump(pw);
+ pw.println();
} else {
pw.println("Current user not set!");
}
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index f591b26f1770..297d28dadde3 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -18,6 +18,7 @@ package com.android.server.adb;
import static com.android.internal.util.dump.DumpUtils.writeStringIfNotNull;
+import android.annotation.NonNull;
import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.Notification;
@@ -170,6 +171,12 @@ public class AdbDebuggingManager {
mAdbConnectionInfo = new AdbConnectionInfo();
}
+ static void sendBroadcastWithDebugPermission(@NonNull Context context, @NonNull Intent intent,
+ @NonNull UserHandle userHandle) {
+ context.sendBroadcastAsUser(intent, userHandle,
+ android.Manifest.permission.MANAGE_DEBUGGING);
+ }
+
class PairingThread extends Thread implements NsdManager.RegistrationListener {
private NsdManager mNsdManager;
private String mPublicKey;
@@ -1278,7 +1285,7 @@ public class AdbDebuggingManager {
? AdbManager.WIRELESS_STATUS_CONNECTED
: AdbManager.WIRELESS_STATUS_DISCONNECTED);
intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
private void onAdbdWifiServerConnected(int port) {
@@ -1350,7 +1357,8 @@ public class AdbDebuggingManager {
if (publicKey == null) {
Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA, AdbManager.WIRELESS_STATUS_FAIL);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
+ UserHandle.ALL);
} else {
Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
@@ -1366,7 +1374,8 @@ public class AdbDebuggingManager {
device.guid = hostname;
device.connected = false;
intent.putExtra(AdbManager.WIRELESS_PAIR_DEVICE_EXTRA, device);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent,
+ UserHandle.ALL);
// Add the key into the keystore
mAdbKeyStore.setLastConnectionTime(publicKey,
System.currentTimeMillis());
@@ -1380,14 +1389,14 @@ public class AdbDebuggingManager {
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
AdbManager.WIRELESS_STATUS_CONNECTED);
intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
private void sendPairedDevicesToUI(Map<String, PairDevice> devices) {
Intent intent = new Intent(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
// Map is not serializable, so need to downcast
intent.putExtra(AdbManager.WIRELESS_DEVICES_EXTRA, (HashMap) devices);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
private void updateUIPairCode(String code) {
@@ -1397,7 +1406,7 @@ public class AdbDebuggingManager {
intent.putExtra(AdbManager.WIRELESS_PAIRING_CODE_EXTRA, code);
intent.putExtra(AdbManager.WIRELESS_STATUS_EXTRA,
AdbManager.WIRELESS_STATUS_PAIRING_CODE);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
}
}
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index 7a4d2ce50cd3..2845fbfc6ebf 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -459,7 +459,7 @@ public class AdbService extends IAdbManager.Stub {
? AdbManager.WIRELESS_STATUS_CONNECTED
: AdbManager.WIRELESS_STATUS_DISCONNECTED);
intent.putExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, port);
- mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ AdbDebuggingManager.sendBroadcastWithDebugPermission(mContext, intent, UserHandle.ALL);
Slog.i(TAG, "sent port broadcast port=" + port);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index da8c407a501d..70bd734a9ccd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2333,7 +2333,7 @@ public class ActivityManagerService extends IActivityManager.Stub
offloadConstants.SLOW_TIME = Integer.MAX_VALUE;
mEnableOffloadQueue = SystemProperties.getBoolean(
- "persist.device_config.activity_manager_native_boot.offload_queue_enabled", false);
+ "persist.device_config.activity_manager_native_boot.offload_queue_enabled", true);
mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
"foreground", foreConstants, false);
@@ -13378,7 +13378,12 @@ public class ActivityManagerService extends IActivityManager.Stub
!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
final boolean fullUninstall = removed && !replacing;
if (removed) {
- if (!killProcess) {
+ if (killProcess) {
+ forceStopPackageLocked(ssp, UserHandle.getAppId(
+ intent.getIntExtra(Intent.EXTRA_UID, -1)),
+ false, true, true, false, fullUninstall, userId,
+ removed ? "pkg removed" : "pkg changed");
+ } else {
// Kill any app zygotes always, since they can't fork new
// processes with references to the old code
forceStopAppZygoteLocked(ssp, UserHandle.getAppId(
diff --git a/services/core/java/com/android/server/am/AppNotRespondingDialog.java b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
index 878ef31f143d..5fe842752e81 100644
--- a/services/core/java/com/android/server/am/AppNotRespondingDialog.java
+++ b/services/core/java/com/android/server/am/AppNotRespondingDialog.java
@@ -163,7 +163,9 @@ final class AppNotRespondingDialog extends BaseErrorDialog implements View.OnCli
synchronized (mService.mProcLock) {
errState.setNotResponding(false);
- errState.setNotRespondingReport(null);
+ // We're not clearing the ANR report here, in case we'd need to report
+ // it again when the ANR dialog shows again.
+ // errState.setNotRespondingReport(null);
errState.getDialogController().clearAnrDialogs();
}
mService.mServices.scheduleServiceTimeoutLocked(app);
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 336572f44be3..8561b61c2172 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -16,6 +16,7 @@
package com.android.server.am;
import android.annotation.Nullable;
+import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
@@ -712,8 +713,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
if (wifiInfo.isValid()) {
final long wifiChargeUC = measuredEnergyDeltas != null ?
measuredEnergyDeltas.wifiChargeUC : MeasuredEnergySnapshot.UNAVAILABLE;
- mStats.updateWifiState(
- extractDeltaLocked(wifiInfo), wifiChargeUC, elapsedRealtime, uptime);
+ final NetworkStatsManager networkStatsManager = mInjector.getSystemService(
+ NetworkStatsManager.class);
+ mStats.updateWifiState(extractDeltaLocked(wifiInfo),
+ wifiChargeUC, elapsedRealtime, uptime, networkStatsManager);
} else {
Slog.w(TAG, "wifi info is invalid: " + wifiInfo);
}
@@ -722,8 +725,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
if (modemInfo != null) {
final long mobileRadioChargeUC = measuredEnergyDeltas != null
? measuredEnergyDeltas.mobileRadioChargeUC : MeasuredEnergySnapshot.UNAVAILABLE;
+ final NetworkStatsManager networkStatsManager = mInjector.getSystemService(
+ NetworkStatsManager.class);
mStats.noteModemControllerActivity(modemInfo, mobileRadioChargeUC, elapsedRealtime,
- uptime);
+ uptime, networkStatsManager);
}
if (updateFlags == UPDATE_ALL) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 8cb20404b3e1..9ffafe256033 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -22,6 +22,7 @@ import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
import android.annotation.NonNull;
import android.app.StatsManager;
+import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.content.ContentResolver;
import android.content.Context;
@@ -2029,8 +2030,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
+ final NetworkStatsManager networkStatsManager = mContext.getSystemService(
+ NetworkStatsManager.class);
mHandler.post(() -> {
- mStats.updateWifiState(info, POWER_DATA_UNAVAILABLE, elapsedRealtime, uptime);
+ mStats.updateWifiState(info, POWER_DATA_UNAVAILABLE, elapsedRealtime, uptime,
+ networkStatsManager);
});
}
}
@@ -2067,9 +2071,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
+ final NetworkStatsManager networkStatsManager = mContext.getSystemService(
+ NetworkStatsManager.class);
mHandler.post(() -> {
mStats.noteModemControllerActivity(info, POWER_DATA_UNAVAILABLE, elapsedRealtime,
- uptime);
+ uptime, networkStatsManager);
});
}
}
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index c55bbe8e971b..c08cf6485855 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -539,6 +539,8 @@ public final class CachedAppOptimizer {
*/
static private native void compactProcess(int pid, int compactionFlags);
+ static private native void cancelCompaction();
+
/**
* Reads the flag value from DeviceConfig to determine whether app compaction
* should be enabled, and starts the freeze/compaction thread if needed.
@@ -1049,6 +1051,26 @@ public final class CachedAppOptimizer {
}
}
+ @GuardedBy({"mService", "mProcLock"})
+ void onOomAdjustChanged(int oldAdj, int newAdj, ProcessRecord app) {
+ // Cancel any currently executing compactions
+ // if the process moved out of cached state
+ if (DefaultProcessDependencies.mPidCompacting == app.mPid && newAdj < oldAdj
+ && newAdj < ProcessList.CACHED_APP_MIN_ADJ) {
+ cancelCompaction();
+ }
+
+ // Perform a minor compaction when a perceptible app becomes the prev/home app
+ // Perform a major compaction when any app enters cached
+ if (oldAdj <= ProcessList.PERCEPTIBLE_APP_ADJ
+ && (newAdj == ProcessList.PREVIOUS_APP_ADJ || newAdj == ProcessList.HOME_APP_ADJ)) {
+ compactAppSome(app);
+ } else if (newAdj >= ProcessList.CACHED_APP_MIN_ADJ
+ && newAdj <= ProcessList.CACHED_APP_MAX_ADJ) {
+ compactAppFull(app);
+ }
+ }
+
@VisibleForTesting
static final class LastCompactionStats {
private final long[] mRssAfterCompaction;
@@ -1091,6 +1113,13 @@ public final class CachedAppOptimizer {
name = proc.processName;
opt.setHasPendingCompact(false);
+ if (mAm.mInternal.isPendingTopUid(proc.uid)) {
+ // In case the OOM Adjust has not yet been propagated we see if this is
+ // pending on becoming top app in which case we should not compact.
+ Slog.e(TAG_AM, "Skip compaction since UID is active for " + name);
+ return;
+ }
+
// don't compact if the process has returned to perceptible
// and this is only a cached/home/prev compaction
if ((pendingAction == COMPACT_PROCESS_SOME
@@ -1500,6 +1529,8 @@ public final class CachedAppOptimizer {
* Default implementation for ProcessDependencies, public vor visibility to OomAdjuster class.
*/
private static final class DefaultProcessDependencies implements ProcessDependencies {
+ public static int mPidCompacting = -1;
+
// Get memory RSS from process.
@Override
public long[] getRss(int pid) {
@@ -1509,6 +1540,7 @@ public final class CachedAppOptimizer {
// Compact process.
@Override
public void performCompaction(String action, int pid) throws IOException {
+ mPidCompacting = pid;
if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FULL])) {
compactProcess(pid, COMPACT_ACTION_FILE_FLAG | COMPACT_ACTION_ANON_FLAG);
} else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_FILE])) {
@@ -1516,6 +1548,7 @@ public final class CachedAppOptimizer {
} else if (action.equals(COMPACT_ACTION_STRING[COMPACT_ACTION_ANON])) {
compactProcess(pid, COMPACT_ACTION_ANON_FLAG);
}
+ mPidCompacting = -1;
}
}
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index af4ff58596a1..b1234962efc2 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -2486,18 +2486,9 @@ public class OomAdjuster {
// don't compact during bootup
if (mCachedAppOptimizer.useCompaction() && mService.mBooted) {
// Cached and prev/home compaction
+ // reminder: here, setAdj is previous state, curAdj is upcoming state
if (state.getCurAdj() != state.getSetAdj()) {
- // Perform a minor compaction when a perceptible app becomes the prev/home app
- // Perform a major compaction when any app enters cached
- // reminder: here, setAdj is previous state, curAdj is upcoming state
- if (state.getSetAdj() <= ProcessList.PERCEPTIBLE_APP_ADJ
- && (state.getCurAdj() == ProcessList.PREVIOUS_APP_ADJ
- || state.getCurAdj() == ProcessList.HOME_APP_ADJ)) {
- mCachedAppOptimizer.compactAppSome(app);
- } else if (state.getCurAdj() >= ProcessList.CACHED_APP_MIN_ADJ
- && state.getCurAdj() <= ProcessList.CACHED_APP_MAX_ADJ) {
- mCachedAppOptimizer.compactAppFull(app);
- }
+ mCachedAppOptimizer.onOomAdjustChanged(state.getSetAdj(), state.getCurAdj(), app);
} else if (mService.mWakefulness.get() != PowerManagerInternal.WAKEFULNESS_AWAKE
&& state.getSetAdj() < ProcessList.FOREGROUND_APP_ADJ
// Because these can fire independent of oom_adj/procstate changes, we need
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 9b731d58153c..b3e46cd0b526 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -174,6 +174,9 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
boolean mFgsNotificationWasDeferred;
// FGS notification was shown before the FGS finishes, or it wasn't deferred in the first place.
boolean mFgsNotificationShown;
+ // Whether FGS package has permissions to show notifications.
+ // TODO(b/194833441): Output this field to logs in ActiveServices#logFGSStateChangeLocked.
+ boolean mFgsHasNotificationPermission;
// allow the service becomes foreground service? Service started from background may not be
// allowed to become a foreground service.
@@ -968,6 +971,9 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
if (nm == null) {
return;
}
+ // Record whether the package has permission to notify the user
+ mFgsHasNotificationPermission = nm.areNotificationsEnabledForPackage(
+ localPackageName, appUid);
Notification localForegroundNoti = _foregroundNoti;
try {
if (localForegroundNoti.getSmallIcon() == null) {
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 4d025c981ce9..9d4d1c1b0ff3 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -223,10 +223,10 @@ public final class AppHibernationService extends SystemService {
android.Manifest.permission.MANAGE_APP_HIBERNATION,
"Caller does not have MANAGE_APP_HIBERNATION permission.");
userId = handleIncomingUser(userId, methodName);
- if (!checkUserStatesExist(userId, methodName)) {
- return false;
- }
synchronized (mLock) {
+ if (!checkUserStatesExist(userId, methodName)) {
+ return false;
+ }
final Map<String, UserLevelState> packageStates = mUserStates.get(userId);
final UserLevelState pkgState = packageStates.get(packageName);
if (pkgState == null) {
@@ -278,10 +278,10 @@ public final class AppHibernationService extends SystemService {
android.Manifest.permission.MANAGE_APP_HIBERNATION,
"Caller does not have MANAGE_APP_HIBERNATION permission.");
final int realUserId = handleIncomingUser(userId, methodName);
- if (!checkUserStatesExist(realUserId, methodName)) {
- return;
- }
synchronized (mLock) {
+ if (!checkUserStatesExist(realUserId, methodName)) {
+ return;
+ }
final Map<String, UserLevelState> packageStates = mUserStates.get(realUserId);
final UserLevelState pkgState = packageStates.get(packageName);
if (pkgState == null) {
@@ -365,10 +365,10 @@ public final class AppHibernationService extends SystemService {
android.Manifest.permission.MANAGE_APP_HIBERNATION,
"Caller does not have MANAGE_APP_HIBERNATION permission.");
userId = handleIncomingUser(userId, methodName);
- if (!checkUserStatesExist(userId, methodName)) {
- return hibernatingPackages;
- }
synchronized (mLock) {
+ if (!checkUserStatesExist(userId, methodName)) {
+ return hibernatingPackages;
+ }
Map<String, UserLevelState> userStates = mUserStates.get(userId);
for (UserLevelState state : userStates.values()) {
if (state.hibernated) {
@@ -658,6 +658,14 @@ public final class AppHibernationService extends SystemService {
}
}
+ /**
+ * Check that user states exist.
+ *
+ * @param userId user to check
+ * @param methodName method name that is calling. Used for logging purposes.
+ * @return true if user states exist
+ */
+ @GuardedBy("mLock")
private boolean checkUserStatesExist(int userId, String methodName) {
if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
Slog.e(TAG, String.format(
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 0879bec665ba..805e45db7010 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -8541,7 +8541,7 @@ public class AudioService extends IAudioService.Stub
/** @see Spatializer#getSpatializerCompatibleAudioDevices() */
public @NonNull List<AudioDeviceAttributes> getSpatializerCompatibleAudioDevices() {
- enforceModifyAudioRoutingPermission();
+ enforceModifyDefaultAudioEffectsPermission();
return mSpatializerHelper.getCompatibleAudioDevices();
}
@@ -9319,8 +9319,6 @@ public class AudioService extends IAudioService.Stub
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
- mAudioSystem.dump(pw);
-
sLifecycleLogger.dump(pw);
if (mAudioHandler != null) {
pw.println("\nMessage handler (watch for unhandled messages):");
@@ -9400,6 +9398,8 @@ public class AudioService extends IAudioService.Stub
pw.println("mHasSpatializerEffect:" + mHasSpatializerEffect);
pw.println("isSpatializerEnabled:" + isSpatializerEnabled());
pw.println("isSpatialAudioEnabled:" + isSpatialAudioEnabled());
+
+ mAudioSystem.dump(pw);
}
private void dumpSupportedSystemUsage(PrintWriter pw) {
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index ac212eee21e6..a2ba76b6fd6a 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -524,11 +524,28 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback {
* @param pw
*/
public void dump(PrintWriter pw) {
+ pw.println("\nAudioSystemAdapter:");
+ pw.println(" mDevicesForStreamCache:");
+ if (mDevicesForStreamCache != null) {
+ for (Integer stream : mDevicesForStreamCache.keySet()) {
+ pw.println("\t stream:" + stream + " device:"
+ + AudioSystem.getOutputDeviceName(mDevicesForStreamCache.get(stream)));
+ }
+ }
+ pw.println(" mDevicesForAttrCache:");
+ if (mDevicesForAttrCache != null) {
+ for (AudioAttributes attr : mDevicesForAttrCache.keySet()) {
+ pw.println("\t" + attr);
+ for (AudioDeviceAttributes devAttr : mDevicesForAttrCache.get(attr)) {
+ pw.println("\t\t" + devAttr);
+ }
+ }
+ }
+
if (!ENABLE_GETDEVICES_STATS) {
- // only stats in this dump
+ // only stats in the rest of this dump
return;
}
- pw.println("\nAudioSystemAdapter:");
for (int i = 0; i < NB_MEASUREMENTS; i++) {
pw.println(mMethodNames[i]
+ ": counter=" + mMethodCallCounter[i]
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 9273a5d5cf9c..6ec983620698 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -102,8 +102,6 @@ public class BtHelper {
/*package*/ static final int SCO_MODE_UNDEFINED = -1;
// SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall())
/*package*/ static final int SCO_MODE_VIRTUAL_CALL = 0;
- // SCO audio mode is raw audio (BluetoothHeadset.connectAudio())
- private static final int SCO_MODE_RAW = 1;
// SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition())
private static final int SCO_MODE_VR = 2;
// max valid SCO audio mode values
@@ -122,8 +120,6 @@ public class BtHelper {
return "SCO_MODE_UNDEFINED";
case SCO_MODE_VIRTUAL_CALL:
return "SCO_MODE_VIRTUAL_CALL";
- case SCO_MODE_RAW:
- return "SCO_MODE_RAW";
case SCO_MODE_VR:
return "SCO_MODE_VR";
default:
@@ -812,8 +808,6 @@ public class BtHelper {
private static boolean disconnectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset,
BluetoothDevice device, int scoAudioMode) {
switch (scoAudioMode) {
- case SCO_MODE_RAW:
- return bluetoothHeadset.disconnectAudio();
case SCO_MODE_VIRTUAL_CALL:
return bluetoothHeadset.stopScoUsingVirtualVoiceCall();
case SCO_MODE_VR:
@@ -826,8 +820,6 @@ public class BtHelper {
private static boolean connectBluetoothScoAudioHelper(BluetoothHeadset bluetoothHeadset,
BluetoothDevice device, int scoAudioMode) {
switch (scoAudioMode) {
- case SCO_MODE_RAW:
- return bluetoothHeadset.connectAudio();
case SCO_MODE_VIRTUAL_CALL:
return bluetoothHeadset.startScoUsingVirtualVoiceCall();
case SCO_MODE_VR:
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index 26bbb403f39f..b73e91173a43 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -16,8 +16,6 @@
package com.android.server.biometrics.sensors;
-import static com.android.internal.annotations.VisibleForTesting.Visibility;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -50,6 +48,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
* Interface that ClientMonitor holders should use to receive callbacks.
*/
public interface Callback {
+
/**
* Invoked when the ClientMonitor operation has been started (e.g. reached the head of
* the queue and becomes the current operation).
@@ -204,8 +203,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
}
/** Signals this operation has completed its lifecycle and should no longer be used. */
- @VisibleForTesting(visibility = Visibility.PACKAGE)
- public void destroy() {
+ void destroy() {
mAlreadyDone = true;
if (mToken != null) {
try {
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
index 1f91c4d6803e..a358bc2bad55 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -17,14 +17,15 @@
package com.android.server.biometrics.sensors;
import android.annotation.IntDef;
-import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.IBiometricService;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Slog;
@@ -54,7 +55,6 @@ import java.util.Locale;
* We currently assume (and require) that each biometric sensor have its own instance of a
* {@link BiometricScheduler}. See {@link CoexCoordinator}.
*/
-@MainThread
public class BiometricScheduler {
private static final String BASE_TAG = "BiometricScheduler";
@@ -110,6 +110,123 @@ public class BiometricScheduler {
}
}
+ /**
+ * Contains all the necessary information for a HAL operation.
+ */
+ @VisibleForTesting
+ static final class Operation {
+
+ /**
+ * The operation is added to the list of pending operations and waiting for its turn.
+ */
+ static final int STATE_WAITING_IN_QUEUE = 0;
+
+ /**
+ * The operation is added to the list of pending operations, but a subsequent operation
+ * has been added. This state only applies to {@link Interruptable} operations. When this
+ * operation reaches the head of the queue, it will send ERROR_CANCELED and finish.
+ */
+ static final int STATE_WAITING_IN_QUEUE_CANCELING = 1;
+
+ /**
+ * The operation has reached the front of the queue and has started.
+ */
+ static final int STATE_STARTED = 2;
+
+ /**
+ * The operation was started, but is now canceling. Operations should wait for the HAL to
+ * acknowledge that the operation was canceled, at which point it finishes.
+ */
+ static final int STATE_STARTED_CANCELING = 3;
+
+ /**
+ * The operation has reached the head of the queue but is waiting for BiometricService
+ * to acknowledge and start the operation.
+ */
+ static final int STATE_WAITING_FOR_COOKIE = 4;
+
+ /**
+ * The {@link BaseClientMonitor.Callback} has been invoked and the client is finished.
+ */
+ static final int STATE_FINISHED = 5;
+
+ @IntDef({STATE_WAITING_IN_QUEUE,
+ STATE_WAITING_IN_QUEUE_CANCELING,
+ STATE_STARTED,
+ STATE_STARTED_CANCELING,
+ STATE_WAITING_FOR_COOKIE,
+ STATE_FINISHED})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface OperationState {}
+
+ @NonNull final BaseClientMonitor mClientMonitor;
+ @Nullable final BaseClientMonitor.Callback mClientCallback;
+ @OperationState int mState;
+
+ Operation(
+ @NonNull BaseClientMonitor clientMonitor,
+ @Nullable BaseClientMonitor.Callback callback
+ ) {
+ this(clientMonitor, callback, STATE_WAITING_IN_QUEUE);
+ }
+
+ protected Operation(
+ @NonNull BaseClientMonitor clientMonitor,
+ @Nullable BaseClientMonitor.Callback callback,
+ @OperationState int state
+ ) {
+ mClientMonitor = clientMonitor;
+ mClientCallback = callback;
+ mState = state;
+ }
+
+ public boolean isHalOperation() {
+ return mClientMonitor instanceof HalClientMonitor<?>;
+ }
+
+ /**
+ * @return true if the operation requires the HAL, and the HAL is null.
+ */
+ public boolean isUnstartableHalOperation() {
+ if (isHalOperation()) {
+ final HalClientMonitor<?> client = (HalClientMonitor<?>) mClientMonitor;
+ if (client.getFreshDaemon() == null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return mClientMonitor + ", State: " + mState;
+ }
+ }
+
+ /**
+ * Monitors an operation's cancellation. If cancellation takes too long, the watchdog will
+ * kill the current operation and forcibly start the next.
+ */
+ private static final class CancellationWatchdog implements Runnable {
+ static final int DELAY_MS = 3000;
+
+ final String tag;
+ final Operation operation;
+ CancellationWatchdog(String tag, Operation operation) {
+ this.tag = tag;
+ this.operation = operation;
+ }
+
+ @Override
+ public void run() {
+ if (operation.mState != Operation.STATE_FINISHED) {
+ Slog.e(tag, "[Watchdog Triggered]: " + operation);
+ operation.mClientMonitor.mCallback
+ .onClientFinished(operation.mClientMonitor, false /* success */);
+ }
+ }
+ }
+
private static final class CrashState {
static final int NUM_ENTRIES = 10;
final String timestamp;
@@ -146,9 +263,10 @@ public class BiometricScheduler {
private final @SensorType int mSensorType;
@Nullable private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
@NonNull private final IBiometricService mBiometricService;
- @NonNull protected final Handler mHandler;
- @VisibleForTesting @NonNull final Deque<BiometricSchedulerOperation> mPendingOperations;
- @VisibleForTesting @Nullable BiometricSchedulerOperation mCurrentOperation;
+ @NonNull protected final Handler mHandler = new Handler(Looper.getMainLooper());
+ @NonNull private final InternalCallback mInternalCallback;
+ @VisibleForTesting @NonNull final Deque<Operation> mPendingOperations;
+ @VisibleForTesting @Nullable Operation mCurrentOperation;
@NonNull private final ArrayDeque<CrashState> mCrashStates;
private int mTotalOperationsHandled;
@@ -159,7 +277,7 @@ public class BiometricScheduler {
// Internal callback, notified when an operation is complete. Notifies the requester
// that the operation is complete, before performing internal scheduler work (such as
// starting the next client).
- private final BaseClientMonitor.Callback mInternalCallback = new BaseClientMonitor.Callback() {
+ public class InternalCallback implements BaseClientMonitor.Callback {
@Override
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
Slog.d(getTag(), "[Started] " + clientMonitor);
@@ -168,11 +286,16 @@ public class BiometricScheduler {
mCoexCoordinator.addAuthenticationClient(mSensorType,
(AuthenticationClient<?>) clientMonitor);
}
+
+ if (mCurrentOperation.mClientCallback != null) {
+ mCurrentOperation.mClientCallback.onClientStarted(clientMonitor);
+ }
}
@Override
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) {
mHandler.post(() -> {
+ clientMonitor.destroy();
if (mCurrentOperation == null) {
Slog.e(getTag(), "[Finishing] " + clientMonitor
+ " but current operation is null, success: " + success
@@ -180,9 +303,9 @@ public class BiometricScheduler {
return;
}
- if (!mCurrentOperation.isFor(clientMonitor)) {
+ if (clientMonitor != mCurrentOperation.mClientMonitor) {
Slog.e(getTag(), "[Ignoring Finish] " + clientMonitor + " does not match"
- + " current: " + mCurrentOperation);
+ + " current: " + mCurrentOperation.mClientMonitor);
return;
}
@@ -192,33 +315,36 @@ public class BiometricScheduler {
(AuthenticationClient<?>) clientMonitor);
}
+ mCurrentOperation.mState = Operation.STATE_FINISHED;
+
+ if (mCurrentOperation.mClientCallback != null) {
+ mCurrentOperation.mClientCallback.onClientFinished(clientMonitor, success);
+ }
+
if (mGestureAvailabilityDispatcher != null) {
mGestureAvailabilityDispatcher.markSensorActive(
- mCurrentOperation.getSensorId(), false /* active */);
+ mCurrentOperation.mClientMonitor.getSensorId(), false /* active */);
}
if (mRecentOperations.size() >= mRecentOperationsLimit) {
mRecentOperations.remove(0);
}
- mRecentOperations.add(mCurrentOperation.getProtoEnum());
+ mRecentOperations.add(mCurrentOperation.mClientMonitor.getProtoEnum());
mCurrentOperation = null;
mTotalOperationsHandled++;
startNextOperationIfIdle();
});
}
- };
+ }
@VisibleForTesting
- BiometricScheduler(@NonNull String tag,
- @NonNull Handler handler,
- @SensorType int sensorType,
+ BiometricScheduler(@NonNull String tag, @SensorType int sensorType,
@Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
- @NonNull IBiometricService biometricService,
- int recentOperationsLimit,
+ @NonNull IBiometricService biometricService, int recentOperationsLimit,
@NonNull CoexCoordinator coexCoordinator) {
mBiometricTag = tag;
- mHandler = handler;
mSensorType = sensorType;
+ mInternalCallback = new InternalCallback();
mGestureAvailabilityDispatcher = gestureAvailabilityDispatcher;
mPendingOperations = new ArrayDeque<>();
mBiometricService = biometricService;
@@ -230,26 +356,24 @@ public class BiometricScheduler {
/**
* Creates a new scheduler.
- *
* @param tag for the specific instance of the scheduler. Should be unique.
- * @param handler handler for callbacks (all methods of this class must be called on the
- * thread associated with this handler)
* @param sensorType the sensorType that this scheduler is handling.
* @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures
* (such as fingerprint swipe).
*/
public BiometricScheduler(@NonNull String tag,
- @NonNull Handler handler,
@SensorType int sensorType,
@Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
- this(tag, handler, sensorType, gestureAvailabilityDispatcher,
- IBiometricService.Stub.asInterface(
- ServiceManager.getService(Context.BIOMETRIC_SERVICE)),
- LOG_NUM_RECENT_OPERATIONS, CoexCoordinator.getInstance());
+ this(tag, sensorType, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface(
+ ServiceManager.getService(Context.BIOMETRIC_SERVICE)), LOG_NUM_RECENT_OPERATIONS,
+ CoexCoordinator.getInstance());
}
- @VisibleForTesting
- public BaseClientMonitor.Callback getInternalCallback() {
+ /**
+ * @return A reference to the internal callback that should be invoked whenever the scheduler
+ * needs to (e.g. client started, client finished).
+ */
+ @NonNull protected InternalCallback getInternalCallback() {
return mInternalCallback;
}
@@ -268,46 +392,72 @@ public class BiometricScheduler {
}
mCurrentOperation = mPendingOperations.poll();
+ final BaseClientMonitor currentClient = mCurrentOperation.mClientMonitor;
Slog.d(getTag(), "[Polled] " + mCurrentOperation);
// If the operation at the front of the queue has been marked for cancellation, send
// ERROR_CANCELED. No need to start this client.
- if (mCurrentOperation.isMarkedCanceling()) {
+ if (mCurrentOperation.mState == Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
Slog.d(getTag(), "[Now Cancelling] " + mCurrentOperation);
- mCurrentOperation.cancel(mHandler, mInternalCallback);
+ if (!(currentClient instanceof Interruptable)) {
+ throw new IllegalStateException("Mis-implemented client or scheduler, "
+ + "trying to cancel non-interruptable operation: " + mCurrentOperation);
+ }
+
+ final Interruptable interruptable = (Interruptable) currentClient;
+ interruptable.cancelWithoutStarting(getInternalCallback());
// Now we wait for the client to send its FinishCallback, which kicks off the next
// operation.
return;
}
- if (mGestureAvailabilityDispatcher != null && mCurrentOperation.isAcquisitionOperation()) {
+ if (mGestureAvailabilityDispatcher != null
+ && mCurrentOperation.mClientMonitor instanceof AcquisitionClient) {
mGestureAvailabilityDispatcher.markSensorActive(
- mCurrentOperation.getSensorId(), true /* active */);
+ mCurrentOperation.mClientMonitor.getSensorId(),
+ true /* active */);
}
// Not all operations start immediately. BiometricPrompt waits for its operation
// to arrive at the head of the queue, before pinging it to start.
- final int cookie = mCurrentOperation.isReadyToStart();
- if (cookie == 0) {
- if (!mCurrentOperation.start(mInternalCallback)) {
+ final boolean shouldStartNow = currentClient.getCookie() == 0;
+ if (shouldStartNow) {
+ if (mCurrentOperation.isUnstartableHalOperation()) {
+ final HalClientMonitor<?> halClientMonitor =
+ (HalClientMonitor<?>) mCurrentOperation.mClientMonitor;
// Note down current length of queue
final int pendingOperationsLength = mPendingOperations.size();
- final BiometricSchedulerOperation lastOperation = mPendingOperations.peekLast();
+ final Operation lastOperation = mPendingOperations.peekLast();
Slog.e(getTag(), "[Unable To Start] " + mCurrentOperation
+ ". Last pending operation: " + lastOperation);
+ // For current operations, 1) unableToStart, which notifies the caller-side, then
+ // 2) notify operation's callback, to notify applicable system service that the
+ // operation failed.
+ halClientMonitor.unableToStart();
+ if (mCurrentOperation.mClientCallback != null) {
+ mCurrentOperation.mClientCallback.onClientFinished(
+ mCurrentOperation.mClientMonitor, false /* success */);
+ }
+
// Then for each operation currently in the pending queue at the time of this
// failure, do the same as above. Otherwise, it's possible that something like
// setActiveUser fails, but then authenticate (for the wrong user) is invoked.
for (int i = 0; i < pendingOperationsLength; i++) {
- final BiometricSchedulerOperation operation = mPendingOperations.pollFirst();
- if (operation != null) {
- Slog.w(getTag(), "[Aborting Operation] " + operation);
- operation.abort();
- } else {
+ final Operation operation = mPendingOperations.pollFirst();
+ if (operation == null) {
Slog.e(getTag(), "Null operation, index: " + i
+ ", expected length: " + pendingOperationsLength);
+ break;
+ }
+ if (operation.isHalOperation()) {
+ ((HalClientMonitor<?>) operation.mClientMonitor).unableToStart();
+ }
+ if (operation.mClientCallback != null) {
+ operation.mClientCallback.onClientFinished(operation.mClientMonitor,
+ false /* success */);
}
+ Slog.w(getTag(), "[Aborted Operation] " + operation);
}
// It's possible that during cleanup a new set of operations came in. We can try to
@@ -315,20 +465,25 @@ public class BiometricScheduler {
// actually be multiple operations (i.e. updateActiveUser + authenticate).
mCurrentOperation = null;
startNextOperationIfIdle();
+ } else {
+ Slog.d(getTag(), "[Starting] " + mCurrentOperation);
+ currentClient.start(getInternalCallback());
+ mCurrentOperation.mState = Operation.STATE_STARTED;
}
} else {
try {
- mBiometricService.onReadyForAuthentication(cookie);
+ mBiometricService.onReadyForAuthentication(currentClient.getCookie());
} catch (RemoteException e) {
Slog.e(getTag(), "Remote exception when contacting BiometricService", e);
}
Slog.d(getTag(), "Waiting for cookie before starting: " + mCurrentOperation);
+ mCurrentOperation.mState = Operation.STATE_WAITING_FOR_COOKIE;
}
}
/**
* Starts the {@link #mCurrentOperation} if
- * 1) its state is {@link BiometricSchedulerOperation#STATE_WAITING_FOR_COOKIE} and
+ * 1) its state is {@link Operation#STATE_WAITING_FOR_COOKIE} and
* 2) its cookie matches this cookie
*
* This is currently only used by {@link com.android.server.biometrics.BiometricService}, which
@@ -344,13 +499,45 @@ public class BiometricScheduler {
Slog.e(getTag(), "Current operation is null");
return;
}
+ if (mCurrentOperation.mState != Operation.STATE_WAITING_FOR_COOKIE) {
+ if (mCurrentOperation.mState == Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
+ Slog.d(getTag(), "Operation was marked for cancellation, cancelling now: "
+ + mCurrentOperation);
+ // This should trigger the internal onClientFinished callback, which clears the
+ // operation and starts the next one.
+ final ErrorConsumer errorConsumer =
+ (ErrorConsumer) mCurrentOperation.mClientMonitor;
+ errorConsumer.onError(BiometricConstants.BIOMETRIC_ERROR_CANCELED,
+ 0 /* vendorCode */);
+ return;
+ } else {
+ Slog.e(getTag(), "Operation is in the wrong state: " + mCurrentOperation
+ + ", expected STATE_WAITING_FOR_COOKIE");
+ return;
+ }
+ }
+ if (mCurrentOperation.mClientMonitor.getCookie() != cookie) {
+ Slog.e(getTag(), "Mismatched cookie for operation: " + mCurrentOperation
+ + ", received: " + cookie);
+ return;
+ }
- if (mCurrentOperation.startWithCookie(mInternalCallback, cookie)) {
- Slog.d(getTag(), "[Started] Prepared client: " + mCurrentOperation);
- } else {
+ if (mCurrentOperation.isUnstartableHalOperation()) {
Slog.e(getTag(), "[Unable To Start] Prepared client: " + mCurrentOperation);
+ // This is BiometricPrompt trying to auth but something's wrong with the HAL.
+ final HalClientMonitor<?> halClientMonitor =
+ (HalClientMonitor<?>) mCurrentOperation.mClientMonitor;
+ halClientMonitor.unableToStart();
+ if (mCurrentOperation.mClientCallback != null) {
+ mCurrentOperation.mClientCallback.onClientFinished(mCurrentOperation.mClientMonitor,
+ false /* success */);
+ }
mCurrentOperation = null;
startNextOperationIfIdle();
+ } else {
+ Slog.d(getTag(), "[Starting] Prepared client: " + mCurrentOperation);
+ mCurrentOperation.mState = Operation.STATE_STARTED;
+ mCurrentOperation.mClientMonitor.start(getInternalCallback());
}
}
@@ -375,13 +562,17 @@ public class BiometricScheduler {
// pending clients as canceling. Once they reach the head of the queue, the scheduler will
// send ERROR_CANCELED and skip the operation.
if (clientMonitor.interruptsPrecedingClients()) {
- for (BiometricSchedulerOperation operation : mPendingOperations) {
- Slog.d(getTag(), "New client, marking pending op as canceling: " + operation);
- operation.markCanceling();
+ for (Operation operation : mPendingOperations) {
+ if (operation.mClientMonitor instanceof Interruptable
+ && operation.mState != Operation.STATE_WAITING_IN_QUEUE_CANCELING) {
+ Slog.d(getTag(), "New client incoming, marking pending client as canceling: "
+ + operation.mClientMonitor);
+ operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING;
+ }
}
}
- mPendingOperations.add(new BiometricSchedulerOperation(clientMonitor, clientCallback));
+ mPendingOperations.add(new Operation(clientMonitor, clientCallback));
Slog.d(getTag(), "[Added] " + clientMonitor
+ ", new queue size: " + mPendingOperations.size());
@@ -389,34 +580,67 @@ public class BiometricScheduler {
// cancellable, start the cancellation process.
if (clientMonitor.interruptsPrecedingClients()
&& mCurrentOperation != null
- && mCurrentOperation.isInterruptable()
- && mCurrentOperation.isStarted()) {
+ && mCurrentOperation.mClientMonitor instanceof Interruptable
+ && mCurrentOperation.mState == Operation.STATE_STARTED) {
Slog.d(getTag(), "[Cancelling Interruptable]: " + mCurrentOperation);
- mCurrentOperation.cancel(mHandler, mInternalCallback);
- } else {
+ cancelInternal(mCurrentOperation);
+ }
+
+ startNextOperationIfIdle();
+ }
+
+ private void cancelInternal(Operation operation) {
+ if (operation != mCurrentOperation) {
+ Slog.e(getTag(), "cancelInternal invoked on non-current operation: " + operation);
+ return;
+ }
+ if (!(operation.mClientMonitor instanceof Interruptable)) {
+ Slog.w(getTag(), "Operation not interruptable: " + operation);
+ return;
+ }
+ if (operation.mState == Operation.STATE_STARTED_CANCELING) {
+ Slog.w(getTag(), "Cancel already invoked for operation: " + operation);
+ return;
+ }
+ if (operation.mState == Operation.STATE_WAITING_FOR_COOKIE) {
+ Slog.w(getTag(), "Skipping cancellation for non-started operation: " + operation);
+ // We can set it to null immediately, since the HAL was never notified to start.
+ if (mCurrentOperation != null) {
+ mCurrentOperation.mClientMonitor.destroy();
+ }
+ mCurrentOperation = null;
startNextOperationIfIdle();
+ return;
}
+ Slog.d(getTag(), "[Cancelling] Current client: " + operation.mClientMonitor);
+ final Interruptable interruptable = (Interruptable) operation.mClientMonitor;
+ interruptable.cancel();
+ operation.mState = Operation.STATE_STARTED_CANCELING;
+
+ // Add a watchdog. If the HAL does not acknowledge within the timeout, we will
+ // forcibly finish this client.
+ mHandler.postDelayed(new CancellationWatchdog(getTag(), operation),
+ CancellationWatchdog.DELAY_MS);
}
/**
* Requests to cancel enrollment.
* @param token from the caller, should match the token passed in when requesting enrollment
*/
- public void cancelEnrollment(IBinder token, long requestId) {
- Slog.d(getTag(), "cancelEnrollment, requestId: " + requestId);
-
- if (mCurrentOperation != null
- && canCancelEnrollOperation(mCurrentOperation, token, requestId)) {
- Slog.d(getTag(), "Cancelling enrollment op: " + mCurrentOperation);
- mCurrentOperation.cancel(mHandler, mInternalCallback);
- } else {
- for (BiometricSchedulerOperation operation : mPendingOperations) {
- if (canCancelEnrollOperation(operation, token, requestId)) {
- Slog.d(getTag(), "Cancelling pending enrollment op: " + operation);
- operation.markCanceling();
- }
- }
+ public void cancelEnrollment(IBinder token) {
+ if (mCurrentOperation == null) {
+ Slog.e(getTag(), "Unable to cancel enrollment, null operation");
+ return;
+ }
+ final boolean isEnrolling = mCurrentOperation.mClientMonitor instanceof EnrollClient;
+ final boolean tokenMatches = mCurrentOperation.mClientMonitor.getToken() == token;
+ if (!isEnrolling || !tokenMatches) {
+ Slog.w(getTag(), "Not cancelling enrollment, isEnrolling: " + isEnrolling
+ + " tokenMatches: " + tokenMatches);
+ return;
}
+
+ cancelInternal(mCurrentOperation);
}
/**
@@ -425,42 +649,62 @@ public class BiometricScheduler {
* @param requestId the id returned when requesting authentication
*/
public void cancelAuthenticationOrDetection(IBinder token, long requestId) {
- Slog.d(getTag(), "cancelAuthenticationOrDetection, requestId: " + requestId);
+ Slog.d(getTag(), "cancelAuthenticationOrDetection, requestId: " + requestId
+ + " current: " + mCurrentOperation
+ + " stack size: " + mPendingOperations.size());
if (mCurrentOperation != null
&& canCancelAuthOperation(mCurrentOperation, token, requestId)) {
- Slog.d(getTag(), "Cancelling auth/detect op: " + mCurrentOperation);
- mCurrentOperation.cancel(mHandler, mInternalCallback);
+ Slog.d(getTag(), "Cancelling: " + mCurrentOperation);
+ cancelInternal(mCurrentOperation);
} else {
- for (BiometricSchedulerOperation operation : mPendingOperations) {
+ // Look through the current queue for all authentication clients for the specified
+ // token, and mark them as STATE_WAITING_IN_QUEUE_CANCELING. Note that we're marking
+ // all of them, instead of just the first one, since the API surface currently doesn't
+ // allow us to distinguish between multiple authentication requests from the same
+ // process. However, this generally does not happen anyway, and would be a class of
+ // bugs on its own.
+ for (Operation operation : mPendingOperations) {
if (canCancelAuthOperation(operation, token, requestId)) {
- Slog.d(getTag(), "Cancelling pending auth/detect op: " + operation);
- operation.markCanceling();
+ Slog.d(getTag(), "Marking " + operation
+ + " as STATE_WAITING_IN_QUEUE_CANCELING");
+ operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING;
}
}
}
}
- private static boolean canCancelEnrollOperation(BiometricSchedulerOperation operation,
- IBinder token, long requestId) {
- return operation.isEnrollOperation()
- && operation.isMatchingToken(token)
- && operation.isMatchingRequestId(requestId);
+ private static boolean canCancelAuthOperation(Operation operation, IBinder token,
+ long requestId) {
+ // TODO: restrict callers that can cancel without requestId (negative value)?
+ return isAuthenticationOrDetectionOperation(operation)
+ && operation.mClientMonitor.getToken() == token
+ && isMatchingRequestId(operation, requestId);
+ }
+
+ // By default, monitors are not associated with a request id to retain the original
+ // behavior (i.e. if no requestId is explicitly set then assume it matches)
+ private static boolean isMatchingRequestId(Operation operation, long requestId) {
+ return !operation.mClientMonitor.hasRequestId()
+ || operation.mClientMonitor.getRequestId() == requestId;
}
- private static boolean canCancelAuthOperation(BiometricSchedulerOperation operation,
- IBinder token, long requestId) {
- // TODO: restrict callers that can cancel without requestId (negative value)?
- return operation.isAuthenticationOrDetectionOperation()
- && operation.isMatchingToken(token)
- && operation.isMatchingRequestId(requestId);
+ private static boolean isAuthenticationOrDetectionOperation(@NonNull Operation operation) {
+ final boolean isAuthentication =
+ operation.mClientMonitor instanceof AuthenticationConsumer;
+ final boolean isDetection =
+ operation.mClientMonitor instanceof DetectionConsumer;
+ return isAuthentication || isDetection;
}
/**
* @return the current operation
*/
public BaseClientMonitor getCurrentClient() {
- return mCurrentOperation != null ? mCurrentOperation.getClientMonitor() : null;
+ if (mCurrentOperation == null) {
+ return null;
+ }
+ return mCurrentOperation.mClientMonitor;
}
public int getCurrentPendingCount() {
@@ -475,7 +719,7 @@ public class BiometricScheduler {
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US);
final String timestamp = dateFormat.format(new Date(System.currentTimeMillis()));
final List<String> pendingOperations = new ArrayList<>();
- for (BiometricSchedulerOperation operation : mPendingOperations) {
+ for (Operation operation : mPendingOperations) {
pendingOperations.add(operation.toString());
}
@@ -491,7 +735,7 @@ public class BiometricScheduler {
pw.println("Type: " + mSensorType);
pw.println("Current operation: " + mCurrentOperation);
pw.println("Pending operations: " + mPendingOperations.size());
- for (BiometricSchedulerOperation operation : mPendingOperations) {
+ for (Operation operation : mPendingOperations) {
pw.println("Pending operation: " + operation);
}
for (CrashState crashState : mCrashStates) {
@@ -502,7 +746,7 @@ public class BiometricScheduler {
public byte[] dumpProtoState(boolean clearSchedulerBuffer) {
final ProtoOutputStream proto = new ProtoOutputStream();
proto.write(BiometricSchedulerProto.CURRENT_OPERATION, mCurrentOperation != null
- ? mCurrentOperation.getProtoEnum() : BiometricsProto.CM_NONE);
+ ? mCurrentOperation.mClientMonitor.getProtoEnum() : BiometricsProto.CM_NONE);
proto.write(BiometricSchedulerProto.TOTAL_OPERATIONS, mTotalOperationsHandled);
if (!mRecentOperations.isEmpty()) {
@@ -527,7 +771,6 @@ public class BiometricScheduler {
* HAL dies.
*/
public void reset() {
- Slog.d(getTag(), "Resetting scheduler");
mPendingOperations.clear();
mCurrentOperation = null;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java b/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java
deleted file mode 100644
index a8cce153dc70..000000000000
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.hardware.biometrics.BiometricConstants;
-import android.os.Handler;
-import android.os.IBinder;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Contains all the necessary information for a HAL operation.
- */
-public class BiometricSchedulerOperation {
- protected static final String TAG = "BiometricSchedulerOperation";
-
- /**
- * The operation is added to the list of pending operations and waiting for its turn.
- */
- protected static final int STATE_WAITING_IN_QUEUE = 0;
-
- /**
- * The operation is added to the list of pending operations, but a subsequent operation
- * has been added. This state only applies to {@link Interruptable} operations. When this
- * operation reaches the head of the queue, it will send ERROR_CANCELED and finish.
- */
- protected static final int STATE_WAITING_IN_QUEUE_CANCELING = 1;
-
- /**
- * The operation has reached the front of the queue and has started.
- */
- protected static final int STATE_STARTED = 2;
-
- /**
- * The operation was started, but is now canceling. Operations should wait for the HAL to
- * acknowledge that the operation was canceled, at which point it finishes.
- */
- protected static final int STATE_STARTED_CANCELING = 3;
-
- /**
- * The operation has reached the head of the queue but is waiting for BiometricService
- * to acknowledge and start the operation.
- */
- protected static final int STATE_WAITING_FOR_COOKIE = 4;
-
- /**
- * The {@link BaseClientMonitor.Callback} has been invoked and the client is finished.
- */
- protected static final int STATE_FINISHED = 5;
-
- @IntDef({STATE_WAITING_IN_QUEUE,
- STATE_WAITING_IN_QUEUE_CANCELING,
- STATE_STARTED,
- STATE_STARTED_CANCELING,
- STATE_WAITING_FOR_COOKIE,
- STATE_FINISHED})
- @Retention(RetentionPolicy.SOURCE)
- protected @interface OperationState {}
-
- private static final int CANCEL_WATCHDOG_DELAY_MS = 3000;
-
- @NonNull
- private final BaseClientMonitor mClientMonitor;
- @Nullable
- private final BaseClientMonitor.Callback mClientCallback;
- @OperationState
- private int mState;
- @VisibleForTesting
- @NonNull
- final Runnable mCancelWatchdog;
-
- BiometricSchedulerOperation(
- @NonNull BaseClientMonitor clientMonitor,
- @Nullable BaseClientMonitor.Callback callback
- ) {
- this(clientMonitor, callback, STATE_WAITING_IN_QUEUE);
- }
-
- protected BiometricSchedulerOperation(
- @NonNull BaseClientMonitor clientMonitor,
- @Nullable BaseClientMonitor.Callback callback,
- @OperationState int state
- ) {
- mClientMonitor = clientMonitor;
- mClientCallback = callback;
- mState = state;
- mCancelWatchdog = () -> {
- if (!isFinished()) {
- Slog.e(TAG, "[Watchdog Triggered]: " + this);
- getWrappedCallback().onClientFinished(mClientMonitor, false /* success */);
- }
- };
- }
-
- /**
- * Zero if this operation is ready to start or has already started. A non-zero cookie
- * is returned if the operation has not started and is waiting on
- * {@link android.hardware.biometrics.IBiometricService#onReadyForAuthentication(int)}.
- *
- * @return cookie or 0 if ready/started
- */
- public int isReadyToStart() {
- if (mState == STATE_WAITING_FOR_COOKIE || mState == STATE_WAITING_IN_QUEUE) {
- final int cookie = mClientMonitor.getCookie();
- if (cookie != 0) {
- mState = STATE_WAITING_FOR_COOKIE;
- }
- return cookie;
- }
-
- return 0;
- }
-
- /**
- * Start this operation without waiting for a cookie
- * (i.e. {@link #isReadyToStart() returns zero}
- *
- * @param callback lifecycle callback
- * @return if this operation started
- */
- public boolean start(@NonNull BaseClientMonitor.Callback callback) {
- checkInState("start",
- STATE_WAITING_IN_QUEUE,
- STATE_WAITING_FOR_COOKIE,
- STATE_WAITING_IN_QUEUE_CANCELING);
-
- if (mClientMonitor.getCookie() != 0) {
- throw new IllegalStateException("operation requires cookie");
- }
-
- return doStart(callback);
- }
-
- /**
- * Start this operation after receiving the given cookie.
- *
- * @param callback lifecycle callback
- * @param cookie cookie indicting the operation should begin
- * @return if this operation started
- */
- public boolean startWithCookie(@NonNull BaseClientMonitor.Callback callback, int cookie) {
- checkInState("start",
- STATE_WAITING_IN_QUEUE,
- STATE_WAITING_FOR_COOKIE,
- STATE_WAITING_IN_QUEUE_CANCELING);
-
- if (mClientMonitor.getCookie() != cookie) {
- Slog.e(TAG, "Mismatched cookie for operation: " + this + ", received: " + cookie);
- return false;
- }
-
- return doStart(callback);
- }
-
- private boolean doStart(@NonNull BaseClientMonitor.Callback callback) {
- final BaseClientMonitor.Callback cb = getWrappedCallback(callback);
-
- if (mState == STATE_WAITING_IN_QUEUE_CANCELING) {
- Slog.d(TAG, "Operation marked for cancellation, cancelling now: " + this);
-
- cb.onClientFinished(mClientMonitor, true /* success */);
- if (mClientMonitor instanceof ErrorConsumer) {
- final ErrorConsumer errorConsumer = (ErrorConsumer) mClientMonitor;
- errorConsumer.onError(BiometricConstants.BIOMETRIC_ERROR_CANCELED,
- 0 /* vendorCode */);
- } else {
- Slog.w(TAG, "monitor cancelled but does not implement ErrorConsumer");
- }
-
- return false;
- }
-
- if (isUnstartableHalOperation()) {
- Slog.v(TAG, "unable to start: " + this);
- ((HalClientMonitor<?>) mClientMonitor).unableToStart();
- cb.onClientFinished(mClientMonitor, false /* success */);
- return false;
- }
-
- mState = STATE_STARTED;
- mClientMonitor.start(cb);
-
- Slog.v(TAG, "started: " + this);
- return true;
- }
-
- /**
- * Abort a pending operation.
- *
- * This is similar to cancel but the operation must not have been started. It will
- * immediately abort the operation and notify the client that it has finished unsuccessfully.
- */
- public void abort() {
- checkInState("cannot abort a non-pending operation",
- STATE_WAITING_IN_QUEUE,
- STATE_WAITING_FOR_COOKIE,
- STATE_WAITING_IN_QUEUE_CANCELING);
-
- if (isHalOperation()) {
- ((HalClientMonitor<?>) mClientMonitor).unableToStart();
- }
- getWrappedCallback().onClientFinished(mClientMonitor, false /* success */);
-
- Slog.v(TAG, "Aborted: " + this);
- }
-
- /** Flags this operation as canceled, but does not cancel it until started. */
- public void markCanceling() {
- if (mState == STATE_WAITING_IN_QUEUE && isInterruptable()) {
- mState = STATE_WAITING_IN_QUEUE_CANCELING;
- Slog.v(TAG, "Marked cancelling: " + this);
- }
- }
-
- /**
- * Cancel the operation now.
- *
- * @param handler handler to use for the cancellation watchdog
- * @param callback lifecycle callback (only used if this operation hasn't started, otherwise
- * the callback used from {@link #start(BaseClientMonitor.Callback)} is used)
- */
- public void cancel(@NonNull Handler handler, @NonNull BaseClientMonitor.Callback callback) {
- checkNotInState("cancel", STATE_FINISHED);
-
- final int currentState = mState;
- if (!isInterruptable()) {
- Slog.w(TAG, "Cannot cancel - operation not interruptable: " + this);
- return;
- }
- if (currentState == STATE_STARTED_CANCELING) {
- Slog.w(TAG, "Cannot cancel - already invoked for operation: " + this);
- return;
- }
-
- mState = STATE_STARTED_CANCELING;
- if (currentState == STATE_WAITING_IN_QUEUE
- || currentState == STATE_WAITING_IN_QUEUE_CANCELING
- || currentState == STATE_WAITING_FOR_COOKIE) {
- Slog.d(TAG, "[Cancelling] Current client (without start): " + mClientMonitor);
- ((Interruptable) mClientMonitor).cancelWithoutStarting(getWrappedCallback(callback));
- } else {
- Slog.d(TAG, "[Cancelling] Current client: " + mClientMonitor);
- ((Interruptable) mClientMonitor).cancel();
- }
-
- // forcibly finish this client if the HAL does not acknowledge within the timeout
- handler.postDelayed(mCancelWatchdog, CANCEL_WATCHDOG_DELAY_MS);
- }
-
- @NonNull
- private BaseClientMonitor.Callback getWrappedCallback() {
- return getWrappedCallback(null);
- }
-
- @NonNull
- private BaseClientMonitor.Callback getWrappedCallback(
- @Nullable BaseClientMonitor.Callback callback) {
- final BaseClientMonitor.Callback destroyCallback = new BaseClientMonitor.Callback() {
- @Override
- public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
- boolean success) {
- mClientMonitor.destroy();
- mState = STATE_FINISHED;
- }
- };
- return new BaseClientMonitor.CompositeCallback(destroyCallback, callback, mClientCallback);
- }
-
- /** {@link BaseClientMonitor#getSensorId()}. */
- public int getSensorId() {
- return mClientMonitor.getSensorId();
- }
-
- /** {@link BaseClientMonitor#getProtoEnum()}. */
- public int getProtoEnum() {
- return mClientMonitor.getProtoEnum();
- }
-
- /** {@link BaseClientMonitor#getTargetUserId()}. */
- public int getTargetUserId() {
- return mClientMonitor.getTargetUserId();
- }
-
- /** If the given clientMonitor is the same as the one in the constructor. */
- public boolean isFor(@NonNull BaseClientMonitor clientMonitor) {
- return mClientMonitor == clientMonitor;
- }
-
- /** If this operation is {@link Interruptable}. */
- public boolean isInterruptable() {
- return mClientMonitor instanceof Interruptable;
- }
-
- private boolean isHalOperation() {
- return mClientMonitor instanceof HalClientMonitor<?>;
- }
-
- private boolean isUnstartableHalOperation() {
- if (isHalOperation()) {
- final HalClientMonitor<?> client = (HalClientMonitor<?>) mClientMonitor;
- if (client.getFreshDaemon() == null) {
- return true;
- }
- }
- return false;
- }
-
- /** If this operation is an enrollment. */
- public boolean isEnrollOperation() {
- return mClientMonitor instanceof EnrollClient;
- }
-
- /** If this operation is authentication. */
- public boolean isAuthenticateOperation() {
- return mClientMonitor instanceof AuthenticationClient;
- }
-
- /** If this operation is authentication or detection. */
- public boolean isAuthenticationOrDetectionOperation() {
- final boolean isAuthentication = mClientMonitor instanceof AuthenticationConsumer;
- final boolean isDetection = mClientMonitor instanceof DetectionConsumer;
- return isAuthentication || isDetection;
- }
-
- /** If this operation performs acquisition {@link AcquisitionClient}. */
- public boolean isAcquisitionOperation() {
- return mClientMonitor instanceof AcquisitionClient;
- }
-
- /**
- * If this operation matches the original requestId.
- *
- * By default, monitors are not associated with a request id to retain the original
- * behavior (i.e. if no requestId is explicitly set then assume it matches)
- *
- * @param requestId a unique id {@link BaseClientMonitor#setRequestId(long)}.
- */
- public boolean isMatchingRequestId(long requestId) {
- return !mClientMonitor.hasRequestId()
- || mClientMonitor.getRequestId() == requestId;
- }
-
- /** If the token matches */
- public boolean isMatchingToken(@Nullable IBinder token) {
- return mClientMonitor.getToken() == token;
- }
-
- /** If this operation has started. */
- public boolean isStarted() {
- return mState == STATE_STARTED;
- }
-
- /** If this operation is cancelling but has not yet completed. */
- public boolean isCanceling() {
- return mState == STATE_STARTED_CANCELING;
- }
-
- /** If this operation has finished and completed its lifecycle. */
- public boolean isFinished() {
- return mState == STATE_FINISHED;
- }
-
- /** If {@link #markCanceling()} was called but the operation hasn't been canceled. */
- public boolean isMarkedCanceling() {
- return mState == STATE_WAITING_IN_QUEUE_CANCELING;
- }
-
- /**
- * The monitor passed to the constructor.
- * @deprecated avoid using and move to encapsulate within the operation
- */
- @Deprecated
- public BaseClientMonitor getClientMonitor() {
- return mClientMonitor;
- }
-
- private void checkNotInState(String message, @OperationState int... states) {
- for (int state : states) {
- if (mState == state) {
- throw new IllegalStateException(message + ": illegal state= " + state);
- }
- }
- }
-
- private void checkInState(String message, @OperationState int... states) {
- for (int state : states) {
- if (mState == state) {
- return;
- }
- }
- throw new IllegalStateException(message + ": illegal state= " + mState);
- }
-
- @Override
- public String toString() {
- return mClientMonitor + ", State: " + mState;
- }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/Interruptable.java b/services/core/java/com/android/server/biometrics/sensors/Interruptable.java
index d5093c756415..fab98b6581a3 100644
--- a/services/core/java/com/android/server/biometrics/sensors/Interruptable.java
+++ b/services/core/java/com/android/server/biometrics/sensors/Interruptable.java
@@ -32,11 +32,6 @@ public interface Interruptable {
* {@link BaseClientMonitor#start(BaseClientMonitor.Callback)} was invoked. This usually happens
* if the client is still waiting in the pending queue and got notified that a subsequent
* operation is preempting it.
- *
- * This method must invoke
- * {@link BaseClientMonitor.Callback#onClientFinished(BaseClientMonitor, boolean)} on the
- * given callback (with success).
- *
* @param callback invoked when the operation is completed.
*/
void cancelWithoutStarting(@NonNull BaseClientMonitor.Callback callback);
diff --git a/services/core/java/com/android/server/biometrics/sensors/LockoutResetDispatcher.java b/services/core/java/com/android/server/biometrics/sensors/LockoutResetDispatcher.java
index f4997d4abe24..92218b1023c4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/LockoutResetDispatcher.java
+++ b/services/core/java/com/android/server/biometrics/sensors/LockoutResetDispatcher.java
@@ -25,7 +25,11 @@ import android.os.PowerManager;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
/**
* Allows clients (such as keyguard) to register for notifications on when biometric lockout
@@ -37,7 +41,8 @@ public class LockoutResetDispatcher implements IBinder.DeathRecipient {
private static final String TAG = "LockoutResetTracker";
private final Context mContext;
- private final ArrayList<ClientCallback> mClientCallbacks;
+ @VisibleForTesting
+ final List<ClientCallback> mClientCallbacks = new ArrayList<>();
private static class ClientCallback {
private static final long WAKELOCK_TIMEOUT_MS = 2000;
@@ -81,7 +86,6 @@ public class LockoutResetDispatcher implements IBinder.DeathRecipient {
public LockoutResetDispatcher(Context context) {
mContext = context;
- mClientCallbacks = new ArrayList<>();
}
public void addCallback(IBiometricServiceLockoutResetCallback callback, String opPackageName) {
@@ -106,11 +110,13 @@ public class LockoutResetDispatcher implements IBinder.DeathRecipient {
@Override
public void binderDied(IBinder who) {
Slog.e(TAG, "Callback binder died: " + who);
- for (ClientCallback callback : mClientCallbacks) {
+ final Iterator<ClientCallback> iterator = mClientCallbacks.iterator();
+ while (iterator.hasNext()) {
+ final ClientCallback callback = iterator.next();
if (callback.mCallback.asBinder().equals(who)) {
Slog.e(TAG, "Removing dead callback for: " + callback.mOpPackageName);
callback.releaseWakelock();
- mClientCallbacks.remove(callback);
+ iterator.remove();
}
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java
index 19eaa178c7c9..b056bf897b5c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java
@@ -16,13 +16,10 @@
package com.android.server.biometrics.sensors;
-import static com.android.server.biometrics.sensors.BiometricSchedulerOperation.STATE_STARTED;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.IBiometricService;
-import android.os.Handler;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.Slog;
@@ -71,8 +68,9 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
return;
}
- Slog.d(getTag(), "[Client finished] " + clientMonitor + ", success: " + success);
- if (mCurrentOperation != null && mCurrentOperation.isFor(mOwner)) {
+ Slog.d(getTag(), "[Client finished] "
+ + clientMonitor + ", success: " + success);
+ if (mCurrentOperation != null && mCurrentOperation.mClientMonitor == mOwner) {
mCurrentOperation = null;
startNextOperationIfIdle();
} else {
@@ -85,31 +83,26 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
}
@VisibleForTesting
- UserAwareBiometricScheduler(@NonNull String tag,
- @NonNull Handler handler,
- @SensorType int sensorType,
+ UserAwareBiometricScheduler(@NonNull String tag, @SensorType int sensorType,
@Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
@NonNull IBiometricService biometricService,
@NonNull CurrentUserRetriever currentUserRetriever,
@NonNull UserSwitchCallback userSwitchCallback,
@NonNull CoexCoordinator coexCoordinator) {
- super(tag, handler, sensorType, gestureAvailabilityDispatcher, biometricService,
+ super(tag, sensorType, gestureAvailabilityDispatcher, biometricService,
LOG_NUM_RECENT_OPERATIONS, coexCoordinator);
mCurrentUserRetriever = currentUserRetriever;
mUserSwitchCallback = userSwitchCallback;
}
- public UserAwareBiometricScheduler(@NonNull String tag,
- @NonNull Handler handler,
- @SensorType int sensorType,
+ public UserAwareBiometricScheduler(@NonNull String tag, @SensorType int sensorType,
@Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
@NonNull CurrentUserRetriever currentUserRetriever,
@NonNull UserSwitchCallback userSwitchCallback) {
- this(tag, handler, sensorType, gestureAvailabilityDispatcher,
- IBiometricService.Stub.asInterface(
- ServiceManager.getService(Context.BIOMETRIC_SERVICE)),
- currentUserRetriever, userSwitchCallback, CoexCoordinator.getInstance());
+ this(tag, sensorType, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface(
+ ServiceManager.getService(Context.BIOMETRIC_SERVICE)), currentUserRetriever,
+ userSwitchCallback, CoexCoordinator.getInstance());
}
@Override
@@ -129,7 +122,7 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
}
final int currentUserId = mCurrentUserRetriever.getCurrentUserId();
- final int nextUserId = mPendingOperations.getFirst().getTargetUserId();
+ final int nextUserId = mPendingOperations.getFirst().mClientMonitor.getTargetUserId();
if (nextUserId == currentUserId) {
super.startNextOperationIfIdle();
@@ -140,8 +133,8 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
new ClientFinishedCallback(startClient);
Slog.d(getTag(), "[Starting User] " + startClient);
- mCurrentOperation = new BiometricSchedulerOperation(
- startClient, finishedCallback, STATE_STARTED);
+ mCurrentOperation = new Operation(
+ startClient, finishedCallback, Operation.STATE_STARTED);
startClient.start(finishedCallback);
} else {
if (mStopUserClient != null) {
@@ -154,8 +147,8 @@ public class UserAwareBiometricScheduler extends BiometricScheduler {
Slog.d(getTag(), "[Stopping User] current: " + currentUserId
+ ", next: " + nextUserId + ". " + mStopUserClient);
- mCurrentOperation = new BiometricSchedulerOperation(
- mStopUserClient, finishedCallback, STATE_STARTED);
+ mCurrentOperation = new Operation(
+ mStopUserClient, finishedCallback, Operation.STATE_STARTED);
mStopUserClient.start(finishedCallback);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 039b08e805c1..675ee545a14f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -213,7 +213,7 @@ public class FaceService extends SystemService {
}
@Override // Binder call
- public long enroll(int userId, final IBinder token, final byte[] hardwareAuthToken,
+ public void enroll(int userId, final IBinder token, final byte[] hardwareAuthToken,
final IFaceServiceReceiver receiver, final String opPackageName,
final int[] disabledFeatures, Surface previewSurface, boolean debugConsent) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
@@ -221,24 +221,23 @@ public class FaceService extends SystemService {
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for enroll");
- return -1;
+ return;
}
- return provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
+ provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
receiver, opPackageName, disabledFeatures, previewSurface, debugConsent);
}
@Override // Binder call
- public long enrollRemotely(int userId, final IBinder token, final byte[] hardwareAuthToken,
+ public void enrollRemotely(int userId, final IBinder token, final byte[] hardwareAuthToken,
final IFaceServiceReceiver receiver, final String opPackageName,
final int[] disabledFeatures) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
// TODO(b/145027036): Implement this.
- return -1;
}
@Override // Binder call
- public void cancelEnrollment(final IBinder token, long requestId) {
+ public void cancelEnrollment(final IBinder token) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
@@ -247,7 +246,7 @@ public class FaceService extends SystemService {
return;
}
- provider.second.cancelEnrollment(provider.first, token, requestId);
+ provider.second.cancelEnrollment(provider.first, token);
}
@Override // Binder call
@@ -625,7 +624,7 @@ public class FaceService extends SystemService {
private void addHidlProviders(@NonNull List<FaceSensorPropertiesInternal> hidlSensors) {
for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) {
mServiceProviders.add(
- Face10.newInstance(getContext(), hidlSensor, mLockoutResetDispatcher));
+ new Face10(getContext(), hidlSensor, mLockoutResetDispatcher));
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
index 77e431c81192..e099ba372b05 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -94,12 +94,12 @@ public interface ServiceProvider {
void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token,
@NonNull String opPackageName, long challenge);
- long scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
+ void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName,
@NonNull int[] disabledFeatures, @Nullable Surface previewSurface,
boolean debugConsent);
- void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId);
+ void cancelEnrollment(int sensorId, @NonNull IBinder token);
long scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId,
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index aae4fbe9b0d7..a806277ed45e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -82,14 +82,13 @@ public class FaceEnrollClient extends EnrollClient<ISession> {
FaceEnrollClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull byte[] hardwareAuthToken, @NonNull String opPackageName, long requestId,
+ @NonNull byte[] hardwareAuthToken, @NonNull String opPackageName,
@NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
@Nullable Surface previewSurface, int sensorId, int maxTemplatesPerUser,
boolean debugConsent) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, opPackageName, utils,
timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
false /* shouldVibrate */);
- setRequestId(requestId);
mEnrollIgnoreList = getContext().getResources()
.getIntArray(R.array.config_face_acquire_enroll_ignorelist);
mEnrollIgnoreListVendor = getContext().getResources()
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index ae507abea537..4bae7756abe0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -327,18 +327,17 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
@Override
- public long scheduleEnroll(int sensorId, @NonNull IBinder token,
+ public void scheduleEnroll(int sensorId, @NonNull IBinder token,
@NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
@NonNull String opPackageName, @NonNull int[] disabledFeatures,
@Nullable Surface previewSurface, boolean debugConsent) {
- final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
final int maxTemplatesPerUser = mSensors.get(
sensorId).getSensorProperties().maxEnrollmentsPerUser;
final FaceEnrollClient client = new FaceEnrollClient(mContext,
mSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
- opPackageName, id, FaceUtils.getInstance(sensorId), disabledFeatures,
+ opPackageName, FaceUtils.getInstance(sensorId), disabledFeatures,
ENROLL_TIMEOUT_SEC, previewSurface, sensorId, maxTemplatesPerUser,
debugConsent);
scheduleForSensor(sensorId, client, new BaseClientMonitor.Callback() {
@@ -352,13 +351,11 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
});
});
- return id;
}
@Override
- public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) {
- mHandler.post(() ->
- mSensors.get(sensorId).getScheduler().cancelEnrollment(token, requestId));
+ public void cancelEnrollment(int sensorId, @NonNull IBinder token) {
+ mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelEnrollment(token));
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 39270430c21d..206b8f0779e8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -494,7 +494,7 @@ public class Sensor {
mToken = new Binder();
mHandler = handler;
mSensorProperties = sensorProperties;
- mScheduler = new UserAwareBiometricScheduler(tag, mHandler,
+ mScheduler = new UserAwareBiometricScheduler(tag,
BiometricScheduler.SENSOR_TYPE_FACE, null /* gestureAvailabilityDispatcher */,
() -> mCurrentSession != null ? mCurrentSession.mUserId : UserHandle.USER_NULL,
new UserAwareBiometricScheduler.UserSwitchCallback() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 493c0a05e379..f4dcbbba21d7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -333,13 +333,12 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
Face10(@NonNull Context context,
@NonNull FaceSensorPropertiesInternal sensorProps,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
- @NonNull Handler handler,
@NonNull BiometricScheduler scheduler) {
mSensorProperties = sensorProps;
mContext = context;
mSensorId = sensorProps.sensorId;
mScheduler = scheduler;
- mHandler = handler;
+ mHandler = new Handler(Looper.getMainLooper());
mUsageStats = new UsageStats(context);
mAuthenticatorIds = new HashMap<>();
mLazyDaemon = Face10.this::getDaemon;
@@ -358,12 +357,10 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
}
}
- public static Face10 newInstance(@NonNull Context context,
- @NonNull FaceSensorPropertiesInternal sensorProps,
+ public Face10(@NonNull Context context, @NonNull FaceSensorPropertiesInternal sensorProps,
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
- final Handler handler = new Handler(Looper.getMainLooper());
- return new Face10(context, sensorProps, lockoutResetDispatcher, handler,
- new BiometricScheduler(TAG, handler, BiometricScheduler.SENSOR_TYPE_FACE,
+ this(context, sensorProps, lockoutResetDispatcher,
+ new BiometricScheduler(TAG, BiometricScheduler.SENSOR_TYPE_FACE,
null /* gestureAvailabilityTracker */));
}
@@ -576,11 +573,10 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
}
@Override
- public long scheduleEnroll(int sensorId, @NonNull IBinder token,
+ public void scheduleEnroll(int sensorId, @NonNull IBinder token,
@NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
@NonNull String opPackageName, @NonNull int[] disabledFeatures,
@Nullable Surface previewSurface, boolean debugConsent) {
- final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
@@ -588,7 +584,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final FaceEnrollClient client = new FaceEnrollClient(mContext, mLazyDaemon, token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
- opPackageName, id, FaceUtils.getLegacyInstance(mSensorId), disabledFeatures,
+ opPackageName, FaceUtils.getLegacyInstance(mSensorId), disabledFeatures,
ENROLL_TIMEOUT_SEC, previewSurface, mSensorId);
mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@@ -602,12 +598,13 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
}
});
});
- return id;
}
@Override
- public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) {
- mHandler.post(() -> mScheduler.cancelEnrollment(token, requestId));
+ public void cancelEnrollment(int sensorId, @NonNull IBinder token) {
+ mHandler.post(() -> {
+ mScheduler.cancelEnrollment(token);
+ });
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
index 31e5c86103fb..80828cced4e8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
@@ -53,13 +53,12 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
FaceEnrollClient(@NonNull Context context, @NonNull LazyDaemon<IBiometricsFace> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull byte[] hardwareAuthToken, @NonNull String owner, long requestId,
+ @NonNull byte[] hardwareAuthToken, @NonNull String owner,
@NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
@Nullable Surface previewSurface, int sensorId) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
false /* shouldVibrate */);
- setRequestId(requestId);
mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
mEnrollIgnoreList = getContext().getResources()
.getIntArray(R.array.config_face_acquire_enroll_ignorelist);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 6366e19ef191..3e70ee52ff1b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -249,7 +249,7 @@ public class FingerprintService extends SystemService {
}
@Override // Binder call
- public long enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken,
+ public void enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken,
final int userId, final IFingerprintServiceReceiver receiver,
final String opPackageName, @FingerprintManager.EnrollReason int enrollReason) {
Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);
@@ -257,15 +257,15 @@ public class FingerprintService extends SystemService {
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for enroll");
- return -1;
+ return;
}
- return provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
+ provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
receiver, opPackageName, enrollReason);
}
@Override // Binder call
- public void cancelEnrollment(final IBinder token, long requestId) {
+ public void cancelEnrollment(final IBinder token) {
Utils.checkPermission(getContext(), MANAGE_FINGERPRINT);
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
@@ -274,7 +274,7 @@ public class FingerprintService extends SystemService {
return;
}
- provider.second.cancelEnrollment(provider.first, token, requestId);
+ provider.second.cancelEnrollment(provider.first, token);
}
@SuppressWarnings("deprecation")
@@ -818,7 +818,7 @@ public class FingerprintService extends SystemService {
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
} else {
fingerprint21 = Fingerprint21.newInstance(getContext(),
- mFingerprintStateCallback, hidlSensor, mHandler,
+ mFingerprintStateCallback, hidlSensor,
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
}
mServiceProviders.add(fingerprint21);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index 535705c63cab..1772f814dd10 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -88,11 +88,11 @@ public interface ServiceProvider {
/**
* Schedules fingerprint enrollment.
*/
- long scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
+ void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
int userId, @NonNull IFingerprintServiceReceiver receiver,
@NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason);
- void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId);
+ void cancelEnrollment(int sensorId, @NonNull IBinder token);
long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 67507ccbbbfe..ccb34aad3198 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -57,7 +57,7 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
private boolean mIsPointerDown;
FingerprintEnrollClient(@NonNull Context context,
- @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, long requestId,
+ @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String owner,
@NonNull BiometricUtils<Fingerprint> utils, int sensorId,
@@ -69,7 +69,6 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
0 /* timeoutSec */, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
!sensorProps.isAnyUdfpsType() /* shouldVibrate */);
- setRequestId(requestId);
mSensorProps = sensorProps;
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
mMaxTemplatesPerUser = maxTemplatesPerUser;
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 eb16c763dea6..734b1737dfbc 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
@@ -347,16 +347,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
}
@Override
- public long scheduleEnroll(int sensorId, @NonNull IBinder token,
+ public void scheduleEnroll(int sensorId, @NonNull IBinder token,
@NonNull byte[] hardwareAuthToken, int userId,
@NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
@FingerprintManager.EnrollReason int enrollReason) {
- final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties()
.maxEnrollmentsPerUser;
final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext,
- mSensors.get(sensorId).getLazySession(), token, id,
+ mSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
mSensors.get(sensorId).getSensorProperties(),
@@ -379,13 +378,11 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
}
});
});
- return id;
}
@Override
- public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) {
- mHandler.post(() ->
- mSensors.get(sensorId).getScheduler().cancelEnrollment(token, requestId));
+ public void cancelEnrollment(int sensorId, @NonNull IBinder token) {
+ mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelEnrollment(token));
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index 256761a61a72..59e4b582ca84 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -449,7 +449,7 @@ class Sensor {
mHandler = handler;
mSensorProperties = sensorProperties;
mLockoutCache = new LockoutCache();
- mScheduler = new UserAwareBiometricScheduler(tag, handler,
+ mScheduler = new UserAwareBiometricScheduler(tag,
BiometricScheduler.sensorTypeFromFingerprintProperties(mSensorProperties),
gestureAvailabilityDispatcher,
() -> mCurrentSession != null ? mCurrentSession.mUserId : UserHandle.USER_NULL,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index d352cda609e3..5f2f4cf6ef3c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -42,6 +42,7 @@ import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Handler;
import android.os.IBinder;
import android.os.IHwBinder;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
@@ -319,8 +320,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
Fingerprint21(@NonNull Context context,
@NonNull FingerprintStateCallback fingerprintStateCallback,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
- @NonNull BiometricScheduler scheduler,
- @NonNull Handler handler,
+ @NonNull BiometricScheduler scheduler, @NonNull Handler handler,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull HalResultController controller) {
mContext = context;
@@ -356,15 +356,16 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
public static Fingerprint21 newInstance(@NonNull Context context,
@NonNull FingerprintStateCallback fingerprintStateCallback,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
- @NonNull Handler handler,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
+ final Handler handler = new Handler(Looper.getMainLooper());
final BiometricScheduler scheduler =
- new BiometricScheduler(TAG, handler,
+ new BiometricScheduler(TAG,
BiometricScheduler.sensorTypeFromFingerprintProperties(sensorProps),
gestureAvailabilityDispatcher);
final HalResultController controller = new HalResultController(sensorProps.sensorId,
- context, handler, scheduler);
+ context, handler,
+ scheduler);
return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler,
lockoutResetDispatcher, controller);
}
@@ -557,20 +558,18 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
}
@Override
- public long scheduleEnroll(int sensorId, @NonNull IBinder token,
+ public void scheduleEnroll(int sensorId, @NonNull IBinder token,
@NonNull byte[] hardwareAuthToken, int userId,
@NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName,
@FingerprintManager.EnrollReason int enrollReason) {
- final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext,
- mLazyDaemon, token, id, new ClientMonitorCallbackConverter(receiver),
- userId, hardwareAuthToken, opPackageName,
- FingerprintUtils.getLegacyInstance(mSensorId), ENROLL_TIMEOUT_SEC,
- mSensorProperties.sensorId, mUdfpsOverlayController, mSidefpsController,
- enrollReason);
+ mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId,
+ hardwareAuthToken, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId),
+ ENROLL_TIMEOUT_SEC, mSensorProperties.sensorId, mUdfpsOverlayController,
+ mSidefpsController, enrollReason);
mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() {
@Override
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
@@ -589,12 +588,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
}
});
});
- return id;
}
@Override
- public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) {
- mHandler.post(() -> mScheduler.cancelEnrollment(token, requestId));
+ public void cancelEnrollment(int sensorId, @NonNull IBinder token) {
+ mHandler.post(() -> {
+ mScheduler.cancelEnrollment(token);
+ });
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index 20dab5552df9..dd68b4d37e2a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -26,6 +26,7 @@ import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.FingerprintStateListener;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Handler;
import android.os.IBinder;
@@ -134,17 +135,43 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
@NonNull private final RestartAuthRunnable mRestartAuthRunnable;
private static class TestableBiometricScheduler extends BiometricScheduler {
+ @NonNull private final TestableInternalCallback mInternalCallback;
@NonNull private Fingerprint21UdfpsMock mFingerprint21;
- TestableBiometricScheduler(@NonNull String tag, @NonNull Handler handler,
+ TestableBiometricScheduler(@NonNull String tag,
@Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
- super(tag, handler, BiometricScheduler.SENSOR_TYPE_FP_OTHER,
+ super(tag, BiometricScheduler.SENSOR_TYPE_FP_OTHER,
gestureAvailabilityDispatcher);
+ mInternalCallback = new TestableInternalCallback();
+ }
+
+ class TestableInternalCallback extends InternalCallback {
+ @Override
+ public void onClientStarted(BaseClientMonitor clientMonitor) {
+ super.onClientStarted(clientMonitor);
+ Slog.d(TAG, "Client started: " + clientMonitor);
+ mFingerprint21.setDebugMessage("Started: " + clientMonitor);
+ }
+
+ @Override
+ public void onClientFinished(BaseClientMonitor clientMonitor, boolean success) {
+ super.onClientFinished(clientMonitor, success);
+ Slog.d(TAG, "Client finished: " + clientMonitor);
+ mFingerprint21.setDebugMessage("Finished: " + clientMonitor);
+ }
}
void init(@NonNull Fingerprint21UdfpsMock fingerprint21) {
mFingerprint21 = fingerprint21;
}
+
+ /**
+ * Expose the internal finish callback so it can be used for testing
+ */
+ @Override
+ @NonNull protected InternalCallback getInternalCallback() {
+ return mInternalCallback;
+ }
}
/**
@@ -253,7 +280,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
final Handler handler = new Handler(Looper.getMainLooper());
final TestableBiometricScheduler scheduler =
- new TestableBiometricScheduler(TAG, handler, gestureAvailabilityDispatcher);
+ new TestableBiometricScheduler(TAG, gestureAvailabilityDispatcher);
final MockHalResultController controller =
new MockHalResultController(sensorProps.sensorId, context, handler, scheduler);
return new Fingerprint21UdfpsMock(context, fingerprintStateCallback, sensorProps, scheduler,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index cc50bdfb59ae..1ebf44ca707f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -55,7 +55,7 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
FingerprintEnrollClient(@NonNull Context context,
@NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
- long requestId, @NonNull ClientMonitorCallbackConverter listener, int userId,
+ @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String owner,
@NonNull BiometricUtils<Fingerprint> utils, int timeoutSec, int sensorId,
@Nullable IUdfpsOverlayController udfpsOverlayController,
@@ -64,7 +64,6 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
timeoutSec, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
true /* shouldVibrate */);
- setRequestId(requestId);
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
mEnrollReason = enrollReason;
diff --git a/services/core/java/com/android/server/communal/CommunalManagerService.java b/services/core/java/com/android/server/communal/CommunalManagerService.java
index 2a6456dfc602..600313bbad64 100644
--- a/services/core/java/com/android/server/communal/CommunalManagerService.java
+++ b/services/core/java/com/android/server/communal/CommunalManagerService.java
@@ -19,10 +19,7 @@ package com.android.server.communal;
import android.Manifest;
import android.annotation.RequiresPermission;
import android.app.communal.ICommunalManager;
-import android.app.communal.ICommunalModeListener;
import android.content.Context;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.SystemService;
@@ -36,9 +33,6 @@ public final class CommunalManagerService extends SystemService {
private final Context mContext;
private final AtomicBoolean mCommunalViewIsShowing = new AtomicBoolean(false);
private final BinderService mBinderService;
- private final RemoteCallbackList<ICommunalModeListener> mListeners =
- new RemoteCallbackList<>();
-
public CommunalManagerService(Context context) {
super(context);
@@ -56,27 +50,6 @@ public final class CommunalManagerService extends SystemService {
publishBinderService(Context.COMMUNAL_SERVICE, mBinderService);
}
- private void dispatchCommunalMode(boolean isShowing) {
- synchronized (mListeners) {
- int i = mListeners.beginBroadcast();
- while (i > 0) {
- i--;
- try {
- mListeners.getBroadcastItem(i).onCommunalModeChanged(isShowing);
- } catch (RemoteException e) {
- // Handled by the RemoteCallbackList.
- }
- }
- mListeners.finishBroadcast();
- }
- }
-
- private void enforceReadPermission() {
- mContext.enforceCallingPermission(Manifest.permission.READ_COMMUNAL_STATE,
- Manifest.permission.READ_COMMUNAL_STATE
- + "permission required to read communal state.");
- }
-
private final class BinderService extends ICommunalManager.Stub {
/**
* Sets whether or not we are in communal mode.
@@ -91,39 +64,6 @@ public final class CommunalManagerService extends SystemService {
return;
}
mCommunalViewIsShowing.set(isShowing);
- dispatchCommunalMode(isShowing);
- }
-
- /**
- * Checks whether or not we are in communal mode.
- */
- @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
- @Override
- public boolean isCommunalMode() {
- enforceReadPermission();
- return mCommunalViewIsShowing.get();
- }
-
- /**
- * Adds a callback to execute when communal state changes.
- */
- @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
- public void addCommunalModeListener(ICommunalModeListener listener) {
- enforceReadPermission();
- synchronized (mListeners) {
- mListeners.register(listener);
- }
- }
-
- /**
- * Removes an added callback that execute when communal state changes.
- */
- @RequiresPermission(Manifest.permission.READ_COMMUNAL_STATE)
- public void removeCommunalModeListener(ICommunalModeListener listener) {
- enforceReadPermission();
- synchronized (mListeners) {
- mListeners.unregister(listener);
- }
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 6a716cbc2816..066c263fa83b 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1223,8 +1223,11 @@ public class Vpn {
for (RouteInfo route : mConfig.routes) {
lp.addRoute(route);
InetAddress address = route.getDestination().getAddress();
- allowIPv4 |= address instanceof Inet4Address;
- allowIPv6 |= address instanceof Inet6Address;
+
+ if (route.getType() == RouteInfo.RTN_UNICAST) {
+ allowIPv4 |= address instanceof Inet4Address;
+ allowIPv6 |= address instanceof Inet6Address;
+ }
}
}
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index f84b68e7c556..9b0b7829005d 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -35,6 +35,7 @@ import android.os.HandlerThread;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
import android.util.Log;
import android.util.Pair;
@@ -435,7 +436,7 @@ public abstract class IContextHubWrapper {
public void onHostEndpointConnected(HostEndpointInfo info) {
try {
mHub.onHostEndpointConnected(info);
- } catch (RemoteException e) {
+ } catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "RemoteException in onHostEndpointConnected");
}
}
@@ -444,7 +445,7 @@ public abstract class IContextHubWrapper {
public void onHostEndpointDisconnected(short hostEndpointId) {
try {
mHub.onHostEndpointDisconnected((char) hostEndpointId);
- } catch (RemoteException e) {
+ } catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "RemoteException in onHostEndpointDisconnected");
}
}
@@ -457,7 +458,7 @@ public abstract class IContextHubWrapper {
mHub.sendMessageToHub(contextHubId,
ContextHubServiceUtil.createAidlContextHubMessage(hostEndpointId, message));
return ContextHubTransaction.RESULT_SUCCESS;
- } catch (RemoteException e) {
+ } catch (RemoteException | ServiceSpecificException e) {
return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
}
}
@@ -470,7 +471,7 @@ public abstract class IContextHubWrapper {
try {
mHub.loadNanoapp(contextHubId, aidlNanoAppBinary, transactionId);
return ContextHubTransaction.RESULT_SUCCESS;
- } catch (RemoteException e) {
+ } catch (RemoteException | ServiceSpecificException e) {
return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
}
}
@@ -481,7 +482,7 @@ public abstract class IContextHubWrapper {
try {
mHub.unloadNanoapp(contextHubId, nanoappId, transactionId);
return ContextHubTransaction.RESULT_SUCCESS;
- } catch (RemoteException e) {
+ } catch (RemoteException | ServiceSpecificException e) {
return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
}
}
@@ -492,7 +493,7 @@ public abstract class IContextHubWrapper {
try {
mHub.enableNanoapp(contextHubId, nanoappId, transactionId);
return ContextHubTransaction.RESULT_SUCCESS;
- } catch (RemoteException e) {
+ } catch (RemoteException | ServiceSpecificException e) {
return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
}
}
@@ -503,7 +504,7 @@ public abstract class IContextHubWrapper {
try {
mHub.disableNanoapp(contextHubId, nanoappId, transactionId);
return ContextHubTransaction.RESULT_SUCCESS;
- } catch (RemoteException e) {
+ } catch (RemoteException | ServiceSpecificException e) {
return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
}
}
@@ -513,21 +514,25 @@ public abstract class IContextHubWrapper {
try {
mHub.queryNanoapps(contextHubId);
return ContextHubTransaction.RESULT_SUCCESS;
- } catch (RemoteException e) {
+ } catch (RemoteException | ServiceSpecificException e) {
return ContextHubTransaction.RESULT_FAILED_UNKNOWN;
}
}
public void registerCallback(int contextHubId, ICallback callback) throws RemoteException {
mAidlCallbackMap.put(contextHubId, new ContextHubAidlCallback(contextHubId, callback));
- mHub.registerCallback(contextHubId, mAidlCallbackMap.get(contextHubId));
+ try {
+ mHub.registerCallback(contextHubId, mAidlCallbackMap.get(contextHubId));
+ } catch (RemoteException | ServiceSpecificException e) {
+ Log.e(TAG, "Exception while registering callback: " + e.getMessage());
+ }
}
private void onSettingChanged(byte setting, boolean enabled) {
try {
mHub.onSettingChanged(setting, enabled);
- } catch (RemoteException e) {
- Log.e(TAG, "RemoteException while sending setting update");
+ } catch (RemoteException | ServiceSpecificException e) {
+ Log.e(TAG, "Exception while sending setting update: " + e.getMessage());
}
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 4822d6a62ac7..96391ac62530 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -52,7 +52,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
-import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
@@ -643,22 +642,24 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
}
private void pushQueueUpdate() {
- ParceledListSlice<QueueItem> parcelableQueue;
+ ArrayList<QueueItem> toSend;
synchronized (mLock) {
if (mDestroyed) {
return;
}
- if (mQueue == null) {
- parcelableQueue = null;
- } else {
- parcelableQueue = new ParceledListSlice<>(mQueue);
- // Limit the size of initial Parcel to prevent binder buffer overflow
- // as onQueueChanged is an async binder call.
- parcelableQueue.setInlineCountLimit(1);
+ toSend = new ArrayList<>();
+ if (mQueue != null) {
+ toSend.ensureCapacity(mQueue.size());
+ toSend.addAll(mQueue);
}
}
Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
+ ParceledListSlice<QueueItem> parcelableQueue = new ParceledListSlice<>(toSend);
+ // Limit the size of initial Parcel to prevent binder buffer overflow
+ // as onQueueChanged is an async binder call.
+ parcelableQueue.setInlineCountLimit(1);
+
try {
holder.mCallback.onQueueChanged(parcelableQueue);
} catch (DeadObjectException e) {
diff --git a/services/core/java/com/android/server/media/OWNERS b/services/core/java/com/android/server/media/OWNERS
index 2e2d812c058e..8097f4e9b329 100644
--- a/services/core/java/com/android/server/media/OWNERS
+++ b/services/core/java/com/android/server/media/OWNERS
@@ -1,8 +1,6 @@
+# Bug component: 137631
elaurent@google.com
-hdmoon@google.com
-insun@google.com
-jaewan@google.com
-jinpark@google.com
-klhyun@google.com
lajos@google.com
-sungsoo@google.com
+
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 65c5b88d846a..5660951a9efa 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -130,7 +130,7 @@ import static com.android.internal.util.XmlUtils.writeIntArrayXml;
import static com.android.internal.util.XmlUtils.writeIntAttribute;
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
-import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
+import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
diff --git a/services/core/java/com/android/server/notification/CountdownConditionProvider.java b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
index 471c9b97200f..4b70e2e31888 100644
--- a/services/core/java/com/android/server/notification/CountdownConditionProvider.java
+++ b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
@@ -94,7 +94,8 @@ public class CountdownConditionProvider extends SystemConditionProviderService {
@Override
public void onConnected() {
if (DEBUG) Slog.d(TAG, "onConnected");
- mContext.registerReceiver(mReceiver, new IntentFilter(ACTION));
+ mContext.registerReceiver(mReceiver, new IntentFilter(ACTION),
+ Context.RECEIVER_EXPORTED_UNAUDITED);
mConnected = true;
}
diff --git a/services/core/java/com/android/server/notification/EventConditionProvider.java b/services/core/java/com/android/server/notification/EventConditionProvider.java
index 4be4f0a1e7f0..4fe7a27c64c6 100644
--- a/services/core/java/com/android/server/notification/EventConditionProvider.java
+++ b/services/core/java/com/android/server/notification/EventConditionProvider.java
@@ -306,7 +306,8 @@ public class EventConditionProvider extends SystemConditionProviderService {
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(ACTION_EVALUATE);
- registerReceiver(mReceiver, filter);
+ registerReceiver(mReceiver, filter,
+ Context.RECEIVER_EXPORTED_UNAUDITED);
} else {
unregisterReceiver(mReceiver);
}
diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
index 8a3329913142..a9b2570a3dda 100644
--- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
+++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
@@ -100,7 +100,8 @@ public class NotificationHistoryDatabase {
IntentFilter deletionFilter = new IntentFilter(ACTION_HISTORY_DELETION);
deletionFilter.addDataScheme(SCHEME_DELETION);
- mContext.registerReceiver(mFileCleanupReceiver, deletionFilter);
+ mContext.registerReceiver(mFileCleanupReceiver, deletionFilter,
+ Context.RECEIVER_EXPORTED_UNAUDITED);
}
public void init() {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
index 0528b95d1a6e..c548e7edc3cf 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerInternal.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
@@ -36,4 +36,10 @@ public interface NotificationManagerInternal {
void removeForegroundServiceFlagFromNotification(String pkg, int notificationId, int userId);
void onConversationRemoved(String pkg, int uid, Set<String> shortcuts);
+
+ /** Get the number of notification channels for a given package */
+ int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted);
+
+ /** Does the specified package/uid have permission to post notifications? */
+ boolean areNotificationsEnabledForPackage(String pkg, int uid);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 755c50df1bef..399ae5347e6e 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -133,6 +133,7 @@ import android.annotation.WorkerThread;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerInternal.ServiceNotificationPolicy;
+import android.app.ActivityTaskManager;
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
@@ -296,6 +297,7 @@ import com.android.server.notification.toast.TextToastRecord;
import com.android.server.notification.toast.ToastRecord;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.utils.quota.MultiRateLimiter;
@@ -480,6 +482,7 @@ public class NotificationManagerService extends SystemService {
private IPackageManager mPackageManager;
private PackageManager mPackageManagerClient;
private PackageManagerInternal mPackageManagerInternal;
+ private PermissionPolicyInternal mPermissionPolicyInternal;
AudioManager mAudioManager;
AudioManagerInternal mAudioManagerInternal;
// Can be null for wear
@@ -2106,6 +2109,7 @@ public class NotificationManagerService extends SystemService {
mPackageManager = packageManager;
mPackageManagerClient = packageManagerClient;
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+ mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
mAppOps = appOps;
mAppOpsService = iAppOps;
try {
@@ -2330,7 +2334,8 @@ public class NotificationManagerService extends SystemService {
IntentFilter timeoutFilter = new IntentFilter(ACTION_NOTIFICATION_TIMEOUT);
timeoutFilter.addDataScheme(SCHEME_TIMEOUT);
- getContext().registerReceiver(mNotificationTimeoutReceiver, timeoutFilter);
+ getContext().registerReceiver(mNotificationTimeoutReceiver, timeoutFilter,
+ Context.RECEIVER_EXPORTED_UNAUDITED);
IntentFilter settingsRestoredFilter = new IntentFilter(Intent.ACTION_SETTING_RESTORED);
getContext().registerReceiver(mRestoreReceiver, settingsRestoredFilter);
@@ -2766,7 +2771,7 @@ public class NotificationManagerService extends SystemService {
}
}
- private void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
+ void createNotificationChannelGroup(String pkg, int uid, NotificationChannelGroup group,
boolean fromApp, boolean fromListener) {
Objects.requireNonNull(group);
Objects.requireNonNull(pkg);
@@ -3674,9 +3679,19 @@ public class NotificationManagerService extends SystemService {
private void createNotificationChannelsImpl(String pkg, int uid,
ParceledListSlice channelsList) {
+ createNotificationChannelsImpl(pkg, uid, channelsList,
+ ActivityTaskManager.INVALID_TASK_ID);
+ }
+
+ private void createNotificationChannelsImpl(String pkg, int uid,
+ ParceledListSlice channelsList, int startingTaskId) {
List<NotificationChannel> channels = channelsList.getList();
final int channelsSize = channels.size();
+ ParceledListSlice<NotificationChannel> oldChannels =
+ mPreferencesHelper.getNotificationChannels(pkg, uid, true);
+ final boolean hadChannel = oldChannels != null && !oldChannels.getList().isEmpty();
boolean needsPolicyFileChange = false;
+ boolean hasRequestedNotificationPermission = false;
for (int i = 0; i < channelsSize; i++) {
final NotificationChannel channel = channels.get(i);
Objects.requireNonNull(channel, "channel in list is null");
@@ -3690,6 +3705,19 @@ public class NotificationManagerService extends SystemService {
mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(),
false),
NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
+ boolean hasChannel = hadChannel || hasRequestedNotificationPermission;
+ if (!hasChannel) {
+ ParceledListSlice<NotificationChannel> currChannels =
+ mPreferencesHelper.getNotificationChannels(pkg, uid, true);
+ hasChannel = currChannels != null && !currChannels.getList().isEmpty();
+ }
+ if (!hadChannel && hasChannel && !hasRequestedNotificationPermission
+ && startingTaskId != ActivityTaskManager.INVALID_TASK_ID) {
+ hasRequestedNotificationPermission = true;
+ mHandler.post(new ShowNotificationPermissionPromptRunnable(pkg,
+ UserHandle.getUserId(uid), startingTaskId,
+ mPermissionPolicyInternal));
+ }
}
}
if (needsPolicyFileChange) {
@@ -3698,10 +3726,29 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public void createNotificationChannels(String pkg,
- ParceledListSlice channelsList) {
+ public void createNotificationChannels(String pkg, ParceledListSlice channelsList) {
checkCallerIsSystemOrSameApp(pkg);
- createNotificationChannelsImpl(pkg, Binder.getCallingUid(), channelsList);
+ int taskId = ActivityTaskManager.INVALID_TASK_ID;
+ try {
+ int uid = mPackageManager.getPackageUid(pkg, 0,
+ UserHandle.getUserId(Binder.getCallingUid()));
+ List<ActivityManager.AppTask> tasks = mAtm.getAppTasks(pkg, uid);
+ for (int i = 0; i < tasks.size(); i++) {
+ ActivityManager.RecentTaskInfo task = tasks.get(i).getTaskInfo();
+ if (mPermissionPolicyInternal == null) {
+ mPermissionPolicyInternal =
+ LocalServices.getService(PermissionPolicyInternal.class);
+ }
+ if (mPermissionPolicyInternal != null
+ && mPermissionPolicyInternal.canShowPermissionPromptForTask(task)) {
+ taskId = task.taskId;
+ break;
+ }
+ }
+ } catch (RemoteException e) {
+ // Do nothing
+ }
+ createNotificationChannelsImpl(pkg, Binder.getCallingUid(), channelsList, taskId);
}
@Override
@@ -3822,7 +3869,8 @@ public class NotificationManagerService extends SystemService {
final int callingUid = Binder.getCallingUid();
NotificationChannelGroup groupToDelete =
- mPreferencesHelper.getNotificationChannelGroup(groupId, pkg, callingUid);
+ mPreferencesHelper.getNotificationChannelGroupWithChannels(
+ pkg, callingUid, groupId, false);
if (groupToDelete != null) {
// Preflight for allowability
final int userId = UserHandle.getUserId(callingUid);
@@ -3884,8 +3932,8 @@ public class NotificationManagerService extends SystemService {
public int getNumNotificationChannelsForPackage(String pkg, int uid,
boolean includeDeleted) {
enforceSystemOrSystemUI("getNumNotificationChannelsForPackage");
- return mPreferencesHelper.getNotificationChannels(pkg, uid, includeDeleted)
- .getList().size();
+ return NotificationManagerService.this
+ .getNumNotificationChannelsForPackage(pkg, uid, includeDeleted);
}
@Override
@@ -6150,8 +6198,25 @@ public class NotificationManagerService extends SystemService {
// initially *and* force remove FLAG_FOREGROUND_SERVICE.
sbn.getNotification().flags = (r.mOriginalFlags & ~FLAG_FOREGROUND_SERVICE);
}
+
+ @Override
+ public int getNumNotificationChannelsForPackage(String pkg, int uid,
+ boolean includeDeleted) {
+ return NotificationManagerService.this
+ .getNumNotificationChannelsForPackage(pkg, uid, includeDeleted);
+ }
+
+ @Override
+ public boolean areNotificationsEnabledForPackage(String pkg, int uid) {
+ return areNotificationsEnabledForPackageInt(pkg, uid);
+ }
};
+ int getNumNotificationChannelsForPackage(String pkg, int uid, boolean includeDeleted) {
+ return mPreferencesHelper.getNotificationChannels(pkg, uid, includeDeleted).getList()
+ .size();
+ }
+
void cancelNotificationInternal(String pkg, String opPkg, int callingUid, int callingPid,
String tag, int id, int userId) {
userId = ActivityManager.handleIncomingUser(callingPid,
@@ -6973,6 +7038,44 @@ public class NotificationManagerService extends SystemService {
}
}
+ protected static class ShowNotificationPermissionPromptRunnable implements Runnable {
+ private final String mPkgName;
+ private final int mUserId;
+ private final int mTaskId;
+ private final PermissionPolicyInternal mPpi;
+
+ ShowNotificationPermissionPromptRunnable(String pkg, int user, int task,
+ PermissionPolicyInternal pPi) {
+ mPkgName = pkg;
+ mUserId = user;
+ mTaskId = task;
+ mPpi = pPi;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof ShowNotificationPermissionPromptRunnable)) {
+ return false;
+ }
+
+ ShowNotificationPermissionPromptRunnable other =
+ (ShowNotificationPermissionPromptRunnable) o;
+
+ return Objects.equals(mPkgName, other.mPkgName) && mUserId == other.mUserId
+ && mTaskId == other.mTaskId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPkgName, mUserId, mTaskId);
+ }
+
+ @Override
+ public void run() {
+ mPpi.showNotificationPromptIfNeeded(mPkgName, mUserId, mTaskId);
+ }
+ }
+
protected class EnqueueNotificationRunnable implements Runnable {
private final NotificationRecord r;
private final int userId;
diff --git a/services/core/java/com/android/server/notification/PermissionHelper.java b/services/core/java/com/android/server/notification/PermissionHelper.java
index 24008d0f64ca..0cbdbc18ad39 100644
--- a/services/core/java/com/android/server/notification/PermissionHelper.java
+++ b/services/core/java/com/android/server/notification/PermissionHelper.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.permission.PermissionManager.PERMISSION_GRANTED;
@@ -159,13 +160,21 @@ public final class PermissionHelper {
}
/**
+ * @see setNotificationPermission(String, int, boolean, boolean, boolean)
+ */
+ public void setNotificationPermission(String packageName, @UserIdInt int userId, boolean grant,
+ boolean userSet) {
+ setNotificationPermission(packageName, userId, grant, userSet, false);
+ }
+
+ /**
* Grants or revokes the notification permission for a given package/user. UserSet should
* only be true if this method is being called to migrate existing user choice, because it
* can prevent the user from seeing the in app permission dialog. Must not be called
* with a lock held.
*/
public void setNotificationPermission(String packageName, @UserIdInt int userId, boolean grant,
- boolean userSet) {
+ boolean userSet, boolean reviewRequired) {
assertFlag();
final long callingId = Binder.clearCallingIdentity();
try {
@@ -177,7 +186,12 @@ public final class PermissionHelper {
}
if (userSet) {
mPermManager.updatePermissionFlags(packageName, NOTIFICATION_PERMISSION,
- FLAG_PERMISSION_USER_SET, FLAG_PERMISSION_USER_SET, true, userId);
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_REVIEW_REQUIRED,
+ FLAG_PERMISSION_USER_SET, true, userId);
+ } else if (reviewRequired) {
+ mPermManager.updatePermissionFlags(packageName, NOTIFICATION_PERMISSION,
+ FLAG_PERMISSION_REVIEW_REQUIRED, FLAG_PERMISSION_REVIEW_REQUIRED, true,
+ userId);
}
} catch (RemoteException e) {
Slog.e(TAG, "Could not reach system server", e);
@@ -186,15 +200,17 @@ public final class PermissionHelper {
}
}
+ /**
+ * Set the notification permission state upon phone version upgrade from S- to T+, or upon
+ * restoring a pre-T backup on a T+ device
+ */
public void setNotificationPermission(PackagePermission pkgPerm) {
assertFlag();
- final long callingId = Binder.clearCallingIdentity();
- try {
- setNotificationPermission(
- pkgPerm.packageName, pkgPerm.userId, pkgPerm.granted, pkgPerm.userSet);
- } finally {
- Binder.restoreCallingIdentity(callingId);
+ if (pkgPerm == null || pkgPerm.packageName == null) {
+ return;
}
+ setNotificationPermission(pkgPerm.packageName, pkgPerm.userId, pkgPerm.granted,
+ pkgPerm.userSet, !pkgPerm.userSet);
}
public boolean isPermissionFixed(String packageName, @UserIdInt int userId) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 258ae8c1c849..0246c0c851cf 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -848,6 +848,9 @@ public class PreferencesHelper implements RankingConfig {
if (r == null) {
throw new IllegalArgumentException("Invalid package");
}
+ if (fromTargetApp) {
+ group.setBlocked(false);
+ }
final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
if (oldGroup != null) {
group.setChannels(oldGroup.getChannels());
diff --git a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
index 92cdce7ddceb..737353dc5151 100644
--- a/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
+++ b/services/core/java/com/android/server/notification/ScheduleConditionProvider.java
@@ -261,7 +261,8 @@ public class ScheduleConditionProvider extends SystemConditionProviderService {
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(ACTION_EVALUATE);
filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
- registerReceiver(mReceiver, filter);
+ registerReceiver(mReceiver, filter,
+ Context.RECEIVER_EXPORTED_UNAUDITED);
} else {
unregisterReceiver(mReceiver);
}
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 4500bbcd250f..7f265df3f416 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -116,7 +116,8 @@ public class SnoozeHelper {
mContext = context;
IntentFilter filter = new IntentFilter(REPOST_ACTION);
filter.addDataScheme(REPOST_SCHEME);
- mContext.registerReceiver(mBroadcastReceiver, filter);
+ mContext.registerReceiver(mBroadcastReceiver, filter,
+ Context.RECEIVER_EXPORTED_UNAUDITED);
mAm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mCallback = callback;
mUserProfiles = userProfiles;
diff --git a/services/core/java/com/android/server/notification/VibratorHelper.java b/services/core/java/com/android/server/notification/VibratorHelper.java
index be5f2194997a..8acc8572453b 100644
--- a/services/core/java/com/android/server/notification/VibratorHelper.java
+++ b/services/core/java/com/android/server/notification/VibratorHelper.java
@@ -125,10 +125,10 @@ public final class VibratorHelper {
private static VibrationEffect createChirpVibration(int rampDuration, boolean insistent) {
VibrationEffect.WaveformBuilder waveformBuilder = VibrationEffect.startWaveform()
- .addStep(/* amplitude= */ 0, /* frequency= */ -0.85f, /* duration= */ 0)
- .addRamp(/* amplitude= */ 1, /* frequency= */ -0.25f, rampDuration)
- .addStep(/* amplitude= */ 1, /* frequency= */ -0.25f, CHIRP_LEVEL_DURATION_MILLIS)
- .addRamp(/* amplitude= */ 0, /* frequency= */ -0.85f, rampDuration);
+ .addStep(/* amplitude= */ 0, /* frequencyHz= */ 60f, /* duration= */ 0)
+ .addRamp(/* amplitude= */ 1, /* frequencyHz= */ 120f, rampDuration)
+ .addStep(/* amplitude= */ 1, /* frequencyHz= */ 120f, CHIRP_LEVEL_DURATION_MILLIS)
+ .addRamp(/* amplitude= */ 0, /* frequencyHz= */ 60f, rampDuration);
if (insistent) {
return waveformBuilder
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 05567480e6bf..c285e2795510 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -799,7 +799,7 @@ public abstract class ApexManager {
throw new RuntimeException(re);
} catch (Exception e) {
throw new PackageManagerException(
- PackageInstaller.SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ PackageInstaller.SessionInfo.SESSION_VERIFICATION_FAILED,
"apexd verification failed : " + e.getMessage());
}
}
@@ -826,7 +826,7 @@ public abstract class ApexManager {
throw new RuntimeException(re);
} catch (Exception e) {
throw new PackageManagerException(
- PackageInstaller.SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ PackageInstaller.SessionInfo.SESSION_VERIFICATION_FAILED,
"Failed to mark apexd session as ready : " + e.getMessage());
}
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 05a51ccfaca7..31df0a53eaa9 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -896,10 +896,10 @@ public final class BackgroundDexOptService {
synchronized (mLock) {
if (!mFinishedPostBootUpdate) {
mFinishedPostBootUpdate = true;
- JobScheduler js = mInjector.getJobScheduler();
- js.cancel(JOB_POST_BOOT_UPDATE);
}
}
+ // Safe to do this outside lock.
+ mInjector.getJobScheduler().cancel(JOB_POST_BOOT_UPDATE);
}
private void notifyPinService(ArraySet<String> updatedPackages) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index cfcf199d01a4..8ebd254d03d3 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -70,6 +70,7 @@ import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.ExceptionUtils;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -121,7 +122,7 @@ import java.util.function.Supplier;
public class PackageInstallerService extends IPackageInstaller.Stub implements
PackageSessionProvider {
private static final String TAG = "PackageInstaller";
- private static final boolean LOGD = false;
+ private static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
private static final boolean DEBUG = Build.IS_DEBUGGABLE;
@@ -135,7 +136,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
/** Automatically destroy sessions older than this */
private static final long MAX_AGE_MILLIS = 3 * DateUtils.DAY_IN_MILLIS;
/** Automatically destroy staged sessions that have not changed state in this time */
- private static final long MAX_TIME_SINCE_UPDATE_MILLIS = 7 * DateUtils.DAY_IN_MILLIS;
+ private static final long MAX_TIME_SINCE_UPDATE_MILLIS = 21 * DateUtils.DAY_IN_MILLIS;
/** Upper bound on number of active sessions for a UID that has INSTALL_PACKAGES */
private static final long MAX_ACTIVE_SESSIONS_WITH_PERMISSION = 1024;
/** Upper bound on number of active sessions for a UID without INSTALL_PACKAGES */
@@ -330,7 +331,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
StagingManager.StagedSession stagedSession = session.mStagedSession;
if (!stagedSession.isInTerminalState() && stagedSession.hasParentSessionId()
&& getSession(stagedSession.getParentSessionId()) == null) {
- stagedSession.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ stagedSession.setSessionFailed(SessionInfo.SESSION_ACTIVATION_FAILED,
"An orphan staged session " + stagedSession.sessionId() + " is found, "
+ "parent " + stagedSession.getParentSessionId() + " is missing");
continue;
@@ -510,6 +511,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
valid = true;
}
if (!valid) {
+ Slog.w(TAG, "Remove old session: " + session.sessionId);
// Remove expired sessions as well as child sessions if any
mSessions.remove(session.sessionId);
// Since this is early during boot we don't send
@@ -841,7 +843,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
mSilentUpdatePolicy, mInstallThread.getLooper(), mStagingManager, sessionId,
userId, callingUid, installSource, params, createdMillis, 0L, stageDir, stageCid,
null, null, false, false, false, false, null, SessionInfo.INVALID_ID,
- false, false, false, SessionInfo.STAGED_SESSION_NO_ERROR, "");
+ false, false, false, SessionInfo.SESSION_NO_ERROR, "");
synchronized (mSessions) {
mSessions.put(sessionId, session);
@@ -850,6 +852,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
mCallbacks.notifySessionCreated(session.sessionId, session.userId);
mSettingsWriteRequest.schedule();
+ if (LOGD) {
+ Slog.d(TAG, "Created session id=" + sessionId + " staged=" + params.isStaged);
+ }
return sessionId;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index f45e54b04e54..304ad72c6359 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -460,7 +460,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@GuardedBy("mLock")
private boolean mSessionFailed;
@GuardedBy("mLock")
- private int mSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
+ private int mSessionErrorCode = SessionInfo.SESSION_NO_ERROR;
@GuardedBy("mLock")
private String mSessionErrorMessage;
@@ -2092,7 +2092,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (isStaged()) {
// This will clean up the session when it reaches the terminal state
mStagedSession.setSessionFailed(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, msgWithErrorCode);
+ SessionInfo.SESSION_VERIFICATION_FAILED, msgWithErrorCode);
mStagedSession.notifyEndPreRebootVerification();
} else {
// Session is sealed and committed but could not be verified, we need to destroy it.
@@ -2547,7 +2547,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (isStaged()) {
mSessionProvider.getSessionVerifier().verifyStaged(mStagedSession, (error, msg) -> {
mStagedSession.notifyEndPreRebootVerification();
- if (error == SessionInfo.STAGED_SESSION_NO_ERROR) {
+ if (error == SessionInfo.SESSION_NO_ERROR) {
mStagingManager.commitSession(mStagedSession);
}
});
@@ -4168,7 +4168,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mSessionReady = true;
mSessionApplied = false;
mSessionFailed = false;
- mSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
+ mSessionErrorCode = SessionInfo.SESSION_NO_ERROR;
mSessionErrorMessage = "";
}
mCallback.onSessionChanged(this);
@@ -4196,7 +4196,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mSessionReady = false;
mSessionApplied = true;
mSessionFailed = false;
- mSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
+ mSessionErrorCode = SessionInfo.SESSION_NO_ERROR;
mSessionErrorMessage = "";
Slog.d(TAG, "Marking session " + sessionId + " as applied");
}
@@ -4705,7 +4705,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final boolean isFailed = in.getAttributeBoolean(null, ATTR_IS_FAILED, false);
final boolean isApplied = in.getAttributeBoolean(null, ATTR_IS_APPLIED, false);
final int sessionErrorCode = in.getAttributeInt(null, ATTR_SESSION_ERROR_CODE,
- SessionInfo.STAGED_SESSION_NO_ERROR);
+ SessionInfo.SESSION_NO_ERROR);
final String sessionErrorMessage = readStringAttribute(in, ATTR_SESSION_ERROR_MESSAGE);
if (!isStagedSessionStateValid(isReady, isApplied, isFailed)) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 0564e858c84c..be2bdaac13e4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2816,7 +2816,7 @@ class PackageManagerShellCommand extends ShellCommand {
case UserManager.REMOVE_RESULT_REMOVED:
getOutPrintWriter().printf("Success: user %d removed\n", userId);
return 0;
- case UserManager.REMOVE_RESULT_SET_EPHEMERAL:
+ case UserManager.REMOVE_RESULT_DEFERRED:
getOutPrintWriter().printf("Success: user %d set as ephemeral\n", userId);
return 0;
case UserManager.REMOVE_RESULT_ALREADY_BEING_REMOVED:
diff --git a/services/core/java/com/android/server/pm/PackageSessionVerifier.java b/services/core/java/com/android/server/pm/PackageSessionVerifier.java
index a532fe3a3d4d..ccabce719402 100644
--- a/services/core/java/com/android/server/pm/PackageSessionVerifier.java
+++ b/services/core/java/com/android/server/pm/PackageSessionVerifier.java
@@ -202,7 +202,7 @@ final class PackageSessionVerifier {
}
private void onVerificationSuccess(StagingManager.StagedSession session, Callback callback) {
- callback.onResult(SessionInfo.STAGED_SESSION_NO_ERROR, null);
+ callback.onResult(SessionInfo.SESSION_NO_ERROR, null);
}
private void onVerificationFailure(StagingManager.StagedSession session, Callback callback,
@@ -298,7 +298,7 @@ final class PackageSessionVerifier {
// Failed to get hold of StorageManager
Slog.e(TAG, "Failed to get hold of StorageManager", e);
throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_UNKNOWN,
+ SessionInfo.SESSION_UNKNOWN_ERROR,
"Failed to get hold of StorageManager");
}
// Proactively mark session as ready before calling apexd. Although this call order
@@ -336,7 +336,7 @@ final class PackageSessionVerifier {
final ParseResult<SigningDetails> newResult = ApkSignatureVerifier.verify(
input.reset(), apexPath, minSignatureScheme);
if (newResult.isError()) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ throw new PackageManagerException(SessionInfo.SESSION_VERIFICATION_FAILED,
"Failed to parse APEX package " + apexPath + " : "
+ newResult.getException(), newResult.getException());
}
@@ -355,7 +355,7 @@ final class PackageSessionVerifier {
input.reset(), existingApexPkg.applicationInfo.sourceDir,
SigningDetails.SignatureSchemeVersion.JAR);
if (existingResult.isError()) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ throw new PackageManagerException(SessionInfo.SESSION_VERIFICATION_FAILED,
"Failed to parse APEX package " + existingApexPkg.applicationInfo.sourceDir
+ " : " + existingResult.getException(), existingResult.getException());
}
@@ -369,7 +369,7 @@ final class PackageSessionVerifier {
return;
}
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ throw new PackageManagerException(SessionInfo.SESSION_VERIFICATION_FAILED,
"APK-container signature of APEX package " + packageName + " with version "
+ newApexPkg.versionCodeMajor + " and path " + apexPath + " is not"
+ " compatible with the one currently installed on device");
@@ -412,11 +412,11 @@ final class PackageSessionVerifier {
packageInfo = PackageInfoWithoutStateUtils.generate(parsedPackage, apexInfo, flags);
if (packageInfo == null) {
throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ SessionInfo.SESSION_VERIFICATION_FAILED,
"Unable to generate package info: " + apexInfo.modulePath);
}
} catch (PackageManagerException e) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ throw new PackageManagerException(SessionInfo.SESSION_VERIFICATION_FAILED,
"Failed to parse APEX package " + apexInfo.modulePath + " : " + e, e);
}
result.add(packageInfo);
@@ -438,7 +438,7 @@ final class PackageSessionVerifier {
}
}
throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ SessionInfo.SESSION_VERIFICATION_FAILED,
"Could not find rollback id for commit session: " + sessionId);
}
@@ -546,7 +546,7 @@ final class PackageSessionVerifier {
try {
checkActiveSessions(PackageHelper.getStorageManager().supportsCheckpoint());
} catch (RemoteException e) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ throw new PackageManagerException(SessionInfo.SESSION_VERIFICATION_FAILED,
"Can't query fs-checkpoint status : " + e);
}
}
@@ -562,7 +562,7 @@ final class PackageSessionVerifier {
}
if (!supportsCheckpoint && activeSessions > 1) {
throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ SessionInfo.SESSION_VERIFICATION_FAILED,
"Cannot stage multiple sessions without checkpoint support");
}
}
@@ -593,13 +593,13 @@ final class PackageSessionVerifier {
// will be deleted.
}
stagedSession.setSessionFailed(
- SessionInfo.STAGED_SESSION_CONFLICT,
+ SessionInfo.SESSION_CONFLICT,
"Session was failed by rollback session: " + session.sessionId());
Slog.i(TAG, "Session " + stagedSession.sessionId() + " is marked failed due to "
+ "rollback session: " + session.sessionId());
} else if (!isRollback(session) && isRollback(stagedSession)) {
throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_CONFLICT,
+ SessionInfo.SESSION_CONFLICT,
"Session was failed by rollback session: " + stagedSession.sessionId());
}
@@ -622,7 +622,7 @@ final class PackageSessionVerifier {
final String packageName = child.getPackageName();
if (packageName == null) {
throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ SessionInfo.SESSION_VERIFICATION_FAILED,
"Cannot stage session " + child.sessionId() + " with package name null");
}
for (StagingManager.StagedSession stagedSession : mStagedSessions) {
@@ -634,14 +634,14 @@ final class PackageSessionVerifier {
if (stagedSession.getCommittedMillis() < parent.getCommittedMillis()) {
// Fail the session committed later when there are overlapping packages
throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ SessionInfo.SESSION_VERIFICATION_FAILED,
"Package: " + packageName + " in session: "
+ child.sessionId()
+ " has been staged already by session: "
+ stagedSession.sessionId());
} else {
stagedSession.setSessionFailed(
- SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ SessionInfo.SESSION_VERIFICATION_FAILED,
"Package: " + packageName + " in session: "
+ stagedSession.sessionId()
+ " has been staged already by session: "
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 8a6ef6bfcb41..29de5551cb27 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -284,7 +284,7 @@ public class StagingManager {
String packageName = apexSession.getPackageName();
String errorMsg = mApexManager.getApkInApexInstallError(packageName);
if (errorMsg != null) {
- throw new PackageManagerException(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ throw new PackageManagerException(SessionInfo.SESSION_ACTIVATION_FAILED,
"Failed to install apk-in-apex of " + packageName + " : " + errorMsg);
}
}
@@ -397,7 +397,7 @@ public class StagingManager {
revertMsg += " Reason for revert: " + reasonForRevert;
}
Slog.d(TAG, revertMsg);
- session.setSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, revertMsg);
+ session.setSessionFailed(SessionInfo.SESSION_UNKNOWN_ERROR, revertMsg);
return;
}
@@ -484,7 +484,7 @@ public class StagingManager {
for (String apkInApex : mApexManager.getApksInApex(packageName)) {
if (!apkNames.add(apkInApex)) {
throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ SessionInfo.SESSION_ACTIVATION_FAILED,
"Package: " + packageName + " in session: "
+ apexSession.sessionId() + " has duplicate apk-in-apex: "
+ apkInApex, null);
@@ -511,7 +511,7 @@ public class StagingManager {
Slog.e(TAG, "Failure to install APK staged session "
+ session.sessionId() + " [" + errorMessage + "]");
throw new PackageManagerException(
- SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMessage);
+ SessionInfo.SESSION_ACTIVATION_FAILED, errorMessage);
}
}
@@ -665,7 +665,7 @@ public class StagingManager {
// is upgrading. Fail all the sessions and exit early.
for (int i = 0; i < sessions.size(); i++) {
StagedSession session = sessions.get(i);
- session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ session.setSessionFailed(SessionInfo.SESSION_ACTIVATION_FAILED,
"Build fingerprint has changed");
}
return;
@@ -705,7 +705,7 @@ public class StagingManager {
final ApexSessionInfo apexSession = apexSessions.get(session.sessionId());
if (apexSession == null || apexSession.isUnknown) {
hasFailedApexSession = true;
- session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, "apexd did "
+ session.setSessionFailed(SessionInfo.SESSION_ACTIVATION_FAILED, "apexd did "
+ "not know anything about a staged session supposed to be activated");
continue;
} else if (isApexSessionFailed(apexSession)) {
@@ -721,7 +721,7 @@ public class StagingManager {
errorMsg += " Error: " + apexSession.errorMessage;
}
Slog.d(TAG, errorMsg);
- session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
+ session.setSessionFailed(SessionInfo.SESSION_ACTIVATION_FAILED, errorMsg);
continue;
} else if (apexSession.isActivated || apexSession.isSuccess) {
hasAppliedApexSession = true;
@@ -730,13 +730,13 @@ public class StagingManager {
// Apexd did not apply the session for some unknown reason. There is no guarantee
// that apexd will install it next time. Safer to proactively mark it as failed.
hasFailedApexSession = true;
- session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ session.setSessionFailed(SessionInfo.SESSION_ACTIVATION_FAILED,
"Staged session " + session.sessionId() + " at boot didn't activate nor "
+ "fail. Marking it as failed anyway.");
} else {
Slog.w(TAG, "Apex session " + session.sessionId() + " is in impossible state");
hasFailedApexSession = true;
- session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ session.setSessionFailed(SessionInfo.SESSION_ACTIVATION_FAILED,
"Impossible state");
}
}
@@ -756,7 +756,7 @@ public class StagingManager {
// Session has been already failed in the loop above.
continue;
}
- session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ session.setSessionFailed(SessionInfo.SESSION_ACTIVATION_FAILED,
"Another apex session failed");
}
return;
@@ -772,7 +772,7 @@ public class StagingManager {
} catch (Exception e) {
Slog.e(TAG, "Staged install failed due to unhandled exception", e);
onInstallationFailure(session, new PackageManagerException(
- SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ SessionInfo.SESSION_ACTIVATION_FAILED,
"Staged install failed due to unhandled exception: " + e),
supportsCheckpoint, needsCheckpoint);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 167ad3ba7d0e..fb3ca91003ea 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3537,8 +3537,11 @@ public class UserManagerService extends IUserManager.Stub {
Slog.wtf(LOG_TAG, "Seeing both legacy and current local restrictions in xml");
}
} else if (legacyLocalRestrictions != null) {
- mDevicePolicyLocalUserRestrictions.put(id,
- new RestrictionsSet(id, legacyLocalRestrictions));
+ RestrictionsSet legacyLocalRestrictionsSet =
+ legacyLocalRestrictions.isEmpty()
+ ? new RestrictionsSet()
+ : new RestrictionsSet(id, legacyLocalRestrictions);
+ mDevicePolicyLocalUserRestrictions.put(id, legacyLocalRestrictionsSet);
}
if (globalRestrictions != null) {
mDevicePolicyGlobalUserRestrictions.updateRestrictions(id,
@@ -4478,7 +4481,7 @@ public class UserManagerService extends IUserManager.Stub {
userData.info.flags |= UserInfo.FLAG_EPHEMERAL;
writeUserLP(userData);
- return UserManager.REMOVE_RESULT_SET_EPHEMERAL;
+ return UserManager.REMOVE_RESULT_DEFERRED;
}
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index af524db74341..60d2fc1ab498 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1378,7 +1378,9 @@ final class DefaultPermissionGrantPolicy {
pm.grantPermission(permission, pkg, user);
}
- pm.updatePermissionFlags(permission, pkg, newFlags, newFlags, user);
+ // clear the REVIEW_REQUIRED flag, if set
+ int flagMask = newFlags | PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+ pm.updatePermissionFlags(permission, pkg, flagMask, newFlags, user);
}
// If a component gets a permission for being the default handler A
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index a3b6b8221843..1cfcdf51f5b8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -66,9 +66,11 @@ import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.function.TriFunction;
import com.android.server.LocalServices;
import com.android.server.pm.UserManagerInternal;
+import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal.HotwordDetectionServiceProvider;
@@ -384,7 +386,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Override
public void startOneTimePermissionSession(String packageName, @UserIdInt int userId,
long timeoutMillis, int importanceToResetTimer, int importanceToKeepSessionAlive) {
- mContext.enforceCallingPermission(Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS,
"Must hold " + Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS
+ " to register permissions as one time.");
Objects.requireNonNull(packageName);
@@ -549,6 +552,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
+ public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) {
+ mPermissionManagerServiceImpl.revokePostNotificationPermissionWithoutKillForTest(
+ packageName, userId);
+ }
+
+ @Override
+ public void selfRevokePermissions(@NonNull String packageName,
+ @NonNull List<String> permissions) {
+ mPermissionManagerServiceImpl.selfRevokePermissions(packageName, permissions);
+ }
+
+ @Override
public boolean shouldShowRequestPermissionRationale(String packageName, String permissionName,
int userId) {
return mPermissionManagerServiceImpl.shouldShowRequestPermissionRationale(packageName,
@@ -678,8 +693,23 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Override
public void onPackageInstalled(@NonNull AndroidPackage pkg, int previousAppId,
- @NonNull PackageInstalledParams params, @UserIdInt int userId) {
- mPermissionManagerServiceImpl.onPackageInstalled(pkg, previousAppId, params, userId);
+ @NonNull PackageInstalledParams params, @UserIdInt int rawUserId) {
+ Objects.requireNonNull(pkg, "pkg");
+ Objects.requireNonNull(params, "params");
+ Preconditions.checkArgument(rawUserId >= UserHandle.USER_SYSTEM
+ || rawUserId == UserHandle.USER_ALL, "userId");
+
+ mPermissionManagerServiceImpl.onPackageInstalled(pkg, previousAppId, params, rawUserId);
+ final int[] userIds = rawUserId == UserHandle.USER_ALL ? getAllUserIds()
+ : new int[] { rawUserId };
+ for (final int userId : userIds) {
+ final int autoRevokePermissionsMode = params.getAutoRevokePermissionsMode();
+ if (autoRevokePermissionsMode == AppOpsManager.MODE_ALLOWED
+ || autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED) {
+ setAutoRevokeExemptedInternal(pkg,
+ autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED, userId);
+ }
+ }
}
@Override
@@ -780,6 +810,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
/**
+ * Returns all relevant user ids. This list include the current set of created user ids as well
+ * as pre-created user ids.
+ * @return user ids for created users and pre-created users
+ */
+ private int[] getAllUserIds() {
+ return UserManagerService.getInstance().getUserIdsIncludingPreCreated();
+ }
+
+ /**
* Interface to intercept permission checks and optionally pass through to the original
* implementation.
*/
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index c9fd12219562..7833c4341a94 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -19,8 +19,6 @@ package com.android.server.pm.permission;
import static android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
-import static android.app.AppOpsManager.MODE_ALLOWED;
-import static android.app.AppOpsManager.MODE_IGNORED;
import static android.content.pm.PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
import static android.content.pm.PackageManager.FLAG_PERMISSION_AUTO_REVOKED;
@@ -63,7 +61,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
-import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.compat.annotation.ChangeId;
@@ -170,6 +167,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
private static final String TAG = "PackageManager";
private static final String LOG_TAG = PermissionManagerServiceImpl.class.getSimpleName();
+ private static final String SKIP_KILL_APP_REASON_NOTIFICATION_TEST = "skip permission revoke "
+ + "app kill for notification test";
+
+
private static final long BACKUP_TIMEOUT_MILLIS = SECONDS.toMillis(60);
// For automotive products, CarService enforces allow-listing of the privileged permissions
@@ -198,14 +199,19 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
/** All nearby devices permissions */
private static final List<String> NEARBY_DEVICES_PERMISSIONS = new ArrayList<>();
- // TODO: This is a placeholder. Replace with actual implementation
- private static final List<String> NOTIFICATION_PERMISSIONS = new ArrayList<>();
-
/**
- * All permissions that should be granted with the REVOKE_WHEN_REQUESTED flag, if they are
- * implicitly added to a package
+ * All notification permissions.
+ * Notification permission state is treated differently from other permissions. Notification
+ * permission get the REVIEW_REQUIRED flag set for S- apps, or for T+ apps on updating to T or
+ * restoring a pre-T backup. The permission and app op remain denied. The flag will be read by
+ * the notification system, and allow apps to send notifications, until cleared.
+ * The flag is cleared for S- apps by the system showing a permission request prompt, and the
+ * user clicking "allow" or "deny" in the dialog. For T+ apps, the flag is cleared upon the
+ * first activity launch.
+ *
+ * @see PermissionPolicyInternal#showNotificationPromptIfNeeded(String, int, int)
*/
- private static final List<String> IMPLICIT_GRANTED_PERMISSIONS = new ArrayList<>();
+ private static final List<String> NOTIFICATION_PERMISSIONS = new ArrayList<>();
/** If the permission of the value is granted, so is the key */
private static final Map<String, String> FULLER_PERMISSION_MAP = new HashMap<>();
@@ -221,7 +227,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_ADVERTISE);
NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_CONNECT);
NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_SCAN);
- IMPLICIT_GRANTED_PERMISSIONS.add(Manifest.permission.POST_NOTIFICATIONS);
+ NOTIFICATION_PERMISSIONS.add(Manifest.permission.POST_NOTIFICATIONS);
}
/** Set of source package names for Privileged Permission Allowlist */
@@ -244,9 +250,6 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
/** Permission controller: User space permission management */
private PermissionControllerManager mPermissionControllerManager;
- /** App ops manager */
- private final AppOpsManager mAppOpsManager;
-
/**
* Built-in permissions. Read from system configuration files. Mapping is from
* UID to permission name.
@@ -321,11 +324,15 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
mPackageManagerInt.writeSettings(true);
}
@Override
- public void onPermissionRevoked(int uid, int userId, String reason) {
+ public void onPermissionRevoked(int uid, int userId, String reason, boolean overrideKill) {
mOnPermissionChangeListeners.onPermissionsChanged(uid);
// Critical; after this call the application should never have the permission
mPackageManagerInt.writeSettings(false);
+ if (overrideKill) {
+ return;
+ }
+
final int appId = UserHandle.getAppId(uid);
if (reason == null) {
mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED));
@@ -374,7 +381,6 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
mContext = context;
mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
- mAppOpsManager = context.getSystemService(AppOpsManager.class);
mPrivilegedPermissionAllowlistSourcePackageNames.add(PLATFORM_PACKAGE_NAME);
// PackageManager.hasSystemFeature() is not used here because PackageManagerService
@@ -1440,9 +1446,29 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
reason, mDefaultPermissionCallback);
}
+ @Override
+ public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final boolean overridePolicy =
+ checkUidPermission(callingUid, ADJUST_RUNTIME_PERMISSIONS_POLICY)
+ == PackageManager.PERMISSION_GRANTED;
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL, "");
+ revokeRuntimePermissionInternal(packageName, Manifest.permission.POST_NOTIFICATIONS,
+ overridePolicy, true, callingUid, userId,
+ SKIP_KILL_APP_REASON_NOTIFICATION_TEST, mDefaultPermissionCallback);
+ }
+
private void revokeRuntimePermissionInternal(String packageName, String permName,
- boolean overridePolicy, int callingUid, final int userId, String reason,
- PermissionCallback callback) {
+ boolean overridePolicy, int callingUid, final int userId,
+ String reason, PermissionCallback callback) {
+ revokeRuntimePermissionInternal(packageName, permName, overridePolicy, false, callingUid,
+ userId, reason, callback);
+ }
+
+ private void revokeRuntimePermissionInternal(String packageName, String permName,
+ boolean overridePolicy, boolean overrideKill, int callingUid, final int userId,
+ String reason, PermissionCallback callback) {
if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES
&& PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
Log.i(TAG, "System is revoking " + packageName + " "
@@ -1554,7 +1580,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
if (callback != null) {
if (isRuntimePermission) {
callback.onPermissionRevoked(UserHandle.getUid(userId, pkg.getUid()), userId,
- reason);
+ reason, overrideKill);
} else {
mDefaultPermissionCallback.onInstallPermissionRevoked();
}
@@ -1565,6 +1591,25 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
}
+ @Override
+ public void selfRevokePermissions(String packageName, List<String> permissions) {
+ final int callingUid = Binder.getCallingUid();
+ int callingUserId = UserHandle.getUserId(callingUid);
+ int targetPackageUid = mPackageManagerInt.getPackageUid(packageName, 0, callingUserId);
+ if (targetPackageUid != callingUid) {
+ throw new SecurityException("uid " + callingUid
+ + " cannot revoke permissions for package " + packageName + " with uid "
+ + targetPackageUid);
+ }
+ for (String permName : permissions) {
+ if (!checkCallingOrSelfPermission(permName)) {
+ throw new SecurityException("uid " + callingUid + " cannot revoke permission "
+ + permName + " because it does not hold that permission");
+ }
+ }
+ mPermissionControllerManager.selfRevokePermissions(packageName, permissions);
+ }
+
private boolean mayManageRolePermission(int uid) {
final PackageManager packageManager = mContext.getPackageManager();
final String[] packageNames = packageManager.getPackagesForUid(uid);
@@ -2594,9 +2639,12 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
// Cache newImplicitPermissions before modifing permissionsState as for the
// shared uids the original and new state are the same object
+ // TODO(205888750): remove the line for LEGACY_REVIEW once propagated through
+ // droidfood
if (!origState.hasPermissionState(permName)
&& (pkg.getImplicitPermissions().contains(permName)
- || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
+ || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))
+ || NOTIFICATION_PERMISSIONS.contains(permName)) {
if (pkg.getImplicitPermissions().contains(permName)) {
// If permName is an implicit permission, try to auto-grant
newImplicitPermissions.add(permName);
@@ -2754,9 +2802,11 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
// Remove review flag as it is not necessary anymore
- if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
- flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;
- wasChanged = true;
+ if (!NOTIFICATION_PERMISSIONS.contains(perm)) {
+ if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
+ flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;
+ wasChanged = true;
+ }
}
if ((flags & FLAG_PERMISSION_REVOKED_COMPAT) != 0
@@ -3117,28 +3167,37 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms, newPerm, ps,
pkg);
}
- } else if (IMPLICIT_GRANTED_PERMISSIONS.contains(newPerm)
- && !origPs.hasPermissionState(newPerm)) {
+ } else if (NOTIFICATION_PERMISSIONS.contains(newPerm)) {
+ //&& (origPs.getPermissionState(newPerm) == null) {
+ // TODO(b/205888750): add back line about origPs once propagated through droidfood
Permission bp = mRegistry.getPermission(newPerm);
if (bp == null) {
throw new IllegalStateException("Unknown new permission " + newPerm);
}
- if ((ps.getPermissionState(newPerm).getFlags()
- & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
- // No need to grant if review is required
- continue;
+ // TODO(b/205888750): remove the line for REVOKE_WHEN_REQUESTED once propagated
+ // through droidfood
+ if (!isUserSetOrPregrantedOrFixed(ps.getPermissionFlags(newPerm))) {
+ updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+ ps.updatePermissionFlags(bp, PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
+ | FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
+ PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED);
+ // TODO(b/205888750): remove revoke once propagated through droidfood
+ if (ps.isPermissionGranted(newPerm)) {
+ ps.revokePermission(bp);
+ }
}
- updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
- ps.updatePermissionFlags(bp,
- FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
- FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
- ps.grantPermission(bp);
}
}
return updatedUserIds;
}
+ private boolean isUserSetOrPregrantedOrFixed(int flags) {
+ return (flags & (FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED
+ | FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_SYSTEM_FIXED
+ | FLAG_PERMISSION_GRANTED_BY_DEFAULT | FLAG_PERMISSION_GRANTED_BY_ROLE)) != 0;
+ }
+
@NonNull
@Override
public List<SplitPermissionInfoParcelable> getSplitPermissions() {
@@ -4323,9 +4382,9 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false)
);
- mSystemReady = true;
-
synchronized (mLock) {
+ mSystemReady = true;
+
if (mPrivappPermissionsViolations != null) {
throw new IllegalStateException("Signature|privileged permissions not in "
+ "privapp-permissions allowlist: " + mPrivappPermissionsViolations);
@@ -4905,15 +4964,6 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
addAllowlistedRestrictedPermissionsInternal(pkg,
params.getAllowlistedRestrictedPermissions(),
FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
- final int autoRevokePermissionsMode = params.getAutoRevokePermissionsMode();
- if (autoRevokePermissionsMode == AppOpsManager.MODE_ALLOWED
- || autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED) {
- // TODO: theianchen Bug: 182523293
- // We should move this portion of code that's calling
- // setAutoRevokeExemptedInternal() into the old PMS
- setAutoRevokeExemptedInternal(pkg,
- autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED, userId);
- }
grantRequestedRuntimePermissionsInternal(pkg, params.getGrantedPermissions(), userId);
}
}
@@ -5182,25 +5232,6 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
onPackageUninstalledInternal(packageName, appId, pkg, sharedUserPkgs, userIds);
}
- private boolean setAutoRevokeExemptedInternal(@NonNull AndroidPackage pkg, boolean exempted,
- @UserIdInt int userId) {
- final int packageUid = UserHandle.getUid(userId, pkg.getUid());
- if (mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
- packageUid, pkg.getPackageName()) != MODE_ALLOWED) {
- // Allowlist user set - don't override
- return false;
- }
-
- final long identity = Binder.clearCallingIdentity();
- try {
- mAppOpsManager.setMode(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid,
- pkg.getPackageName(), exempted ? MODE_IGNORED : MODE_ALLOWED);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- return true;
- }
-
/**
* Callbacks invoked when interesting actions have been taken on a permission.
* <p>
@@ -5213,7 +5244,11 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
public void onPermissionChanged() {}
public void onPermissionGranted(int uid, @UserIdInt int userId) {}
public void onInstallPermissionGranted() {}
- public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason) {}
+ public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason) {
+ onPermissionRevoked(uid, userId, reason, false);
+ }
+ public void onPermissionRevoked(int uid, @UserIdInt int userId, String reason,
+ boolean overrideKill) {}
public void onInstallPermissionRevoked() {}
public void onPermissionUpdated(@UserIdInt int[] updatedUserIds, boolean sync) {}
public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
index d2018f26d04a..c582f9efa7a0 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInterface.java
@@ -318,6 +318,35 @@ public interface PermissionManagerServiceInterface extends PermissionManagerInte
String reason);
/**
+ * Revoke the POST_NOTIFICATIONS permission, without killing the app. This method must ONLY BE
+ * USED in CTS or local tests.
+ *
+ * @param packageName The package to be revoked
+ * @param userId The user for which to revoke
+ */
+ void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId);
+
+ /**
+ * Triggers the revocation of one or more permissions for a package, under the following
+ * conditions:
+ * <ul>
+ * <li>The package {@code packageName} must be under the same UID as the calling process
+ * (typically, the target package is the calling package).
+ * <li>Each permission in {@code permissions} must be granted to the package
+ * {@code packageName}.
+ * <li>Each permission in {@code permissions} must be a runtime permission.
+ * </ul>
+ * <p>
+ * For every permission in {@code permissions}, the entire permission group it belongs to will
+ * be revoked. This revocation happens asynchronously and kills all processes running in the
+ * same UID as {@code packageName}. It will be triggered once it is safe to do so.
+ *
+ * @param packageName The name of the package for which the permissions will be revoked.
+ * @param permissions List of permissions to be revoked.
+ */
+ void selfRevokePermissions(String packageName, List<String> permissions);
+
+ /**
* Get whether you should show UI with rationale for requesting a permission. You should do this
* only if you do not have the permission and the context in which the permission is requested
* does not clearly communicate to the user what would be the benefit from grating this
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyInternal.java b/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
index 6084c6718577..20b7ccd39287 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyInternal.java
@@ -19,6 +19,7 @@ package com.android.server.policy;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.TaskInfo;
import android.content.Intent;
/**
@@ -52,6 +53,25 @@ public abstract class PermissionPolicyInternal {
@Nullable String callingPackage);
/**
+ * Check whether a notification permission prompt should be shown for the given package. A
+ * prompt should be shown if the app targets S-, is currently running in a visible, focused
+ * task, has the REVIEW_REQUIRED flag set on its implicit notification permission, and has
+ * created at least one notification channel (even if it has since been deleted).
+ * @param packageName The package whose permission is being checked
+ * @param userId The user for whom the package is being started
+ * @param taskId The task the notification prompt should be attached to
+ */
+ public abstract void showNotificationPromptIfNeeded(@NonNull String packageName, int userId,
+ int taskId);
+
+ /**
+ * Determine if a particular task is in the proper state to show a system-triggered permission
+ * prompt. A prompt can be shown if the task is focused, visible, and running.
+ * @param taskInfo The task to be checked
+ */
+ public abstract boolean canShowPermissionPromptForTask(@Nullable TaskInfo taskInfo);
+
+ /**
* @return Whether the policy is initialized for a user.
*/
public abstract boolean isInitialized(@UserIdInt int userId);
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index ad435146f579..c9a8701ec7af 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -16,6 +16,7 @@
package com.android.server.policy;
+import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.MODE_IGNORED;
@@ -25,16 +26,24 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
import android.app.AppOpsManagerInternal;
+import android.app.TaskInfo;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -43,6 +52,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PermissionInfo;
import android.os.Build;
+import android.os.Bundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -53,6 +63,7 @@ import android.provider.Telephony;
import android.telecom.TelecomManager;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.Log;
import android.util.LongSparseLongArray;
import android.util.Pair;
import android.util.Slog;
@@ -67,17 +78,21 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import com.android.server.notification.NotificationManagerInternal;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import com.android.server.utils.TimingsTraceAndSlog;
+import com.android.server.wm.ActivityInterceptorCallback;
+import com.android.server.wm.ActivityTaskManagerInternal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.ExecutionException;
/**
@@ -89,11 +104,15 @@ import java.util.concurrent.ExecutionException;
*/
public final class PermissionPolicyService extends SystemService {
private static final String LOG_TAG = PermissionPolicyService.class.getSimpleName();
+ private static final String SYSTEM_PKG = "android";
private static final boolean DEBUG = false;
private static final long USER_SENSITIVE_UPDATE_DELAY_MS = 60000;
private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private boolean mBootCompleted = false;
+
private IAppOpsCallback mAppOpsCallback;
/** Whether the user is started but not yet stopped */
@@ -118,24 +137,39 @@ public final class PermissionPolicyService extends SystemService {
@GuardedBy("mLock")
private final SparseBooleanArray mIsUidSyncScheduled = new SparseBooleanArray();
+ /**
+ * This change reflects the presence of the new Notification Permission
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ private static final long NOTIFICATION_PERM_CHANGE_ID = 194833441L;
+
private List<String> mAppOpPermissions;
+ private Context mContext;
+ private PackageManagerInternal mPackageManagerInternal;
+ private NotificationManagerInternal mNotificationManager;
+ private PermissionManagerServiceInternal mPermissionManagerService;
+ private final PackageManager mPackageManager;
+
public PermissionPolicyService(@NonNull Context context) {
super(context);
+ mContext = context;
+ mPackageManager = context.getPackageManager();
LocalServices.addService(PermissionPolicyInternal.class, new Internal());
}
@Override
public void onStart() {
- final PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ mPackageManagerInternal = LocalServices.getService(
PackageManagerInternal.class);
- final PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
+ PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
PermissionManagerServiceInternal.class);
final IAppOpsService appOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
- packageManagerInternal.getPackageList(new PackageListObserver() {
+ mPackageManagerInternal.getPackageList(new PackageListObserver() {
@Override
public void onPackageAdded(String packageName, int uid) {
final int userId = UserHandle.getUserId(uid);
@@ -207,10 +241,10 @@ public final class PermissionPolicyService extends SystemService {
final PermissionInfo appOpPermissionInfo = appOpPermissionInfos.get(i);
switch (appOpPermissionInfo.name) {
- case android.Manifest.permission.ACCESS_NOTIFICATIONS:
- case android.Manifest.permission.MANAGE_IPSEC_TUNNELS:
+ case Manifest.permission.ACCESS_NOTIFICATIONS:
+ case Manifest.permission.MANAGE_IPSEC_TUNNELS:
continue;
- case android.Manifest.permission.REQUEST_INSTALL_PACKAGES:
+ case Manifest.permission.REQUEST_INSTALL_PACKAGES:
// Settings allows the user to control the app op if it's not in the default
// mode, regardless of whether the app has requested the permission, so we
// should not reset it.
@@ -251,7 +285,7 @@ public final class PermissionPolicyService extends SystemService {
}
int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
// If there is no valid package for the given UID, return immediately
- if (packageManagerInternal.getPackage(uid) == null) {
+ if (mPackageManagerInternal.getPackage(uid) == null) {
return;
}
@@ -343,6 +377,18 @@ public final class PermissionPolicyService extends SystemService {
}
}
}
+
+ if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+ ((Internal) LocalServices.getService(PermissionPolicyInternal.class))
+ .onActivityManagerReady();
+ }
+
+ if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+ synchronized (mLock) {
+ mBootCompleted = true;
+ }
+ }
+
}
/**
@@ -748,10 +794,12 @@ public final class PermissionPolicyService extends SystemService {
String permissionName = permissionInfo.name;
String packageName = packageInfo.packageName;
+ UserHandle user = UserHandle.getUserHandleForUid(packageInfo.applicationInfo.uid);
int permissionFlags = mPackageManager.getPermissionFlags(permissionName,
packageName, mContext.getUser());
boolean isReviewRequired = (permissionFlags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
- if (isReviewRequired) {
+ if (isReviewRequired && !CompatChanges.isChangeEnabled(
+ NOTIFICATION_PERM_CHANGE_ID, packageName, user)) {
return;
}
@@ -953,6 +1001,33 @@ public final class PermissionPolicyService extends SystemService {
private class Internal extends PermissionPolicyInternal {
+ private ActivityInterceptorCallback mActivityInterceptorCallback =
+ new ActivityInterceptorCallback() {
+ @Nullable
+ @Override
+ public ActivityInterceptorCallback.ActivityInterceptResult intercept(
+ ActivityInterceptorInfo info) {
+ return null;
+ }
+
+ @Override
+ public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo) {
+ super.onActivityLaunched(taskInfo, activityInfo);
+ clearNotificationReviewFlagsIfNeeded(activityInfo.packageName,
+ UserHandle.of(taskInfo.userId));
+ showNotificationPromptIfNeeded(activityInfo.packageName,
+ taskInfo.userId, taskInfo.taskId);
+ }
+ };
+
+ private void onActivityManagerReady() {
+ ActivityTaskManagerInternal atm =
+ LocalServices.getService(ActivityTaskManagerInternal.class);
+ atm.registerActivityStartInterceptor(
+ ActivityInterceptorCallback.PERMISSION_POLICY_ORDERED_ID,
+ mActivityInterceptorCallback);
+ }
+
@Override
public boolean checkStartActivity(@NonNull Intent intent, int callingUid,
@Nullable String callingPackage) {
@@ -962,9 +1037,53 @@ public final class PermissionPolicyService extends SystemService {
+ callingPackage + " (uid=" + callingUid + ")");
return false;
}
+
+ if (PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(intent.getAction())
+ && (callingUid != Process.SYSTEM_UID || !SYSTEM_PKG.equals(callingPackage))) {
+ return false;
+ }
+
return true;
}
+ public void showNotificationPromptIfNeeded(@NonNull String packageName, int userId,
+ int taskId) {
+ UserHandle user = UserHandle.of(userId);
+ if (packageName == null || taskId == ActivityTaskManager.INVALID_TASK_ID
+ || !shouldForceShowNotificationPermissionRequest(packageName, user)) {
+ return;
+ }
+
+ launchNotificationPermissionRequestDialog(packageName, user, taskId);
+ }
+
+ private void clearNotificationReviewFlagsIfNeeded(String packageName, UserHandle userId) {
+ if (!CompatChanges.isChangeEnabled(NOTIFICATION_PERM_CHANGE_ID, packageName, userId)) {
+ return;
+ }
+ mPackageManager.updatePermissionFlags(POST_NOTIFICATIONS, packageName,
+ FLAG_PERMISSION_REVIEW_REQUIRED, 0, userId);
+ }
+
+ private void launchNotificationPermissionRequestDialog(String pkgName, UserHandle user,
+ int taskId) {
+ Intent grantPermission = mPackageManager
+ .buildRequestPermissionsIntent(new String[] { POST_NOTIFICATIONS });
+ grantPermission.setAction(
+ PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER);
+ grantPermission.putExtra(Intent.EXTRA_PACKAGE_NAME, pkgName);
+
+ ActivityOptions options = new ActivityOptions(new Bundle());
+ options.setTaskOverlay(true, false);
+ options.setLaunchTaskId(taskId);
+ try {
+ mContext.startActivityAsUser(grantPermission, options.toBundle(), user);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "couldn't start grant permission dialog"
+ + "for other package " + pkgName, e);
+ }
+ }
+
@Override
public boolean isInitialized(int userId) {
return isStarted(userId);
@@ -977,6 +1096,12 @@ public final class PermissionPolicyService extends SystemService {
}
}
+ @Override
+ public boolean canShowPermissionPromptForTask(@Nullable TaskInfo taskInfo) {
+ return taskInfo != null && taskInfo.isFocused && taskInfo.isVisible
+ && taskInfo.isRunning;
+ }
+
/**
* Check if the intent action is removed for the calling package (often based on target SDK
* version). If the action is removed, we'll silently cancel the activity launch.
@@ -1010,5 +1135,49 @@ public final class PermissionPolicyService extends SystemService {
return false;
}
}
+
+ private boolean shouldForceShowNotificationPermissionRequest(@NonNull String pkgName,
+ @NonNull UserHandle user) {
+ AndroidPackage pkg = mPackageManagerInternal.getPackage(pkgName);
+ if (pkg == null || pkg.getPackageName() == null
+ || Objects.equals(pkgName, mPackageManager.getPermissionControllerPackageName())
+ || pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
+ Slog.w(LOG_TAG, "Cannot check for Notification prompt, no package for "
+ + pkgName + " or pkg is Permission Controller");
+ return false;
+ }
+
+ synchronized (mLock) {
+ if (!mBootCompleted) {
+ return false;
+ }
+ }
+
+ try {
+ if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.NOTIFICATION_PERMISSION_ENABLED, UserHandle.USER_SYSTEM)
+ == 0) {
+ return false;
+ }
+ } catch (Settings.SettingNotFoundException e) {
+ return false;
+ }
+
+ if (!pkg.getRequestedPermissions().contains(POST_NOTIFICATIONS)
+ || CompatChanges.isChangeEnabled(NOTIFICATION_PERM_CHANGE_ID,
+ pkg.getPackageName(), user)) {
+ return false;
+ }
+
+ int uid = user.getUid(pkg.getUid());
+ if (mNotificationManager == null) {
+ mNotificationManager = LocalServices.getService(NotificationManagerInternal.class);
+ }
+ boolean hasCreatedNotificationChannels = mNotificationManager
+ .getNumNotificationChannelsForPackage(pkg.getPackageName(), uid, true) > 0;
+ boolean needsReview = (mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, pkgName,
+ user) & FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
+ return hasCreatedNotificationChannels && needsReview;
+ }
}
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 70a804b8135b..73ec2cd66ac1 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -545,7 +545,7 @@ public class Notifier {
/**
* Called when there has been user activity.
*/
- public void onUserActivity(int event, int uid) {
+ public void onUserActivity(int displayGroupId, int event, int uid) {
if (DEBUG) {
Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
}
@@ -560,7 +560,8 @@ public class Notifier {
if (!mUserActivityPending) {
mUserActivityPending = true;
Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
- msg.arg1 = event;
+ msg.arg1 = displayGroupId;
+ msg.arg2 = event;
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
@@ -633,14 +634,15 @@ public class Notifier {
/**
* Called when the screen policy changes.
*/
- public void onScreenPolicyUpdate(int newPolicy) {
+ public void onScreenPolicyUpdate(int displayGroupId, int newPolicy) {
if (DEBUG) {
Slog.d(TAG, "onScreenPolicyUpdate: newPolicy=" + newPolicy);
}
synchronized (mLock) {
Message msg = mHandler.obtainMessage(MSG_SCREEN_POLICY);
- msg.arg1 = newPolicy;
+ msg.arg1 = displayGroupId;
+ msg.arg2 = newPolicy;
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
@@ -675,7 +677,7 @@ public class Notifier {
mSuspendBlocker.release();
}
- private void sendUserActivity(int event) {
+ private void sendUserActivity(int displayGroupId, int event) {
synchronized (mLock) {
if (!mUserActivityPending) {
return;
@@ -686,7 +688,7 @@ public class Notifier {
tm.notifyUserActivity();
mPolicy.userActivity();
mFaceDownDetector.userActivity(event);
- mScreenUndimDetector.userActivity();
+ mScreenUndimDetector.userActivity(displayGroupId);
}
void postEnhancedDischargePredictionBroadcast(long delayMs) {
@@ -840,8 +842,8 @@ public class Notifier {
mSuspendBlocker.release();
}
- private void screenPolicyChanging(int screenPolicy) {
- mScreenUndimDetector.recordScreenPolicy(screenPolicy);
+ private void screenPolicyChanging(int displayGroupId, int screenPolicy) {
+ mScreenUndimDetector.recordScreenPolicy(displayGroupId, screenPolicy);
}
private void lockProfile(@UserIdInt int userId) {
@@ -866,7 +868,7 @@ public class Notifier {
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_USER_ACTIVITY:
- sendUserActivity(msg.arg1);
+ sendUserActivity(msg.arg1, msg.arg2);
break;
case MSG_BROADCAST:
sendNextBroadcast();
@@ -885,7 +887,7 @@ public class Notifier {
showWiredChargingStarted(msg.arg1);
break;
case MSG_SCREEN_POLICY:
- screenPolicyChanging(msg.arg1);
+ screenPolicyChanging(msg.arg1, msg.arg2);
break;
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 1455326b12f8..4b2770cef476 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -49,6 +49,7 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
+import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
@@ -60,6 +61,7 @@ import android.os.BatteryManagerInternal;
import android.os.BatterySaverPolicyConfig;
import android.os.Binder;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IPowerManager;
import android.os.Looper;
@@ -1151,6 +1153,9 @@ public final class PowerManagerService extends SystemService
PowerManager.GO_TO_SLEEP_REASON_QUIESCENT,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, Process.SYSTEM_UID);
}
+
+ mContext.getSystemService(DeviceStateManager.class).registerCallback(
+ new HandlerExecutor(mHandler), new DeviceStateListener());
}
}
}
@@ -1792,7 +1797,7 @@ public final class PowerManagerService extends SystemService
mLastInteractivePowerHintTime = eventTime;
}
- mNotifier.onUserActivity(event, uid);
+ mNotifier.onUserActivity(powerGroup.getGroupId(), event, uid);
mAttentionDetector.onUserActivity(eventTime, event);
if (mUserInactiveOverrideFromWindowManager) {
@@ -3372,7 +3377,7 @@ public final class PowerManagerService extends SystemService
final boolean ready = mDisplayManagerInternal.requestPowerState(groupId,
displayPowerRequest, mRequestWaitForNegativeProximity);
- mNotifier.onScreenPolicyUpdate(displayPowerRequest.policy);
+ mNotifier.onScreenPolicyUpdate(groupId, displayPowerRequest.policy);
if (DEBUG_SPEW) {
Slog.d(TAG, "updateDisplayPowerStateLocked: displayReady=" + ready
@@ -6349,4 +6354,25 @@ public final class PowerManagerService extends SystemService
return interceptPowerKeyDownInternal(event);
}
}
+
+ /**
+ * Listens to changes in device state and updates the interactivity time.
+ * Any changes to the device state are treated as user interactions.
+ */
+ class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
+ private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
+
+ @Override
+ public void onStateChanged(int deviceState) {
+ if (mDeviceState != deviceState) {
+ mDeviceState = deviceState;
+ // Device-state interactions are applied to the default display so that they
+ // are reflected only with the default power group.
+ userActivityInternal(Display.DEFAULT_DISPLAY, mClock.uptimeMillis(),
+ PowerManager.USER_ACTIVITY_EVENT_DEVICE_STATE, /* flags= */0,
+ Process.SYSTEM_UID);
+ }
+ }
+ };
+
}
diff --git a/services/core/java/com/android/server/power/ScreenUndimDetector.java b/services/core/java/com/android/server/power/ScreenUndimDetector.java
index 951bc1f76e6d..c4929c210e2c 100644
--- a/services/core/java/com/android/server/power/ScreenUndimDetector.java
+++ b/services/core/java/com/android/server/power/ScreenUndimDetector.java
@@ -28,6 +28,7 @@ import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.DeviceConfig;
import android.util.Slog;
+import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
@@ -123,8 +124,8 @@ public class ScreenUndimDetector {
* Launches a message that figures out the screen transitions and detects user undims. Must be
* called by the parent that is trying to update the screen policy.
*/
- public void recordScreenPolicy(int newPolicy) {
- if (newPolicy == mCurrentScreenPolicy) {
+ public void recordScreenPolicy(int displayGroupId, int newPolicy) {
+ if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP || newPolicy == mCurrentScreenPolicy) {
return;
}
@@ -268,7 +269,10 @@ public class ScreenUndimDetector {
* The user interacted with the screen after an undim, indicating the phone is in use.
* We use this event for logging.
*/
- public void userActivity() {
+ public void userActivity(int displayGroupId) {
+ if (displayGroupId != Display.DEFAULT_DISPLAY) {
+ return;
+ }
if (mUndimOccurredTime != 1 && mInteractionAfterUndimTime == -1) {
mInteractionAfterUndimTime = mClock.getCurrentTime();
}
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
index ef0079e0c01f..ca675973b2fd 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
@@ -35,7 +35,6 @@ import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
-
import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
import com.android.server.powerstats.ProtoStreamUtils.ChannelUtils;
import com.android.server.powerstats.ProtoStreamUtils.EnergyConsumerResultUtils;
@@ -313,12 +312,12 @@ public final class PowerStatsLogger extends Handler {
return mStartWallTime;
}
- public PowerStatsLogger(Context context, File dataStoragePath,
+ public PowerStatsLogger(Context context, Looper looper, File dataStoragePath,
String meterFilename, String meterCacheFilename,
String modelFilename, String modelCacheFilename,
String residencyFilename, String residencyCacheFilename,
IPowerStatsHALWrapper powerStatsHALWrapper) {
- super(Looper.getMainLooper());
+ super(looper);
mStartWallTime = currentTimeMillis() - SystemClock.elapsedRealtime();
if (DEBUG) Slog.d(TAG, "mStartWallTime: " + mStartWallTime);
mPowerStatsHALWrapper = powerStatsHALWrapper;
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java
index bb52c1dc1a29..9953ca8f9b65 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsService.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java
@@ -28,6 +28,7 @@ import android.os.Binder;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Looper;
import android.os.UserHandle;
import android.power.PowerStatsInternal;
import android.util.Slog;
@@ -79,6 +80,9 @@ public class PowerStatsService extends SystemService {
private StatsPullAtomCallbackImpl mPullAtomCallback;
@Nullable
private PowerStatsInternal mPowerStatsInternal;
+ @Nullable
+ @GuardedBy("this")
+ private Looper mLooper;
@VisibleForTesting
static class Injector {
@@ -127,12 +131,12 @@ public class PowerStatsService extends SystemService {
}
}
- PowerStatsLogger createPowerStatsLogger(Context context, File dataStoragePath,
- String meterFilename, String meterCacheFilename,
+ PowerStatsLogger createPowerStatsLogger(Context context, Looper looper,
+ File dataStoragePath, String meterFilename, String meterCacheFilename,
String modelFilename, String modelCacheFilename,
String residencyFilename, String residencyCacheFilename,
IPowerStatsHALWrapper powerStatsHALWrapper) {
- return new PowerStatsLogger(context, dataStoragePath,
+ return new PowerStatsLogger(context, looper, dataStoragePath,
meterFilename, meterCacheFilename,
modelFilename, modelCacheFilename,
residencyFilename, residencyCacheFilename,
@@ -229,11 +233,11 @@ public class PowerStatsService extends SystemService {
mDataStoragePath = mInjector.createDataStoragePath();
// Only start logger and triggers if initialization is successful.
- mPowerStatsLogger = mInjector.createPowerStatsLogger(mContext, mDataStoragePath,
- mInjector.createMeterFilename(), mInjector.createMeterCacheFilename(),
- mInjector.createModelFilename(), mInjector.createModelCacheFilename(),
- mInjector.createResidencyFilename(), mInjector.createResidencyCacheFilename(),
- getPowerStatsHal());
+ mPowerStatsLogger = mInjector.createPowerStatsLogger(mContext, getLooper(),
+ mDataStoragePath, mInjector.createMeterFilename(),
+ mInjector.createMeterCacheFilename(), mInjector.createModelFilename(),
+ mInjector.createModelCacheFilename(), mInjector.createResidencyFilename(),
+ mInjector.createResidencyCacheFilename(), getPowerStatsHal());
mBatteryTrigger = mInjector.createBatteryTrigger(mContext, mPowerStatsLogger);
mTimerTrigger = mInjector.createTimerTrigger(mContext, mPowerStatsLogger);
} else {
@@ -245,6 +249,17 @@ public class PowerStatsService extends SystemService {
return mInjector.getPowerStatsHALWrapperImpl();
}
+ private Looper getLooper() {
+ synchronized (this) {
+ if (mLooper == null) {
+ HandlerThread thread = new HandlerThread(TAG);
+ thread.start();
+ return thread.getLooper();
+ }
+ return mLooper;
+ }
+ }
+
public PowerStatsService(Context context) {
this(context, new Injector());
}
@@ -260,9 +275,7 @@ public class PowerStatsService extends SystemService {
private final Handler mHandler;
LocalService() {
- HandlerThread thread = new HandlerThread(TAG);
- thread.start();
- mHandler = new Handler(thread.getLooper());
+ mHandler = new Handler(getLooper());
}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index b1cc51768754..7f50cd6ddb4f 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -28,18 +28,11 @@ import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkIdentity.OEM_PAID;
import static android.net.NetworkIdentity.OEM_PRIVATE;
-import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
-import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_YES;
-import static android.net.NetworkStats.ROAMING_ALL;
import static android.net.NetworkTemplate.MATCH_ETHERNET;
-import static android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD;
-import static android.net.NetworkTemplate.MATCH_WIFI_WILDCARD;
-import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
+import static android.net.NetworkTemplate.MATCH_MOBILE;
+import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.OEM_MANAGED_ALL;
-import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
-import static android.net.NetworkTemplate.buildTemplateMobileWithRatType;
-import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
import static android.net.NetworkTemplate.getAllCollapsedRatTypes;
import static android.os.Debug.getIonHeapsSizeKb;
import static android.os.Process.LAST_SHARED_APPLICATION_GID;
@@ -1179,9 +1172,10 @@ public class StatsPullAtomService extends SystemService {
}
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: {
final NetworkStats wifiStats = getUidNetworkStatsSnapshotForTemplate(
- buildTemplateWifiWildcard(), /*includeTags=*/true);
+ new NetworkTemplate.Builder(MATCH_WIFI).build(), /*includeTags=*/true);
final NetworkStats cellularStats = getUidNetworkStatsSnapshotForTemplate(
- buildTemplateMobileWildcard(), /*includeTags=*/true);
+ new NetworkTemplate.Builder(MATCH_MOBILE)
+ .setMeteredness(METERED_YES).build(), /*includeTags=*/true);
if (wifiStats != null && cellularStats != null) {
final NetworkStats stats = wifiStats.add(cellularStats);
ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
@@ -1333,8 +1327,8 @@ public class StatsPullAtomService extends SystemService {
@NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForOemManaged() {
final List<Pair<Integer, Integer>> matchRulesAndTransports = List.of(
new Pair(MATCH_ETHERNET, TRANSPORT_ETHERNET),
- new Pair(MATCH_MOBILE_WILDCARD, TRANSPORT_CELLULAR),
- new Pair(MATCH_WIFI_WILDCARD, TRANSPORT_WIFI)
+ new Pair(MATCH_MOBILE, TRANSPORT_CELLULAR),
+ new Pair(MATCH_WIFI, TRANSPORT_WIFI)
);
final int[] oemManagedTypes = new int[] {OEM_PAID | OEM_PRIVATE, OEM_PAID, OEM_PRIVATE};
@@ -1343,12 +1337,11 @@ public class StatsPullAtomService extends SystemService {
for (Pair<Integer, Integer> ruleAndTransport : matchRulesAndTransports) {
final Integer matchRule = ruleAndTransport.first;
for (final int oemManaged : oemManagedTypes) {
- /* A null subscriberId will set wildcard=true, since we aren't trying to select a
- specific ssid or subscriber. */
- final NetworkTemplate template = new NetworkTemplate(matchRule,
- /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null,
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
- oemManaged);
+ // Subscriber Ids and Wifi Network Keys will not be set since the purpose is to
+ // slice statistics of different OEM managed networks among all network types.
+ // Thus, specifying networks through their identifiers are not needed.
+ final NetworkTemplate template = new NetworkTemplate.Builder(matchRule)
+ .setOemManaged(oemManaged).build();
final NetworkStats stats = getUidNetworkStatsSnapshotForTemplate(template, false);
final Integer transport = ruleAndTransport.second;
if (stats != null) {
@@ -1367,10 +1360,18 @@ public class StatsPullAtomService extends SystemService {
* Create a snapshot of NetworkStats for a given transport.
*/
@Nullable private NetworkStats getUidNetworkStatsSnapshotForTransport(int transport) {
- final NetworkTemplate template = (transport == TRANSPORT_CELLULAR)
- ? NetworkTemplate.buildTemplateMobileWithRatType(
- /*subscriptionId=*/null, NETWORK_TYPE_ALL, METERED_YES)
- : NetworkTemplate.buildTemplateWifiWildcard();
+ NetworkTemplate template = null;
+ switch (transport) {
+ case TRANSPORT_CELLULAR:
+ template = new NetworkTemplate.Builder(MATCH_MOBILE)
+ .setMeteredness(METERED_YES).build();
+ break;
+ case TRANSPORT_WIFI:
+ template = new NetworkTemplate.Builder(MATCH_WIFI).build();
+ break;
+ default:
+ Log.wtf(TAG, "Unexpected transport.");
+ }
return getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
}
@@ -1409,8 +1410,10 @@ public class StatsPullAtomService extends SystemService {
final List<NetworkStatsExt> ret = new ArrayList<>();
for (final int ratType : getAllCollapsedRatTypes()) {
final NetworkTemplate template =
- buildTemplateMobileWithRatType(subInfo.subscriberId, ratType,
- METERED_YES);
+ new NetworkTemplate.Builder(MATCH_MOBILE)
+ .setSubscriberIds(Set.of(subInfo.subscriberId))
+ .setRatType(ratType)
+ .setMeteredness(METERED_YES).build();
final NetworkStats stats =
getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
if (stats != null) {
diff --git a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
index e98fa28634a4..fe7416782262 100644
--- a/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
+++ b/services/core/java/com/android/server/textclassifier/TextClassificationManagerService.java
@@ -528,12 +528,13 @@ public final class TextClassificationManagerService extends ITextClassifierServi
callback.onFailure();
return;
}
- textClassifierServiceConsumer.accept(serviceState.mService);
+ consumeServiceNoExceptLocked(textClassifierServiceConsumer, serviceState.mService);
} else {
serviceState.mPendingRequests.add(
new PendingRequest(
methodName,
- () -> textClassifierServiceConsumer.accept(serviceState.mService),
+ () -> consumeServiceNoExceptLocked(
+ textClassifierServiceConsumer, serviceState.mService),
callback::onFailure, callback.asBinder(),
this,
serviceState,
@@ -542,6 +543,16 @@ public final class TextClassificationManagerService extends ITextClassifierServi
}
}
+ private static void consumeServiceNoExceptLocked(
+ @NonNull ThrowingConsumer<ITextClassifierService> textClassifierServiceConsumer,
+ @Nullable ITextClassifierService service) {
+ try {
+ textClassifierServiceConsumer.accept(service);
+ } catch (RuntimeException | Error e) {
+ Slog.e(LOG_TAG, "Exception when consume textClassifierService: " + e);
+ }
+ }
+
private static ITextClassifierCallback wrap(ITextClassifierCallback orig) {
return new CallbackWrapper(orig);
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 568e4b8de3ba..e066ca3e9dfc 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -69,6 +69,7 @@ import android.media.tv.TvInputManager;
import android.media.tv.TvInputService;
import android.media.tv.TvStreamConfig;
import android.media.tv.TvTrackInfo;
+import android.media.tv.tunerresourcemanager.TunerResourceManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -2538,6 +2539,31 @@ public final class TvInputManagerService extends SystemService {
}
@Override
+ public int getClientPriority(int useCase, String sessionId) {
+ final int callingPid = Binder.getCallingPid();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ int clientPid = TvInputManager.UNKNOWN_CLIENT_PID;
+ if (sessionId != null) {
+ synchronized (mLock) {
+ try {
+ clientPid = getClientPidLocked(sessionId);
+ } catch (ClientPidNotFoundException e) {
+ Slog.e(TAG, "error in getClientPriority", e);
+ }
+ }
+ } else {
+ clientPid = callingPid;
+ }
+ TunerResourceManager trm = (TunerResourceManager)
+ mContext.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE);
+ return trm.getClientPriority(useCase, clientPid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public List<TunedInfo> getCurrentTunedInfos(@UserIdInt int userId) {
if (mContext.checkCallingPermission(android.Manifest.permission.ACCESS_TUNED_INFO)
!= PackageManager.PERMISSION_GRANTED) {
@@ -2585,9 +2611,9 @@ public final class TvInputManagerService extends SystemService {
@GuardedBy("mLock")
private int getClientPidLocked(String sessionId)
- throws IllegalStateException {
+ throws ClientPidNotFoundException {
if (mSessionIdToSessionStateMap.get(sessionId) == null) {
- throw new IllegalStateException("Client Pid not found with sessionId "
+ throw new ClientPidNotFoundException("Client Pid not found with sessionId "
+ sessionId);
}
return mSessionIdToSessionStateMap.get(sessionId).callingPid;
diff --git a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
index a2bf2fe7df5e..a4732c1a0038 100644
--- a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
@@ -906,6 +906,94 @@ public class TvIAppManagerService extends SystemService {
}
@Override
+ public void notifyVideoAvailable(IBinder sessionToken, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
+ "notifyVideoAvailable");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
+ resolvedUserId);
+ getSessionLocked(sessionState).notifyVideoAvailable();
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in notifyVideoAvailable", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void notifyVideoUnavailable(IBinder sessionToken, int reason, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
+ "notifyVideoUnavailable");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
+ resolvedUserId);
+ getSessionLocked(sessionState).notifyVideoUnavailable(reason);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in notifyVideoUnavailable", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void notifyContentAllowed(IBinder sessionToken, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
+ "notifyContentAllowed");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
+ resolvedUserId);
+ getSessionLocked(sessionState).notifyContentAllowed();
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in notifyContentAllowed", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void notifyContentBlocked(IBinder sessionToken, String rating, int userId) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
+ "notifyContentBlocked");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ try {
+ SessionState sessionState = getSessionStateLocked(sessionToken, callingUid,
+ resolvedUserId);
+ getSessionLocked(sessionState).notifyContentBlocked(rating);
+ } catch (RemoteException | SessionNotFoundException e) {
+ Slogf.e(TAG, "error in notifyContentBlocked", e);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public void startIApp(IBinder sessionToken, int userId) {
if (DEBUG) {
Slogf.d(TAG, "BinderService#start(userId=%d)", userId);
diff --git a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
index 63f4c68b11f6..af705d597af2 100644
--- a/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
+++ b/services/core/java/com/android/server/tv/tunerresourcemanager/TunerResourceManagerService.java
@@ -289,6 +289,23 @@ public class TunerResourceManagerService extends SystemService implements IBinde
}
@Override
+ public boolean transferOwner(int resourceType, int currentOwnerId, int newOwnerId) {
+ enforceTunerAccessPermission("transferOwner");
+ enforceTrmAccessPermission("transferOwner");
+ synchronized (mLock) {
+ if (!checkClientExists(currentOwnerId)) {
+ Slog.e(TAG, "currentOwnerId:" + currentOwnerId + " does not exit");
+ return false;
+ }
+ if (!checkClientExists(newOwnerId)) {
+ Slog.e(TAG, "newOwnerId:" + newOwnerId + " does not exit");
+ return false;
+ }
+ return transferOwnerInternal(resourceType, currentOwnerId, newOwnerId);
+ }
+ }
+
+ @Override
public boolean requestDemux(@NonNull TunerDemuxRequest request,
@NonNull int[] demuxHandle) throws RemoteException {
enforceTunerAccessPermission("requestDemux");
@@ -388,7 +405,11 @@ public class TunerResourceManagerService extends SystemService implements IBinde
if (fe == null) {
throw new RemoteException("Releasing frontend does not exist.");
}
- if (fe.getOwnerClientId() != clientId) {
+ int ownerClientId = fe.getOwnerClientId();
+ ClientProfile ownerProfile = getClientProfile(ownerClientId);
+ if (ownerClientId != clientId
+ && (ownerProfile != null
+ && !ownerProfile.getShareFeClientIds().contains(clientId))) {
throw new RemoteException(
"Client is not the current owner of the releasing fe.");
}
@@ -619,6 +640,21 @@ public class TunerResourceManagerService extends SystemService implements IBinde
}
}
+ @Override
+ public int getClientPriority(int useCase, int pid) throws RemoteException {
+ enforceTrmAccessPermission("getClientPriority");
+ synchronized (mLock) {
+ return TunerResourceManagerService.this.getClientPriority(
+ useCase, checkIsForeground(pid));
+ }
+ }
+ @Override
+ public int getConfigPriority(int useCase, boolean isForeground) throws RemoteException {
+ enforceTrmAccessPermission("getConfigPriority");
+ synchronized (mLock) {
+ return TunerResourceManagerService.this.getClientPriority(useCase, isForeground);
+ }
+ }
}
/**
@@ -976,6 +1012,83 @@ public class TunerResourceManagerService extends SystemService implements IBinde
getClientProfile(targetClientId).shareFrontend(selfClientId);
}
+ private boolean transferFeOwner(int currentOwnerId, int newOwnerId) {
+ ClientProfile currentOwnerProfile = getClientProfile(currentOwnerId);
+ ClientProfile newOwnerProfile = getClientProfile(newOwnerId);
+ // change the owner of all the inUse frontend
+ newOwnerProfile.shareFrontend(currentOwnerId);
+ currentOwnerProfile.stopSharingFrontend(newOwnerId);
+ for (int inUseHandle : newOwnerProfile.getInUseFrontendHandles()) {
+ getFrontendResource(inUseHandle).setOwner(newOwnerId);
+ }
+ // double check there is no other resources tied to the previous owner
+ for (int inUseHandle : currentOwnerProfile.getInUseFrontendHandles()) {
+ int ownerId = getFrontendResource(inUseHandle).getOwnerClientId();
+ if (ownerId != newOwnerId) {
+ Slog.e(TAG, "something is wrong in transferFeOwner:" + inUseHandle
+ + ", " + ownerId + ", " + newOwnerId);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean transferFeCiCamOwner(int currentOwnerId, int newOwnerId) {
+ ClientProfile currentOwnerProfile = getClientProfile(currentOwnerId);
+ ClientProfile newOwnerProfile = getClientProfile(newOwnerId);
+
+ // link ciCamId to the new profile
+ int ciCamId = currentOwnerProfile.getInUseCiCamId();
+ newOwnerProfile.useCiCam(ciCamId);
+
+ // set the new owner Id
+ CiCamResource ciCam = getCiCamResource(ciCamId);
+ ciCam.setOwner(newOwnerId);
+
+ // unlink cicam resource from the original owner profile
+ currentOwnerProfile.releaseCiCam();
+ return true;
+ }
+
+ private boolean transferLnbOwner(int currentOwnerId, int newOwnerId) {
+ ClientProfile currentOwnerProfile = getClientProfile(currentOwnerId);
+ ClientProfile newOwnerProfile = getClientProfile(newOwnerId);
+
+ Set<Integer> inUseLnbHandles = new HashSet<>();
+ for (Integer lnbHandle : currentOwnerProfile.getInUseLnbHandles()) {
+ // link lnb handle to the new profile
+ newOwnerProfile.useLnb(lnbHandle);
+
+ // set new owner Id
+ LnbResource lnb = getLnbResource(lnbHandle);
+ lnb.setOwner(newOwnerId);
+
+ inUseLnbHandles.add(lnbHandle);
+ }
+
+ // unlink lnb handles from the original owner
+ for (Integer lnbHandle : inUseLnbHandles) {
+ currentOwnerProfile.releaseLnb(lnbHandle);
+ }
+
+ return true;
+ }
+
+ @VisibleForTesting
+ protected boolean transferOwnerInternal(int resourceType, int currentOwnerId, int newOwnerId) {
+ switch (resourceType) {
+ case TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND:
+ return transferFeOwner(currentOwnerId, newOwnerId);
+ case TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND_CICAM:
+ return transferFeCiCamOwner(currentOwnerId, newOwnerId);
+ case TunerResourceManager.TUNER_RESOURCE_TYPE_LNB:
+ return transferLnbOwner(currentOwnerId, newOwnerId);
+ default:
+ Slog.e(TAG, "transferOwnerInternal. unsupported resourceType: " + resourceType);
+ return false;
+ }
+ }
+
@VisibleForTesting
protected boolean requestLnbInternal(TunerLnbRequest request, int[] lnbHandle) {
if (DEBUG) {
diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
index bd8d13b87125..6db25b7ed583 100644
--- a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
+++ b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
@@ -20,6 +20,8 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_ANY;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
@@ -44,7 +46,7 @@ import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.VcnContext;
-import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Set;
/** @hide */
@@ -76,7 +78,7 @@ class NetworkPriorityClassifier {
public static int calculatePriorityClass(
VcnContext vcnContext,
UnderlyingNetworkRecord networkRecord,
- LinkedHashSet<VcnUnderlyingNetworkTemplate> underlyingNetworkPriorities,
+ List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
ParcelUuid subscriptionGroup,
TelephonySubscriptionSnapshot snapshot,
UnderlyingNetworkRecord currentlySelected,
@@ -94,7 +96,7 @@ class NetworkPriorityClassifier {
}
int priorityIndex = 0;
- for (VcnUnderlyingNetworkTemplate nwPriority : underlyingNetworkPriorities) {
+ for (VcnUnderlyingNetworkTemplate nwPriority : underlyingNetworkTemplates) {
if (checkMatchesPriorityRule(
vcnContext,
nwPriority,
@@ -122,7 +124,11 @@ class NetworkPriorityClassifier {
// TODO: Check Network Quality reported by metric monitors/probers.
final NetworkCapabilities caps = networkRecord.networkCapabilities;
- if (!networkPriority.allowMetered() && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)) {
+
+ final int meteredMatch = networkPriority.getMetered();
+ final boolean isMetered = !caps.hasCapability(NET_CAPABILITY_NOT_METERED);
+ if (meteredMatch == MATCH_REQUIRED && !isMetered
+ || meteredMatch == MATCH_FORBIDDEN && isMetered) {
return false;
}
@@ -171,7 +177,8 @@ class NetworkPriorityClassifier {
return false;
}
- if (networkPriority.getSsid() != null && networkPriority.getSsid() != caps.getSsid()) {
+ if (!networkPriority.getSsids().isEmpty()
+ && !networkPriority.getSsids().contains(caps.getSsid())) {
return false;
}
@@ -226,26 +233,31 @@ class NetworkPriorityClassifier {
.getSystemService(TelephonyManager.class)
.createForSubscriptionId(subId);
- if (!networkPriority.getAllowedOperatorPlmnIds().isEmpty()) {
+ if (!networkPriority.getOperatorPlmnIds().isEmpty()) {
final String plmnId = subIdSpecificTelephonyMgr.getNetworkOperator();
- if (!networkPriority.getAllowedOperatorPlmnIds().contains(plmnId)) {
+ if (!networkPriority.getOperatorPlmnIds().contains(plmnId)) {
return false;
}
}
- if (!networkPriority.getAllowedSpecificCarrierIds().isEmpty()) {
+ if (!networkPriority.getSimSpecificCarrierIds().isEmpty()) {
final int carrierId = subIdSpecificTelephonyMgr.getSimSpecificCarrierId();
- if (!networkPriority.getAllowedSpecificCarrierIds().contains(carrierId)) {
+ if (!networkPriority.getSimSpecificCarrierIds().contains(carrierId)) {
return false;
}
}
- if (!networkPriority.allowRoaming() && !caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)) {
+ final int roamingMatch = networkPriority.getRoaming();
+ final boolean isRoaming = !caps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+ if (roamingMatch == MATCH_REQUIRED && !isRoaming
+ || roamingMatch == MATCH_FORBIDDEN && isRoaming) {
return false;
}
- if (networkPriority.requireOpportunistic()) {
- if (!isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+ final int opportunisticMatch = networkPriority.getOpportunistic();
+ final boolean isOpportunistic = isOpportunistic(snapshot, caps.getSubscriptionIds());
+ if (opportunisticMatch == MATCH_REQUIRED) {
+ if (!isOpportunistic) {
return false;
}
@@ -265,6 +277,8 @@ class NetworkPriorityClassifier {
.contains(SubscriptionManager.getActiveDataSubscriptionId())) {
return false;
}
+ } else if (opportunisticMatch == MATCH_FORBIDDEN && !isOpportunistic) {
+ return false;
}
return true;
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
index df2f0d58565e..c0488b18cb65 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
@@ -32,7 +32,7 @@ import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscription
import com.android.server.vcn.VcnContext;
import java.util.Comparator;
-import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Objects;
/**
@@ -77,7 +77,7 @@ public class UnderlyingNetworkRecord {
static Comparator<UnderlyingNetworkRecord> getComparator(
VcnContext vcnContext,
- LinkedHashSet<VcnUnderlyingNetworkTemplate> underlyingNetworkPriorities,
+ List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
ParcelUuid subscriptionGroup,
TelephonySubscriptionSnapshot snapshot,
UnderlyingNetworkRecord currentlySelected,
@@ -87,7 +87,7 @@ public class UnderlyingNetworkRecord {
NetworkPriorityClassifier.calculatePriorityClass(
vcnContext,
left,
- underlyingNetworkPriorities,
+ underlyingNetworkTemplates,
subscriptionGroup,
snapshot,
currentlySelected,
@@ -96,7 +96,7 @@ public class UnderlyingNetworkRecord {
NetworkPriorityClassifier.calculatePriorityClass(
vcnContext,
right,
- underlyingNetworkPriorities,
+ underlyingNetworkTemplates,
subscriptionGroup,
snapshot,
currentlySelected,
@@ -133,7 +133,7 @@ public class UnderlyingNetworkRecord {
void dump(
VcnContext vcnContext,
IndentingPrintWriter pw,
- LinkedHashSet<VcnUnderlyingNetworkTemplate> underlyingNetworkPriorities,
+ List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
ParcelUuid subscriptionGroup,
TelephonySubscriptionSnapshot snapshot,
UnderlyingNetworkRecord currentlySelected,
@@ -145,7 +145,7 @@ public class UnderlyingNetworkRecord {
NetworkPriorityClassifier.calculatePriorityClass(
vcnContext,
this,
- underlyingNetworkPriorities,
+ underlyingNetworkTemplates,
subscriptionGroup,
snapshot,
currentlySelected,
diff --git a/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java
index 0690d3be3db1..8189e74f922c 100644
--- a/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java
+++ b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java
@@ -21,18 +21,16 @@ import android.os.vibrator.RampSegment;
import android.os.vibrator.StepSegment;
import android.os.vibrator.VibrationEffectSegment;
import android.util.MathUtils;
+import android.util.Range;
import java.util.List;
/**
- * Adapter that clips frequency values to {@link VibratorInfo#getFrequencyRange()} and
+ * Adapter that clips frequency values to {@link VibratorInfo#getFrequencyRangeHz()} and
* amplitude values to respective {@link VibratorInfo#getMaxAmplitude}.
*
- * <p>Devices with no frequency control will collapse all frequencies to zero and leave
- * amplitudes unchanged.
- *
- * <p>The frequency value returned in segments will be absolute, converted with
- * {@link VibratorInfo#getAbsoluteFrequency(float)}.
+ * <p>Devices with no frequency control will collapse all frequencies to the resonant frequency and
+ * leave amplitudes unchanged.
*/
final class ClippingAmplitudeAndFrequencyAdapter
implements VibrationEffectAdapters.SegmentsAdapter<VibratorInfo> {
@@ -52,29 +50,39 @@ final class ClippingAmplitudeAndFrequencyAdapter
}
private StepSegment apply(StepSegment segment, VibratorInfo info) {
- float clampedFrequency = clampFrequency(info, segment.getFrequency());
+ float clampedFrequency = clampFrequency(info, segment.getFrequencyHz());
return new StepSegment(
clampAmplitude(info, clampedFrequency, segment.getAmplitude()),
- info.getAbsoluteFrequency(clampedFrequency),
+ clampedFrequency,
(int) segment.getDuration());
}
private RampSegment apply(RampSegment segment, VibratorInfo info) {
- float clampedStartFrequency = clampFrequency(info, segment.getStartFrequency());
- float clampedEndFrequency = clampFrequency(info, segment.getEndFrequency());
+ float clampedStartFrequency = clampFrequency(info, segment.getStartFrequencyHz());
+ float clampedEndFrequency = clampFrequency(info, segment.getEndFrequencyHz());
return new RampSegment(
clampAmplitude(info, clampedStartFrequency, segment.getStartAmplitude()),
clampAmplitude(info, clampedEndFrequency, segment.getEndAmplitude()),
- info.getAbsoluteFrequency(clampedStartFrequency),
- info.getAbsoluteFrequency(clampedEndFrequency),
+ clampedStartFrequency,
+ clampedEndFrequency,
(int) segment.getDuration());
}
- private float clampFrequency(VibratorInfo info, float frequency) {
- return info.getFrequencyRange().clamp(frequency);
+ private float clampFrequency(VibratorInfo info, float frequencyHz) {
+ Range<Float> frequencyRangeHz = info.getFrequencyRangeHz();
+ if (frequencyHz == 0 || frequencyRangeHz == null) {
+ return info.getResonantFrequency();
+ }
+ return frequencyRangeHz.clamp(frequencyHz);
}
- private float clampAmplitude(VibratorInfo info, float frequency, float amplitude) {
- return MathUtils.min(amplitude, info.getMaxAmplitude(frequency));
+ private float clampAmplitude(VibratorInfo info, float frequencyHz, float amplitude) {
+ Range<Float> frequencyRangeHz = info.getFrequencyRangeHz();
+ if (frequencyRangeHz == null) {
+ // No frequency range was specified, leave amplitude unchanged, the frequency will be
+ // clamped to the device's resonant frequency.
+ return amplitude;
+ }
+ return MathUtils.min(amplitude, info.getMaxAmplitude(frequencyHz));
}
}
diff --git a/services/core/java/com/android/server/vibrator/RampDownAdapter.java b/services/core/java/com/android/server/vibrator/RampDownAdapter.java
index e97ed4ce6e7c..8fec162bb587 100644
--- a/services/core/java/com/android/server/vibrator/RampDownAdapter.java
+++ b/services/core/java/com/android/server/vibrator/RampDownAdapter.java
@@ -90,13 +90,13 @@ final class RampDownAdapter implements VibrationEffectAdapters.SegmentsAdapter<V
if (previousSegment instanceof StepSegment) {
float previousAmplitude = ((StepSegment) previousSegment).getAmplitude();
- float previousFrequency = ((StepSegment) previousSegment).getFrequency();
+ float previousFrequency = ((StepSegment) previousSegment).getFrequencyHz();
replacementSegments =
createStepsDown(previousAmplitude, previousFrequency, offDuration);
} else if (previousSegment instanceof RampSegment) {
float previousAmplitude = ((RampSegment) previousSegment).getEndAmplitude();
- float previousFrequency = ((RampSegment) previousSegment).getEndFrequency();
+ float previousFrequency = ((RampSegment) previousSegment).getEndFrequencyHz();
if (offDuration <= mRampDownDuration) {
// Replace the zero amplitude segment with a ramp down of same duration, to
@@ -177,12 +177,12 @@ final class RampDownAdapter implements VibrationEffectAdapters.SegmentsAdapter<V
repeatIndex++;
if (lastSegment instanceof StepSegment) {
float previousAmplitude = ((StepSegment) lastSegment).getAmplitude();
- float previousFrequency = ((StepSegment) lastSegment).getFrequency();
+ float previousFrequency = ((StepSegment) lastSegment).getFrequencyHz();
segments.addAll(createStepsDown(previousAmplitude, previousFrequency,
Math.min(offDuration, mRampDownDuration)));
} else if (lastSegment instanceof RampSegment) {
float previousAmplitude = ((RampSegment) lastSegment).getEndAmplitude();
- float previousFrequency = ((RampSegment) lastSegment).getEndFrequency();
+ float previousFrequency = ((RampSegment) lastSegment).getEndFrequencyHz();
segments.add(createRampDown(previousAmplitude, previousFrequency,
Math.min(offDuration, mRampDownDuration)));
}
@@ -214,10 +214,10 @@ final class RampDownAdapter implements VibrationEffectAdapters.SegmentsAdapter<V
if (segment instanceof RampSegment) {
RampSegment ramp = (RampSegment) segment;
return new RampSegment(ramp.getStartAmplitude(), ramp.getEndAmplitude(),
- ramp.getStartFrequency(), ramp.getEndFrequency(), (int) newDuration);
+ ramp.getStartFrequencyHz(), ramp.getEndFrequencyHz(), (int) newDuration);
} else if (segment instanceof StepSegment) {
StepSegment step = (StepSegment) segment;
- return new StepSegment(step.getAmplitude(), step.getFrequency(), (int) newDuration);
+ return new StepSegment(step.getAmplitude(), step.getFrequencyHz(), (int) newDuration);
}
return segment;
}
diff --git a/services/core/java/com/android/server/vibrator/RampToStepAdapter.java b/services/core/java/com/android/server/vibrator/RampToStepAdapter.java
index 64624a28c5da..c592a7072407 100644
--- a/services/core/java/com/android/server/vibrator/RampToStepAdapter.java
+++ b/services/core/java/com/android/server/vibrator/RampToStepAdapter.java
@@ -21,6 +21,7 @@ import android.os.VibratorInfo;
import android.os.vibrator.RampSegment;
import android.os.vibrator.StepSegment;
import android.os.vibrator.VibrationEffectSegment;
+import android.util.MathUtils;
import java.util.ArrayList;
import java.util.Arrays;
@@ -52,7 +53,7 @@ final class RampToStepAdapter implements VibrationEffectAdapters.SegmentsAdapter
if (!(segment instanceof RampSegment)) {
continue;
}
- List<StepSegment> steps = apply((RampSegment) segment);
+ List<StepSegment> steps = apply(info, (RampSegment) segment);
segments.remove(i);
segments.addAll(i, steps);
int addedSegments = steps.size() - 1;
@@ -65,11 +66,12 @@ final class RampToStepAdapter implements VibrationEffectAdapters.SegmentsAdapter
return repeatIndex;
}
- private List<StepSegment> apply(RampSegment ramp) {
+ private List<StepSegment> apply(VibratorInfo info, RampSegment ramp) {
if (Float.compare(ramp.getStartAmplitude(), ramp.getEndAmplitude()) == 0) {
// Amplitude is the same, so return a single step to simulate this ramp.
return Arrays.asList(
- new StepSegment(ramp.getStartAmplitude(), ramp.getStartFrequency(),
+ new StepSegment(ramp.getStartAmplitude(),
+ fillEmptyFrequency(info, ramp.getStartFrequencyHz()),
(int) ramp.getDuration()));
}
@@ -77,17 +79,21 @@ final class RampToStepAdapter implements VibrationEffectAdapters.SegmentsAdapter
int stepCount = (int) (ramp.getDuration() + mStepDuration - 1) / mStepDuration;
for (int i = 0; i < stepCount - 1; i++) {
float pos = (float) i / stepCount;
+ // Fill zero frequency values with the device resonant frequency before interpolating.
+ float startFrequencyHz = fillEmptyFrequency(info, ramp.getStartFrequencyHz());
+ float endFrequencyHz = fillEmptyFrequency(info, ramp.getEndFrequencyHz());
steps.add(new StepSegment(
- interpolate(ramp.getStartAmplitude(), ramp.getEndAmplitude(), pos),
- interpolate(ramp.getStartFrequency(), ramp.getEndFrequency(), pos),
+ MathUtils.lerp(ramp.getStartAmplitude(), ramp.getEndAmplitude(), pos),
+ MathUtils.lerp(startFrequencyHz, endFrequencyHz, pos),
mStepDuration));
}
int duration = (int) ramp.getDuration() - mStepDuration * (stepCount - 1);
- steps.add(new StepSegment(ramp.getEndAmplitude(), ramp.getEndFrequency(), duration));
+ float endFrequencyHz = fillEmptyFrequency(info, ramp.getEndFrequencyHz());
+ steps.add(new StepSegment(ramp.getEndAmplitude(), endFrequencyHz, duration));
return steps;
}
- private static float interpolate(float start, float end, float position) {
- return start + position * (end - start);
+ private static float fillEmptyFrequency(VibratorInfo info, float frequencyHz) {
+ return frequencyHz == 0 ? info.getResonantFrequency() : frequencyHz;
}
}
diff --git a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java
index 6f5adac33ae6..5ace3896f387 100644
--- a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java
+++ b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java
@@ -21,6 +21,7 @@ import android.os.VibratorInfo;
import android.os.vibrator.RampSegment;
import android.os.vibrator.StepSegment;
import android.os.vibrator.VibrationEffectSegment;
+import android.util.MathUtils;
import java.util.ArrayList;
import java.util.List;
@@ -41,18 +42,18 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter
// The vibrator does not have PWLE capability, so keep the segments unchanged.
return repeatIndex;
}
- convertStepsToRamps(segments);
+ convertStepsToRamps(info, segments);
repeatIndex = splitLongRampSegments(info, segments, repeatIndex);
return repeatIndex;
}
- private void convertStepsToRamps(List<VibrationEffectSegment> segments) {
+ private void convertStepsToRamps(VibratorInfo info, List<VibrationEffectSegment> segments) {
int segmentCount = segments.size();
// Convert steps that require frequency control to ramps.
for (int i = 0; i < segmentCount; i++) {
VibrationEffectSegment segment = segments.get(i);
- if (isStep(segment) && ((StepSegment) segment).getFrequency() != 0) {
- segments.set(i, convertStepToRamp((StepSegment) segment));
+ if (isStep(segment) && ((StepSegment) segment).getFrequencyHz() != 0) {
+ segments.set(i, convertStepToRamp(info, (StepSegment) segment));
}
}
// Convert steps that are next to ramps to also become ramps, so they can be composed
@@ -60,10 +61,10 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter
for (int i = 0; i < segmentCount; i++) {
if (segments.get(i) instanceof RampSegment) {
for (int j = i - 1; j >= 0 && isStep(segments.get(j)); j--) {
- segments.set(j, convertStepToRamp((StepSegment) segments.get(j)));
+ segments.set(j, convertStepToRamp(info, (StepSegment) segments.get(j)));
}
for (int j = i + 1; j < segmentCount && isStep(segments.get(j)); j++) {
- segments.set(j, convertStepToRamp((StepSegment) segments.get(j)));
+ segments.set(j, convertStepToRamp(info, (StepSegment) segments.get(j)));
}
}
}
@@ -92,7 +93,7 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter
continue;
}
segments.remove(i);
- segments.addAll(i, splitRampSegment(ramp, splits));
+ segments.addAll(i, splitRampSegment(info, ramp, splits));
int addedSegments = splits - 1;
if (repeatIndex > i) {
repeatIndex += addedSegments;
@@ -104,31 +105,40 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter
return repeatIndex;
}
- private static RampSegment convertStepToRamp(StepSegment segment) {
+ private static RampSegment convertStepToRamp(VibratorInfo info, StepSegment segment) {
+ float frequencyHz = fillEmptyFrequency(info, segment.getFrequencyHz());
return new RampSegment(segment.getAmplitude(), segment.getAmplitude(),
- segment.getFrequency(), segment.getFrequency(), (int) segment.getDuration());
+ frequencyHz, frequencyHz, (int) segment.getDuration());
}
- private static List<RampSegment> splitRampSegment(RampSegment ramp, int splits) {
+ private static List<RampSegment> splitRampSegment(VibratorInfo info, RampSegment ramp,
+ int splits) {
List<RampSegment> ramps = new ArrayList<>(splits);
+ float startFrequencyHz = fillEmptyFrequency(info, ramp.getStartFrequencyHz());
+ float endFrequencyHz = fillEmptyFrequency(info, ramp.getEndFrequencyHz());
long splitDuration = ramp.getDuration() / splits;
float previousAmplitude = ramp.getStartAmplitude();
- float previousFrequency = ramp.getStartFrequency();
+ float previousFrequency = startFrequencyHz;
long accumulatedDuration = 0;
for (int i = 1; i < splits; i++) {
accumulatedDuration += splitDuration;
+ float durationRatio = (float) accumulatedDuration / ramp.getDuration();
+ float interpolatedFrequency =
+ MathUtils.lerp(startFrequencyHz, endFrequencyHz, durationRatio);
+ float interpolatedAmplitude =
+ MathUtils.lerp(ramp.getStartAmplitude(), ramp.getEndAmplitude(), durationRatio);
RampSegment rampSplit = new RampSegment(
- previousAmplitude, interpolateAmplitude(ramp, accumulatedDuration),
- previousFrequency, interpolateFrequency(ramp, accumulatedDuration),
+ previousAmplitude, interpolatedAmplitude,
+ previousFrequency, interpolatedFrequency,
(int) splitDuration);
ramps.add(rampSplit);
previousAmplitude = rampSplit.getEndAmplitude();
- previousFrequency = rampSplit.getEndFrequency();
+ previousFrequency = rampSplit.getEndFrequencyHz();
}
ramps.add(new RampSegment(previousAmplitude, ramp.getEndAmplitude(), previousFrequency,
- ramp.getEndFrequency(), (int) (ramp.getDuration() - accumulatedDuration)));
+ endFrequencyHz, (int) (ramp.getDuration() - accumulatedDuration)));
return ramps;
}
@@ -137,18 +147,7 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter
return segment instanceof StepSegment;
}
- private static float interpolateAmplitude(RampSegment ramp, long duration) {
- return interpolate(ramp.getStartAmplitude(), ramp.getEndAmplitude(), duration,
- ramp.getDuration());
- }
-
- private static float interpolateFrequency(RampSegment ramp, long duration) {
- return interpolate(ramp.getStartFrequency(), ramp.getEndFrequency(), duration,
- ramp.getDuration());
- }
-
- private static float interpolate(float start, float end, long duration, long totalDuration) {
- float position = (float) duration / totalDuration;
- return start + position * (end - start);
+ private static float fillEmptyFrequency(VibratorInfo info, float frequencyHz) {
+ return frequencyHz == 0 ? info.getResonantFrequency() : frequencyHz;
}
}
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index 1d6e1585872d..0c15ee723dd3 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -373,7 +373,7 @@ final class Vibration {
final long token = proto.start(fieldId);
proto.write(StepSegmentProto.DURATION, segment.getDuration());
proto.write(StepSegmentProto.AMPLITUDE, segment.getAmplitude());
- proto.write(StepSegmentProto.FREQUENCY, segment.getFrequency());
+ proto.write(StepSegmentProto.FREQUENCY, segment.getFrequencyHz());
proto.end(token);
}
@@ -382,8 +382,8 @@ final class Vibration {
proto.write(RampSegmentProto.DURATION, segment.getDuration());
proto.write(RampSegmentProto.START_AMPLITUDE, segment.getStartAmplitude());
proto.write(RampSegmentProto.END_AMPLITUDE, segment.getEndAmplitude());
- proto.write(RampSegmentProto.START_FREQUENCY, segment.getStartFrequency());
- proto.write(RampSegmentProto.END_FREQUENCY, segment.getEndFrequency());
+ proto.write(RampSegmentProto.START_FREQUENCY, segment.getStartFrequencyHz());
+ proto.write(RampSegmentProto.END_FREQUENCY, segment.getEndFrequencyHz());
proto.end(token);
}
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index 1ee115dd28f2..df6ffa2bd009 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -16,13 +16,16 @@
package com.android.server.vibrator;
+import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY;
import static android.os.VibrationAttributes.USAGE_ALARM;
import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
+import static android.os.VibrationAttributes.USAGE_MEDIA;
import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION;
import static android.os.VibrationAttributes.USAGE_RINGTONE;
import static android.os.VibrationAttributes.USAGE_TOUCH;
+import static android.os.VibrationAttributes.USAGE_UNKNOWN;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -44,8 +47,11 @@ import android.os.UserHandle;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
+import android.os.Vibrator.VibrationIntensity;
+import android.os.vibrator.VibrationConfig;
import android.provider.Settings;
import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -109,53 +115,31 @@ final class VibrationSettings {
private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>();
private final SparseArray<VibrationEffect> mFallbackEffects;
- private final int mRampStepDuration;
- private final int mRampDownDuration;
+ private final VibrationConfig mVibrationConfig;
@GuardedBy("mLock")
@Nullable
- private Vibrator mVibrator;
- @GuardedBy("mLock")
- @Nullable
private AudioManager mAudioManager;
@GuardedBy("mLock")
private boolean mVibrateInputDevices;
@GuardedBy("mLock")
- private boolean mVibrateWhenRinging;
- @GuardedBy("mLock")
- private boolean mApplyRampingRinger;
- @GuardedBy("mLock")
- private int mHapticFeedbackIntensity;
- @GuardedBy("mLock")
- private int mHardwareFeedbackIntensity;
- @GuardedBy("mLock")
- private int mNotificationIntensity;
- @GuardedBy("mLock")
- private int mRingIntensity;
+ private SparseIntArray mCurrentVibrationIntensities = new SparseIntArray();
@GuardedBy("mLock")
private boolean mBatterySaverMode;
VibrationSettings(Context context, Handler handler) {
- this(context, handler,
- context.getResources().getInteger(
- com.android.internal.R.integer.config_vibrationWaveformRampDownDuration),
- context.getResources().getInteger(
- com.android.internal.R.integer.config_vibrationWaveformRampStepDuration));
+ this(context, handler, new VibrationConfig(context.getResources()));
}
@VisibleForTesting
- VibrationSettings(Context context, Handler handler, int rampDownDuration,
- int rampStepDuration) {
+ VibrationSettings(Context context, Handler handler, VibrationConfig config) {
mContext = context;
+ mVibrationConfig = config;
mSettingObserver = new SettingsObserver(handler);
mUidObserver = new UidObserver();
mUserReceiver = new UserObserver();
- // TODO(b/191150049): move these to vibrator static config file
- mRampDownDuration = rampDownDuration;
- mRampStepDuration = rampStepDuration;
-
VibrationEffect clickEffect = createEffectFromResource(
com.android.internal.R.array.config_virtualKeyVibePattern);
VibrationEffect doubleClickEffect = createEffectFromResource(
@@ -179,7 +163,6 @@ final class VibrationSettings {
public void onSystemReady() {
synchronized (mLock) {
- mVibrator = mContext.getSystemService(Vibrator.class);
mAudioManager = mContext.getSystemService(AudioManager.class);
}
try {
@@ -214,12 +197,21 @@ final class VibrationSettings {
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiver(mUserReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
+ // Listen to all settings that might affect the result of Vibrator.getVibrationIntensity.
registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES));
registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING));
registerSettingsObserver(Settings.System.getUriFor(Settings.System.APPLY_RAMPING_RINGER));
+ registerSettingsObserver(Settings.System.getUriFor(
+ Settings.System.HAPTIC_FEEDBACK_ENABLED));
+ registerSettingsObserver(
+ Settings.System.getUriFor(Settings.System.ALARM_VIBRATION_INTENSITY));
registerSettingsObserver(
Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_INTENSITY));
registerSettingsObserver(
+ Settings.System.getUriFor(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY));
+ registerSettingsObserver(
+ Settings.System.getUriFor(Settings.System.MEDIA_VIBRATION_INTENSITY));
+ registerSettingsObserver(
Settings.System.getUriFor(Settings.System.NOTIFICATION_VIBRATION_INTENSITY));
registerSettingsObserver(
Settings.System.getUriFor(Settings.System.RING_VIBRATION_INTENSITY));
@@ -253,7 +245,7 @@ final class VibrationSettings {
* devices without PWLE support.
*/
public int getRampStepDuration() {
- return mRampStepDuration;
+ return mVibrationConfig.getRampStepDurationMs();
}
/**
@@ -261,7 +253,7 @@ final class VibrationSettings {
* when a vibration is cancelled or finished at non-zero amplitude.
*/
public int getRampDownDuration() {
- return mRampDownDuration;
+ return mVibrationConfig.getRampDownDurationMs();
}
/**
@@ -270,25 +262,8 @@ final class VibrationSettings {
* @param usageHint one of VibrationAttributes.USAGE_*
* @return The vibration intensity, one of Vibrator.VIBRATION_INTENSITY_*
*/
- public int getDefaultIntensity(int usageHint) {
- if (usageHint == USAGE_ALARM) {
- return Vibrator.VIBRATION_INTENSITY_HIGH;
- }
- synchronized (mLock) {
- if (mVibrator != null) {
- switch (usageHint) {
- case USAGE_RINGTONE:
- return mVibrator.getDefaultRingVibrationIntensity();
- case USAGE_NOTIFICATION:
- return mVibrator.getDefaultNotificationVibrationIntensity();
- case USAGE_TOUCH:
- case USAGE_HARDWARE_FEEDBACK:
- case USAGE_PHYSICAL_EMULATION:
- return mVibrator.getDefaultHapticFeedbackIntensity();
- }
- }
- }
- return Vibrator.VIBRATION_INTENSITY_MEDIUM;
+ public int getDefaultIntensity(@VibrationAttributes.Usage int usageHint) {
+ return mVibrationConfig.getDefaultVibrationIntensity(usageHint);
}
/**
@@ -297,23 +272,10 @@ final class VibrationSettings {
* @param usageHint one of VibrationAttributes.USAGE_*
* @return The vibration intensity, one of Vibrator.VIBRATION_INTENSITY_*
*/
- public int getCurrentIntensity(int usageHint) {
+ public int getCurrentIntensity(@VibrationAttributes.Usage int usageHint) {
+ int defaultIntensity = getDefaultIntensity(usageHint);
synchronized (mLock) {
- switch (usageHint) {
- case USAGE_RINGTONE:
- return mRingIntensity;
- case USAGE_NOTIFICATION:
- return mNotificationIntensity;
- case USAGE_TOUCH:
- return mHapticFeedbackIntensity;
- case USAGE_HARDWARE_FEEDBACK:
- case USAGE_PHYSICAL_EMULATION:
- return mHardwareFeedbackIntensity;
- case USAGE_ALARM:
- return Vibrator.VIBRATION_INTENSITY_HIGH;
- default:
- return Vibrator.VIBRATION_INTENSITY_MEDIUM;
- }
+ return mCurrentVibrationIntensities.get(usageHint, defaultIntensity);
}
}
@@ -371,7 +333,7 @@ final class VibrationSettings {
* for touch and ringtone usages only. All other usages are allowed by this method.
*/
@GuardedBy("mLock")
- private boolean shouldVibrateForRingerModeLocked(int usageHint) {
+ private boolean shouldVibrateForRingerModeLocked(@VibrationAttributes.Usage int usageHint) {
// If audio manager was not loaded yet then assume most restrictive mode.
int ringerMode = (mAudioManager == null)
? AudioManager.RINGER_MODE_SILENT
@@ -379,18 +341,9 @@ final class VibrationSettings {
switch (usageHint) {
case USAGE_TOUCH:
- // Touch feedback disabled when phone is on silent mode.
- return ringerMode != AudioManager.RINGER_MODE_SILENT;
case USAGE_RINGTONE:
- switch (ringerMode) {
- case AudioManager.RINGER_MODE_SILENT:
- return false;
- case AudioManager.RINGER_MODE_VIBRATE:
- return true;
- default:
- // Ringtone vibrations also depend on 2 other settings:
- return mVibrateWhenRinging || mApplyRampingRinger;
- }
+ // Touch feedback and ringtone disabled when phone is on silent mode.
+ return ringerMode != AudioManager.RINGER_MODE_SILENT;
default:
// All other usages ignore ringer mode settings.
return true;
@@ -401,64 +354,89 @@ final class VibrationSettings {
@VisibleForTesting
void updateSettings() {
synchronized (mLock) {
- mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
- mApplyRampingRinger = getSystemSetting(Settings.System.APPLY_RAMPING_RINGER, 0) != 0;
- mHapticFeedbackIntensity = getSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- getDefaultIntensity(USAGE_TOUCH));
- mHardwareFeedbackIntensity = getSystemSetting(
- Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
- getHardwareFeedbackIntensityWhenSettingIsMissing(mHapticFeedbackIntensity));
- mNotificationIntensity = getSystemSetting(
- Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- getDefaultIntensity(USAGE_NOTIFICATION));
- mRingIntensity = getSystemSetting(Settings.System.RING_VIBRATION_INTENSITY,
+ mVibrateInputDevices = loadSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
+
+ int alarmIntensity = toIntensity(
+ loadSystemSetting(Settings.System.ALARM_VIBRATION_INTENSITY, -1),
+ getDefaultIntensity(USAGE_ALARM));
+ int defaultHapticFeedbackIntensity = getDefaultIntensity(USAGE_TOUCH);
+ int hapticFeedbackIntensity = toIntensity(
+ loadSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, -1),
+ defaultHapticFeedbackIntensity);
+ int positiveHapticFeedbackIntensity = toPositiveIntensity(
+ hapticFeedbackIntensity, defaultHapticFeedbackIntensity);
+ int hardwareFeedbackIntensity = toIntensity(
+ loadSystemSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, -1),
+ positiveHapticFeedbackIntensity);
+ int mediaIntensity = toIntensity(
+ loadSystemSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, -1),
+ getDefaultIntensity(USAGE_MEDIA));
+ int defaultNotificationIntensity = getDefaultIntensity(USAGE_NOTIFICATION);
+ int notificationIntensity = toIntensity(
+ loadSystemSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, -1),
+ defaultNotificationIntensity);
+ int positiveNotificationIntensity = toPositiveIntensity(
+ notificationIntensity, defaultNotificationIntensity);
+ int ringIntensity = toIntensity(
+ loadSystemSetting(Settings.System.RING_VIBRATION_INTENSITY, -1),
getDefaultIntensity(USAGE_RINGTONE));
- mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
- }
- notifyListeners();
- }
- /**
- * Return the value to be used for {@link Settings.System#HARDWARE_HAPTIC_FEEDBACK_INTENSITY}
- * when the value was not set by the user.
- *
- * <p>This should adapt the behavior preceding the introduction of this new setting key, which
- * is to apply {@link Settings.System#HAPTIC_FEEDBACK_INTENSITY} unless it's disabled.
- */
- private int getHardwareFeedbackIntensityWhenSettingIsMissing(int hapticFeedbackIntensity) {
- if (hapticFeedbackIntensity == Vibrator.VIBRATION_INTENSITY_OFF) {
- return getDefaultIntensity(USAGE_HARDWARE_FEEDBACK);
+
+ mCurrentVibrationIntensities.clear();
+ mCurrentVibrationIntensities.put(USAGE_ALARM, alarmIntensity);
+ mCurrentVibrationIntensities.put(USAGE_NOTIFICATION, notificationIntensity);
+ mCurrentVibrationIntensities.put(USAGE_MEDIA, mediaIntensity);
+ mCurrentVibrationIntensities.put(USAGE_UNKNOWN, mediaIntensity);
+
+ // Communication request is not disabled by the notification setting.
+ mCurrentVibrationIntensities.put(USAGE_COMMUNICATION_REQUEST,
+ positiveNotificationIntensity);
+
+ if (!loadBooleanSetting(Settings.System.VIBRATE_WHEN_RINGING)
+ && !loadBooleanSetting(Settings.System.APPLY_RAMPING_RINGER)) {
+ // Make sure deprecated boolean setting still disables ringtone vibrations.
+ mCurrentVibrationIntensities.put(USAGE_RINGTONE, Vibrator.VIBRATION_INTENSITY_OFF);
+ } else {
+ mCurrentVibrationIntensities.put(USAGE_RINGTONE, ringIntensity);
+ }
+
+ // This should adapt the behavior preceding the introduction of this new setting
+ // key, which is to apply HAPTIC_FEEDBACK_INTENSITY, unless it's disabled.
+ mCurrentVibrationIntensities.put(USAGE_HARDWARE_FEEDBACK, hardwareFeedbackIntensity);
+ mCurrentVibrationIntensities.put(USAGE_PHYSICAL_EMULATION, hardwareFeedbackIntensity);
+
+ if (!loadBooleanSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED)) {
+ // Make sure deprecated boolean setting still disables touch vibrations.
+ mCurrentVibrationIntensities.put(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_OFF);
+ } else {
+ mCurrentVibrationIntensities.put(USAGE_TOUCH, hapticFeedbackIntensity);
+ }
+
+ // A11y is not disabled by any haptic feedback setting.
+ mCurrentVibrationIntensities.put(USAGE_ACCESSIBILITY, positiveHapticFeedbackIntensity);
}
- return hapticFeedbackIntensity;
+ notifyListeners();
}
@Override
public String toString() {
synchronized (mLock) {
+ StringBuilder vibrationIntensitiesString = new StringBuilder("{");
+ for (int i = 0; i < mCurrentVibrationIntensities.size(); i++) {
+ int usage = mCurrentVibrationIntensities.keyAt(i);
+ int intensity = mCurrentVibrationIntensities.valueAt(i);
+ vibrationIntensitiesString.append(VibrationAttributes.usageToString(usage))
+ .append("=(").append(intensityToString(intensity))
+ .append(",default:").append(intensityToString(getDefaultIntensity(usage)))
+ .append("), ");
+ }
+ vibrationIntensitiesString.append('}');
return "VibrationSettings{"
- + "mVibrateInputDevices=" + mVibrateInputDevices
- + ", mVibrateWhenRinging=" + mVibrateWhenRinging
- + ", mApplyRampingRinger=" + mApplyRampingRinger
+ + "mVibratorConfig=" + mVibrationConfig
+ + ", mVibrateInputDevices=" + mVibrateInputDevices
+ ", mBatterySaverMode=" + mBatterySaverMode
+ ", mProcStatesCache=" + mUidObserver.mProcStatesCache
- + ", mHapticChannelMaxVibrationAmplitude="
- + getHapticChannelMaxVibrationAmplitude()
- + ", mRampStepDuration=" + mRampStepDuration
- + ", mRampDownDuration=" + mRampDownDuration
- + ", mHardwareHapticFeedbackIntensity="
- + intensityToString(getCurrentIntensity(USAGE_HARDWARE_FEEDBACK))
- + ", mHapticFeedbackIntensity="
- + intensityToString(getCurrentIntensity(USAGE_TOUCH))
- + ", mHapticFeedbackDefaultIntensity="
- + intensityToString(getDefaultIntensity(USAGE_TOUCH))
- + ", mNotificationIntensity="
- + intensityToString(getCurrentIntensity(USAGE_NOTIFICATION))
- + ", mNotificationDefaultIntensity="
- + intensityToString(getDefaultIntensity(USAGE_NOTIFICATION))
- + ", mRingIntensity="
- + intensityToString(getCurrentIntensity(USAGE_RINGTONE))
- + ", mRingDefaultIntensity="
- + intensityToString(getDefaultIntensity(USAGE_RINGTONE))
+ + ", mVibrationIntensities=" + vibrationIntensitiesString
+ '}';
}
}
@@ -466,16 +444,28 @@ final class VibrationSettings {
/** Write current settings into given {@link ProtoOutputStream}. */
public void dumpProto(ProtoOutputStream proto) {
synchronized (mLock) {
+ proto.write(VibratorManagerServiceDumpProto.ALARM_INTENSITY,
+ getCurrentIntensity(USAGE_ALARM));
+ proto.write(VibratorManagerServiceDumpProto.ALARM_DEFAULT_INTENSITY,
+ getDefaultIntensity(USAGE_ALARM));
+ proto.write(VibratorManagerServiceDumpProto.HARDWARE_FEEDBACK_INTENSITY,
+ getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
+ proto.write(VibratorManagerServiceDumpProto.HARDWARE_FEEDBACK_DEFAULT_INTENSITY,
+ getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY,
- mHapticFeedbackIntensity);
+ getCurrentIntensity(USAGE_TOUCH));
proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_DEFAULT_INTENSITY,
getDefaultIntensity(USAGE_TOUCH));
+ proto.write(VibratorManagerServiceDumpProto.MEDIA_INTENSITY,
+ getCurrentIntensity(USAGE_MEDIA));
+ proto.write(VibratorManagerServiceDumpProto.MEDIA_DEFAULT_INTENSITY,
+ getDefaultIntensity(USAGE_MEDIA));
proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_INTENSITY,
- mNotificationIntensity);
+ getCurrentIntensity(USAGE_NOTIFICATION));
proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_DEFAULT_INTENSITY,
getDefaultIntensity(USAGE_NOTIFICATION));
proto.write(VibratorManagerServiceDumpProto.RING_INTENSITY,
- mRingIntensity);
+ getCurrentIntensity(USAGE_RINGTONE));
proto.write(VibratorManagerServiceDumpProto.RING_DEFAULT_INTENSITY,
getDefaultIntensity(USAGE_RINGTONE));
}
@@ -506,13 +496,29 @@ final class VibrationSettings {
}
}
- private float getHapticChannelMaxVibrationAmplitude() {
- synchronized (mLock) {
- return mVibrator == null ? Float.NaN : mVibrator.getHapticChannelMaximumAmplitude();
+ @VibrationIntensity
+ private int toPositiveIntensity(int value, @VibrationIntensity int defaultValue) {
+ if (value == Vibrator.VIBRATION_INTENSITY_OFF) {
+ return defaultValue;
+ }
+ return toIntensity(value, defaultValue);
+ }
+
+ @VibrationIntensity
+ private int toIntensity(int value, @VibrationIntensity int defaultValue) {
+ if ((value < Vibrator.VIBRATION_INTENSITY_OFF)
+ || (value > Vibrator.VIBRATION_INTENSITY_HIGH)) {
+ return defaultValue;
}
+ return value;
+ }
+
+ private boolean loadBooleanSetting(String settingKey) {
+ return Settings.System.getIntForUser(mContext.getContentResolver(),
+ settingKey, 0, UserHandle.USER_CURRENT) != 0;
}
- private int getSystemSetting(String settingName, int defaultValue) {
+ private int loadSystemSetting(String settingName, int defaultValue) {
return Settings.System.getIntForUser(mContext.getContentResolver(),
settingName, defaultValue, UserHandle.USER_CURRENT);
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java
index 4a1b95bd4596..47b3e1a2294c 100644
--- a/services/core/java/com/android/server/vibrator/VibratorController.java
+++ b/services/core/java/com/android/server/vibrator/VibratorController.java
@@ -36,8 +36,6 @@ import libcore.util.NativeAllocationRegistry;
/** Controls a single vibrator. */
final class VibratorController {
private static final String TAG = "VibratorController";
- // TODO(b/167947076): load suggested range from config
- private static final int SUGGESTED_FREQUENCY_SAFE_RANGE = 200;
private final Object mLock = new Object();
@@ -74,8 +72,7 @@ final class VibratorController {
mNativeWrapper = nativeWrapper;
mNativeWrapper.init(vibratorId, listener);
VibratorInfo.Builder vibratorInfoBuilder = new VibratorInfo.Builder(vibratorId);
- mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(SUGGESTED_FREQUENCY_SAFE_RANGE,
- vibratorInfoBuilder);
+ mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(vibratorInfoBuilder);
mVibratorInfo = vibratorInfoBuilder.build();
if (!mVibratorInfoLoadSuccessful) {
@@ -126,8 +123,7 @@ final class VibratorController {
}
int vibratorId = mVibratorInfo.getId();
VibratorInfo.Builder vibratorInfoBuilder = new VibratorInfo.Builder(vibratorId);
- mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(SUGGESTED_FREQUENCY_SAFE_RANGE,
- vibratorInfoBuilder);
+ mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(vibratorInfoBuilder);
mVibratorInfo = vibratorInfoBuilder.build();
if (!mVibratorInfoLoadSuccessful) {
Slog.e(TAG, "Failed retry of HAL getInfo for vibrator " + vibratorId);
@@ -419,8 +415,7 @@ final class VibratorController {
private static native void alwaysOnDisable(long nativePtr, long id);
- private static native boolean getInfo(long nativePtr, float suggestedFrequencyRange,
- VibratorInfo.Builder infoBuilder);
+ private static native boolean getInfo(long nativePtr, VibratorInfo.Builder infoBuilder);
private long mNativePtr = 0;
@@ -490,8 +485,8 @@ final class VibratorController {
/**
* Loads device vibrator metadata and returns true if all metadata was loaded successfully.
*/
- public boolean getInfo(float suggestedFrequencyRange, VibratorInfo.Builder infoBuilder) {
- return getInfo(mNativePtr, suggestedFrequencyRange, infoBuilder);
+ public boolean getInfo(VibratorInfo.Builder infoBuilder) {
+ return getInfo(mNativePtr, infoBuilder);
}
}
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 478e86e5f710..27566b301a6e 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -1756,17 +1756,23 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
if (hasFrequencies) {
frequencies.add(Float.parseFloat(getNextArgRequired()));
- } else {
- frequencies.add(0f);
}
}
VibrationEffect.WaveformBuilder waveform = VibrationEffect.startWaveform();
for (int i = 0; i < durations.size(); i++) {
if (isContinuous) {
- waveform.addRamp(amplitudes.get(i), frequencies.get(i), durations.get(i));
+ if (hasFrequencies) {
+ waveform.addRamp(amplitudes.get(i), frequencies.get(i), durations.get(i));
+ } else {
+ waveform.addRamp(amplitudes.get(i), durations.get(i));
+ }
} else {
- waveform.addStep(amplitudes.get(i), frequencies.get(i), durations.get(i));
+ if (hasFrequencies) {
+ waveform.addStep(amplitudes.get(i), frequencies.get(i), durations.get(i));
+ } else {
+ waveform.addStep(amplitudes.get(i), durations.get(i));
+ }
}
}
composition.addEffect(waveform.build(repeat), delay);
@@ -1865,7 +1871,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
pw.println(" If -c is provided, the waveform is continuous and will ramp");
pw.println(" between values; otherwise each entry is a fixed step.");
pw.println(" Duration is in milliseconds; amplitude is a scale of 1-255;");
- pw.println(" frequency is a relative value around resonant frequency 0;");
+ pw.println(" frequency is an absolute value in hertz;");
pw.println(" prebaked [-w delay] [-b] <effect-id>");
pw.println(" Vibrates with prebaked effect; ignored when device is on DND ");
pw.println(" (Do Not Disturb) mode; touch feedback strength user setting ");
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 0396a1101c64..8f703c5c7761 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -45,7 +45,6 @@ import static com.android.server.accessibility.AccessibilityTraceProto.WINDOW_MA
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowTracing.WINSCOPE_EXT;
-import static com.android.server.wm.utils.RegionUtils.forEachRect;
import android.accessibilityservice.AccessibilityTrace;
import android.animation.ObjectAnimator;
@@ -101,6 +100,7 @@ import com.android.internal.util.TraceBuffer;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.wm.AccessibilityWindowsPopulator.AccessibilityWindow;
import com.android.server.wm.WindowManagerInternal.AccessibilityControllerInternal;
import com.android.server.wm.WindowManagerInternal.MagnificationCallbacks;
import com.android.server.wm.WindowManagerInternal.WindowsForAccessibilityCallback;
@@ -133,19 +133,22 @@ final class AccessibilityController {
private static final Rect EMPTY_RECT = new Rect();
private static final float[] sTempFloats = new float[9];
- private SparseArray<DisplayMagnifier> mDisplayMagnifiers = new SparseArray<>();
- private SparseArray<WindowsForAccessibilityObserver> mWindowsForAccessibilityObserver =
+ private final SparseArray<DisplayMagnifier> mDisplayMagnifiers = new SparseArray<>();
+ private final SparseArray<WindowsForAccessibilityObserver> mWindowsForAccessibilityObserver =
new SparseArray<>();
private SparseArray<IBinder> mFocusedWindow = new SparseArray<>();
private int mFocusedDisplay = -1;
private boolean mIsImeVisible = false;
// Set to true if initializing window population complete.
private boolean mAllObserversInitialized = true;
+ private final AccessibilityWindowsPopulator mAccessibilityWindowsPopulator;
AccessibilityController(WindowManagerService service) {
mService = service;
mAccessibilityTracing =
AccessibilityController.getAccessibilityControllerInternal(service);
+
+ mAccessibilityWindowsPopulator = new AccessibilityWindowsPopulator(mService, this);
}
boolean setMagnificationCallbacks(int displayId, MagnificationCallbacks callbacks) {
@@ -209,7 +212,9 @@ final class AccessibilityController {
}
mWindowsForAccessibilityObserver.remove(displayId);
}
- observer = new WindowsForAccessibilityObserver(mService, displayId, callback);
+ mAccessibilityWindowsPopulator.setWindowsNotification(true);
+ observer = new WindowsForAccessibilityObserver(mService, displayId, callback,
+ mAccessibilityWindowsPopulator);
mWindowsForAccessibilityObserver.put(displayId, observer);
mAllObserversInitialized &= observer.mInitialized;
} else {
@@ -224,6 +229,10 @@ final class AccessibilityController {
}
}
mWindowsForAccessibilityObserver.remove(displayId);
+
+ if (mWindowsForAccessibilityObserver.size() <= 0) {
+ mAccessibilityWindowsPopulator.setWindowsNotification(false);
+ }
}
}
@@ -309,11 +318,6 @@ final class AccessibilityController {
if (displayMagnifier != null) {
displayMagnifier.onDisplaySizeChanged(displayContent);
}
- final WindowsForAccessibilityObserver windowsForA11yObserver =
- mWindowsForAccessibilityObserver.get(displayId);
- if (windowsForA11yObserver != null) {
- windowsForA11yObserver.scheduleComputeChangedWindows();
- }
}
void onAppWindowTransition(int displayId, int transition) {
@@ -341,11 +345,6 @@ final class AccessibilityController {
if (displayMagnifier != null) {
displayMagnifier.onWindowTransition(windowState, transition);
}
- final WindowsForAccessibilityObserver windowsForA11yObserver =
- mWindowsForAccessibilityObserver.get(displayId);
- if (windowsForA11yObserver != null) {
- windowsForA11yObserver.scheduleComputeChangedWindows();
- }
}
void onWindowFocusChangedNot(int displayId) {
@@ -455,6 +454,19 @@ final class AccessibilityController {
return null;
}
+ boolean getMagnificationSpecForDisplay(int displayId, MagnificationSpec outSpec) {
+ if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
+ mAccessibilityTracing.logTrace(TAG + ".getMagnificationSpecForDisplay",
+ FLAGS_MAGNIFICATION_CALLBACK, "displayId=" + displayId);
+ }
+ final DisplayMagnifier displayMagnifier = mDisplayMagnifiers.get(displayId);
+ if (displayMagnifier == null) {
+ return false;
+ }
+
+ return displayMagnifier.getMagnificationSpec(outSpec);
+ }
+
boolean hasCallbacks() {
if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK
| FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) {
@@ -756,6 +768,25 @@ final class AccessibilityController {
return spec;
}
+ boolean getMagnificationSpec(MagnificationSpec outSpec) {
+ if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
+ mAccessibilityTracing.logTrace(LOG_TAG + ".getMagnificationSpec",
+ FLAGS_MAGNIFICATION_CALLBACK);
+ }
+ MagnificationSpec spec = mMagnifedViewport.getMagnificationSpec();
+ if (spec == null) {
+ return false;
+ }
+
+ outSpec.setTo(spec);
+ if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
+ mAccessibilityTracing.logTrace(LOG_TAG + ".getMagnificationSpec",
+ FLAGS_MAGNIFICATION_CALLBACK, "outSpec={" + outSpec + "}");
+ }
+
+ return true;
+ }
+
void getMagnificationRegion(Region outMagnificationRegion) {
if (mAccessibilityTracing.isTracingEnabled(FLAGS_MAGNIFICATION_CALLBACK)) {
mAccessibilityTracing.logTrace(LOG_TAG + ".getMagnificationRegion",
@@ -1403,20 +1434,18 @@ final class AccessibilityController {
private static final boolean DEBUG = false;
- private final SparseArray<WindowState> mTempWindowStates = new SparseArray<>();
+ private final List<AccessibilityWindow> mTempA11yWindows = new ArrayList<>();
private final Set<IBinder> mTempBinderSet = new ArraySet<>();
- private final RectF mTempRectF = new RectF();
-
- private final Matrix mTempMatrix = new Matrix();
-
private final Point mTempPoint = new Point();
private final Region mTempRegion = new Region();
private final Region mTempRegion1 = new Region();
+ private final Region mTempRegion2 = new Region();
+
private final WindowManagerService mService;
private final Handler mHandler;
@@ -1431,10 +1460,11 @@ final class AccessibilityController {
// Set to true if initializing window population complete.
private boolean mInitialized;
+ private final AccessibilityWindowsPopulator mA11yWindowsPopulator;
WindowsForAccessibilityObserver(WindowManagerService windowManagerService,
- int displayId,
- WindowsForAccessibilityCallback callback) {
+ int displayId, WindowsForAccessibilityCallback callback,
+ AccessibilityWindowsPopulator accessibilityWindowsPopulator) {
mService = windowManagerService;
mCallback = callback;
mDisplayId = displayId;
@@ -1443,6 +1473,7 @@ final class AccessibilityController {
AccessibilityController.getAccessibilityControllerInternal(mService);
mRecurringAccessibilityEventsIntervalMillis = ViewConfiguration
.getSendRecurringAccessibilityEventsInterval();
+ mA11yWindowsPopulator = accessibilityWindowsPopulator;
computeChangedWindows(true);
}
@@ -1466,52 +1497,6 @@ final class AccessibilityController {
}
}
- boolean shellRootIsAbove(WindowState windowState, ShellRoot shellRoot) {
- int wsLayer = mService.mPolicy.getWindowLayerLw(windowState);
- int shellLayer = mService.mPolicy.getWindowLayerFromTypeLw(shellRoot.getWindowType(),
- true);
- return shellLayer >= wsLayer;
- }
-
- int addShellRootsIfAbove(WindowState windowState, ArrayList<ShellRoot> shellRoots,
- int shellRootIndex, List<WindowInfo> windows, Set<IBinder> addedWindows,
- Region unaccountedSpace, boolean focusedWindowAdded) {
- while (shellRootIndex < shellRoots.size()
- && shellRootIsAbove(windowState, shellRoots.get(shellRootIndex))) {
- ShellRoot shellRoot = shellRoots.get(shellRootIndex);
- shellRootIndex++;
- final WindowInfo info = shellRoot.getWindowInfo();
- if (info == null) {
- continue;
- }
-
- info.layer = addedWindows.size();
- windows.add(info);
- addedWindows.add(info.token);
- unaccountedSpace.op(info.regionInScreen, unaccountedSpace,
- Region.Op.REVERSE_DIFFERENCE);
- if (unaccountedSpace.isEmpty() && focusedWindowAdded) {
- break;
- }
- }
- return shellRootIndex;
- }
-
- private ArrayList<ShellRoot> getSortedShellRoots(
- SparseArray<ShellRoot> originalShellRoots) {
- ArrayList<ShellRoot> sortedShellRoots = new ArrayList<>(originalShellRoots.size());
- for (int i = originalShellRoots.size() - 1; i >= 0; --i) {
- sortedShellRoots.add(originalShellRoots.valueAt(i));
- }
-
- sortedShellRoots.sort((left, right) ->
- mService.mPolicy.getWindowLayerFromTypeLw(right.getWindowType(), true)
- - mService.mPolicy.getWindowLayerFromTypeLw(left.getWindowType(),
- true));
-
- return sortedShellRoots;
- }
-
/**
* Check if windows have changed, and send them to the accessibility subsystem if they have.
*
@@ -1561,44 +1546,29 @@ final class AccessibilityController {
Region unaccountedSpace = mTempRegion;
unaccountedSpace.set(0, 0, screenWidth, screenHeight);
- final SparseArray<WindowState> visibleWindows = mTempWindowStates;
- populateVisibleWindowsOnScreen(visibleWindows);
+ final List<AccessibilityWindow> visibleWindows = mTempA11yWindows;
+ mA11yWindowsPopulator.populateVisibleWindowsOnScreenLocked(
+ mDisplayId, visibleWindows);
Set<IBinder> addedWindows = mTempBinderSet;
addedWindows.clear();
boolean focusedWindowAdded = false;
final int visibleWindowCount = visibleWindows.size();
- ArrayList<TaskFragment> skipRemainingWindowsForTaskFragments = new ArrayList<>();
-
- ArrayList<ShellRoot> shellRoots = getSortedShellRoots(dc.mShellRoots);
// Iterate until we figure out what is touchable for the entire screen.
- int shellRootIndex = 0;
- for (int i = visibleWindowCount - 1; i >= 0; i--) {
- final WindowState windowState = visibleWindows.valueAt(i);
- int prevShellRootIndex = shellRootIndex;
- shellRootIndex = addShellRootsIfAbove(windowState, shellRoots, shellRootIndex,
- windows, addedWindows, unaccountedSpace, focusedWindowAdded);
-
- // If a Shell Root was added, it could have accounted for all the space already.
- if (shellRootIndex > prevShellRootIndex && unaccountedSpace.isEmpty()
- && focusedWindowAdded) {
- break;
- }
-
- final Region regionInScreen = new Region();
- computeWindowRegionInScreen(windowState, regionInScreen);
- if (windowMattersToAccessibility(windowState,
- regionInScreen, unaccountedSpace,
- skipRemainingWindowsForTaskFragments)) {
- addPopulatedWindowInfo(windowState, regionInScreen, windows, addedWindows);
- if (windowMattersToUnaccountedSpaceComputation(windowState)) {
- updateUnaccountedSpace(windowState, regionInScreen, unaccountedSpace,
- skipRemainingWindowsForTaskFragments);
+ for (int i = 0; i < visibleWindowCount; i++) {
+ final AccessibilityWindow a11yWindow = visibleWindows.get(i);
+ final Region regionInWindow = new Region();
+ a11yWindow.getTouchableRegionInWindow(regionInWindow);
+ if (windowMattersToAccessibility(a11yWindow, regionInWindow,
+ unaccountedSpace)) {
+ addPopulatedWindowInfo(a11yWindow, regionInWindow, windows, addedWindows);
+ if (windowMattersToUnaccountedSpaceComputation(a11yWindow)) {
+ updateUnaccountedSpace(a11yWindow, unaccountedSpace);
}
- focusedWindowAdded |= windowState.isFocused();
- } else if (isUntouchableNavigationBar(windowState, mTempRegion1)) {
+ focusedWindowAdded |= a11yWindow.isFocused();
+ } else if (a11yWindow.isUntouchableNavigationBar()) {
// If this widow is navigation bar without touchable region, accounting the
// region of navigation bar inset because all touch events from this region
// would be received by launcher, i.e. this region is a un-touchable one
@@ -1647,47 +1617,39 @@ final class AccessibilityController {
// Some windows should be excluded from unaccounted space computation, though they still
// should be reported
- private boolean windowMattersToUnaccountedSpaceComputation(WindowState windowState) {
+ private boolean windowMattersToUnaccountedSpaceComputation(AccessibilityWindow a11yWindow) {
// Do not account space of trusted non-touchable windows, except the split-screen
// divider.
// If it's not trusted, touch events are not sent to the windows behind it.
- if (((windowState.mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
- && (windowState.mAttrs.type != TYPE_DOCK_DIVIDER)
- && windowState.isTrustedOverlay()) {
+ if (((a11yWindow.getFlags() & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
+ && (a11yWindow.getType() != TYPE_DOCK_DIVIDER)
+ && a11yWindow.isTrustedOverlay()) {
return false;
}
- if (windowState.mAttrs.type
- == WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
+ if (a11yWindow.getType() == WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
return false;
}
return true;
}
- private boolean windowMattersToAccessibility(WindowState windowState,
- Region regionInScreen, Region unaccountedSpace,
- ArrayList<TaskFragment> skipRemainingWindowsForTaskFragments) {
- final RecentsAnimationController controller = mService.getRecentsAnimationController();
- if (controller != null && controller.shouldIgnoreForAccessibility(windowState)) {
+ private boolean windowMattersToAccessibility(AccessibilityWindow a11yWindow,
+ Region regionInScreen, Region unaccountedSpace) {
+ if (a11yWindow.ignoreRecentsAnimationForAccessibility()) {
return false;
}
- if (windowState.isFocused()) {
+ if (a11yWindow.isFocused()) {
return true;
}
- // If the window is part of a task that we're finished with - ignore.
- final TaskFragment taskFragment = windowState.getTaskFragment();
- if (taskFragment != null
- && skipRemainingWindowsForTaskFragments.contains(taskFragment)) {
- return false;
- }
-
// Ignore non-touchable windows, except the split-screen divider, which is
// occasionally non-touchable but still useful for identifying split-screen
- // mode.
- if (((windowState.mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
- && (windowState.mAttrs.type != TYPE_DOCK_DIVIDER)) {
+ // mode and the PIP menu.
+ if (((a11yWindow.getFlags()
+ & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0)
+ && (a11yWindow.getType() != TYPE_DOCK_DIVIDER
+ && !a11yWindow.isPIPMenu())) {
return false;
}
@@ -1697,88 +1659,36 @@ final class AccessibilityController {
}
// Add windows of certain types not covered by modal windows.
- if (isReportedWindowType(windowState.mAttrs.type)) {
+ if (isReportedWindowType(a11yWindow.getType())) {
return true;
}
return false;
}
- private void updateUnaccountedSpace(WindowState windowState, Region regionInScreen,
- Region unaccountedSpace,
- ArrayList<TaskFragment> skipRemainingWindowsForTaskFragments) {
- // Account for the space this window takes if the window
- // is not an accessibility overlay which does not change
- // the reported windows.
- unaccountedSpace.op(regionInScreen, unaccountedSpace,
- Region.Op.REVERSE_DIFFERENCE);
-
- // If a window is modal it prevents other windows from being touched
- if ((windowState.mAttrs.flags & (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL)) == 0) {
- if (!windowState.hasTapExcludeRegion()) {
- // Account for all space in the task, whether the windows in it are
- // touchable or not. The modal window blocks all touches from the task's
- // area.
- unaccountedSpace.op(windowState.getDisplayFrame(), unaccountedSpace,
- Region.Op.REVERSE_DIFFERENCE);
- } else {
- // If a window has tap exclude region, we need to account it.
- final Region displayRegion = new Region(windowState.getDisplayFrame());
- final Region tapExcludeRegion = new Region();
- windowState.getTapExcludeRegion(tapExcludeRegion);
- displayRegion.op(tapExcludeRegion, displayRegion,
- Region.Op.REVERSE_DIFFERENCE);
- unaccountedSpace.op(displayRegion, unaccountedSpace,
- Region.Op.REVERSE_DIFFERENCE);
- }
-
- final TaskFragment taskFragment = windowState.getTaskFragment();
- if (taskFragment != null) {
- // If the window is associated with a particular task, we can skip the
- // rest of the windows for that task.
- skipRemainingWindowsForTaskFragments.add(taskFragment);
- } else if (!windowState.hasTapExcludeRegion()) {
- // If the window is not associated with a particular task, then it is
- // globally modal. In this case we can skip all remaining windows when
- // it doesn't has tap exclude region.
- unaccountedSpace.setEmpty();
- }
- }
-
- // Account for the space of letterbox.
- if (windowState.areAppWindowBoundsLetterboxed()) {
- unaccountedSpace.op(getLetterboxBounds(windowState), unaccountedSpace,
+ private void updateUnaccountedSpace(AccessibilityWindow a11yWindow,
+ Region unaccountedSpace) {
+ if (a11yWindow.getType()
+ != WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
+ // Account for the space this window takes if the window
+ // is not an accessibility overlay which does not change
+ // the reported windows.
+ final Region touchableRegion = mTempRegion2;
+ a11yWindow.getTouchableRegionInScreen(touchableRegion);
+ unaccountedSpace.op(touchableRegion, unaccountedSpace,
Region.Op.REVERSE_DIFFERENCE);
+ // Account for the space of letterbox.
+ final Region letterboxBounds = mTempRegion1;
+ if (a11yWindow.setLetterBoxBoundsIfNeeded(letterboxBounds)) {
+ unaccountedSpace.op(letterboxBounds,
+ unaccountedSpace, Region.Op.REVERSE_DIFFERENCE);
+ }
}
}
- private void computeWindowRegionInScreen(WindowState windowState, Region outRegion) {
- // Get the touchable frame.
- Region touchableRegion = mTempRegion1;
- windowState.getTouchableRegion(touchableRegion);
-
- // Map the frame to get what appears on the screen.
- Matrix matrix = mTempMatrix;
- populateTransformationMatrix(windowState, matrix);
-
- forEachRect(touchableRegion, rect -> {
- // Move to origin as all transforms are captured by the matrix.
- RectF windowFrame = mTempRectF;
- windowFrame.set(rect);
- windowFrame.offset(-windowState.getFrame().left, -windowState.getFrame().top);
-
- matrix.mapRect(windowFrame);
-
- // Union all rects.
- outRegion.union(new Rect((int) windowFrame.left, (int) windowFrame.top,
- (int) windowFrame.right, (int) windowFrame.bottom));
- });
- }
-
- private static void addPopulatedWindowInfo(WindowState windowState, Region regionInScreen,
- List<WindowInfo> out, Set<IBinder> tokenOut) {
- final WindowInfo window = windowState.getWindowInfo();
+ private static void addPopulatedWindowInfo(AccessibilityWindow a11yWindow,
+ Region regionInScreen, List<WindowInfo> out, Set<IBinder> tokenOut) {
+ final WindowInfo window = a11yWindow.getWindowInfo();
window.regionInScreen.set(regionInScreen);
window.layer = tokenOut.size();
out.add(window);
@@ -1805,23 +1715,6 @@ final class AccessibilityController {
&& windowType != WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION);
}
- private void populateVisibleWindowsOnScreen(SparseArray<WindowState> outWindows) {
- final List<WindowState> tempWindowStatesList = new ArrayList<>();
- final DisplayContent dc = mService.mRoot.getDisplayContent(mDisplayId);
- if (dc == null) {
- return;
- }
-
- dc.forAllWindows(w -> {
- if (w.isVisible()) {
- tempWindowStatesList.add(w);
- }
- }, false /* traverseTopToBottom */);
- for (int i = 0; i < tempWindowStatesList.size(); i++) {
- outWindows.put(i, tempWindowStatesList.get(i));
- }
- }
-
private WindowState getTopFocusWindow() {
return mService.mRoot.getTopFocusedDisplayContent().mCurrentFocus;
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java
new file mode 100644
index 000000000000..f31ae06f62e9
--- /dev/null
+++ b/services/core/java/com/android/server/wm/AccessibilityWindowsPopulator.java
@@ -0,0 +1,625 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+
+import static com.android.server.wm.utils.RegionUtils.forEachRect;
+
+import android.annotation.NonNull;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.view.IWindow;
+import android.view.InputWindowHandle;
+import android.view.MagnificationSpec;
+import android.view.WindowInfo;
+import android.view.WindowManager;
+import android.window.WindowInfosListener;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is the accessibility windows population adapter.
+ */
+public final class AccessibilityWindowsPopulator extends WindowInfosListener {
+
+ private static final String TAG = AccessibilityWindowsPopulator.class.getSimpleName();
+ // If the surface flinger callback is not coming within in 2 frames time, i.e. about
+ // 35ms, then assuming the windows become stable.
+ private static final int SURFACE_FLINGER_CALLBACK_WINDOWS_STABLE_TIMES_MS = 35;
+ // To avoid the surface flinger callbacks always comes within in 2 frames, then no windows
+ // are reported to the A11y framework, and the animation duration time is 500ms, so setting
+ // this value as the max timeout value to force computing changed windows.
+ private static final int WINDOWS_CHANGED_NOTIFICATION_MAX_DURATION_TIMES_MS = 500;
+
+ private static final float[] sTempFloats = new float[9];
+
+ private final WindowManagerService mService;
+ private final AccessibilityController mAccessibilityController;
+ @GuardedBy("mLock")
+ private final SparseArray<List<InputWindowHandle>> mInputWindowHandlesOnDisplays =
+ new SparseArray<>();
+ @GuardedBy("mLock")
+ private final SparseArray<Matrix> mMagnificationSpecInverseMatrix = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final SparseArray<DisplayInfo> mDisplayInfos = new SparseArray<>();
+ @GuardedBy("mLock")
+ private final List<InputWindowHandle> mVisibleWindows = new ArrayList<>();
+ @GuardedBy("mLock")
+ private boolean mWindowsNotificationEnabled = false;
+ private final Object mLock = new Object();
+ private final Handler mHandler;
+
+ AccessibilityWindowsPopulator(WindowManagerService service,
+ AccessibilityController accessibilityController) {
+ mService = service;
+ mAccessibilityController = accessibilityController;
+ mHandler = new MyHandler(mService.mH.getLooper());
+
+ register();
+ }
+
+ /**
+ * Gets the visible windows list with the window layer on the specified display.
+ *
+ * @param displayId The display.
+ * @param outWindows The visible windows list. The z-order of each window in the list
+ * is from the top to bottom.
+ */
+ public void populateVisibleWindowsOnScreenLocked(int displayId,
+ List<AccessibilityWindow> outWindows) {
+ List<InputWindowHandle> inputWindowHandles;
+ final Matrix inverseMatrix = new Matrix();
+ final Matrix displayMatrix = new Matrix();
+
+ synchronized (mLock) {
+ inputWindowHandles = mInputWindowHandlesOnDisplays.get(displayId);
+ if (inputWindowHandles == null) {
+ outWindows.clear();
+
+ return;
+ }
+ inverseMatrix.set(mMagnificationSpecInverseMatrix.get(displayId));
+
+ final DisplayInfo displayInfo = mDisplayInfos.get(displayId);
+ if (displayInfo != null) {
+ displayMatrix.set(displayInfo.mTransform);
+ } else {
+ Slog.w(TAG, "The displayInfo of this displayId (" + displayId + ") called "
+ + "back from the surface fligner is null");
+ }
+ }
+
+ final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
+ final ShellRoot shellroot = dc.mShellRoots.get(WindowManager.SHELL_ROOT_LAYER_PIP);
+ final IBinder pipMenuIBinder =
+ shellroot != null ? shellroot.getAccessibilityWindowToken() : null;
+
+ for (final InputWindowHandle windowHandle : inputWindowHandles) {
+ final AccessibilityWindow accessibilityWindow =
+ AccessibilityWindow.initializeData(mService, windowHandle, inverseMatrix,
+ pipMenuIBinder, displayMatrix);
+
+ outWindows.add(accessibilityWindow);
+ }
+ }
+
+ @Override
+ public void onWindowInfosChanged(InputWindowHandle[] windowHandles,
+ DisplayInfo[] displayInfos) {
+ synchronized (mLock) {
+ mVisibleWindows.clear();
+ for (InputWindowHandle window : windowHandles) {
+ if (window.visible && window.getWindow() != null) {
+ mVisibleWindows.add(window);
+ }
+ }
+
+ mDisplayInfos.clear();
+ for (final DisplayInfo displayInfo : displayInfos) {
+ mDisplayInfos.put(displayInfo.mDisplayId, displayInfo);
+ }
+
+ if (mWindowsNotificationEnabled) {
+ if (!mHandler.hasMessages(
+ MyHandler.MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_TIMEOUT)) {
+ mHandler.sendEmptyMessageDelayed(
+ MyHandler.MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_TIMEOUT,
+ WINDOWS_CHANGED_NOTIFICATION_MAX_DURATION_TIMES_MS);
+ }
+ populateVisibleWindowHandlesAndNotifyWindowsChangeIfNeededLocked();
+ }
+ }
+ }
+
+ /**
+ * Sets to notify the accessibilityController to compute changed windows on
+ * the display after populating the visible windows if the windows reported
+ * from the surface flinger changes.
+ *
+ * @param register {@code true} means starting windows population.
+ */
+ public void setWindowsNotification(boolean register) {
+ synchronized (mLock) {
+ if (mWindowsNotificationEnabled == register) {
+ return;
+ }
+ mWindowsNotificationEnabled = register;
+ if (mWindowsNotificationEnabled) {
+ populateVisibleWindowHandlesAndNotifyWindowsChangeIfNeededLocked();
+ } else {
+ releaseResources();
+ }
+ }
+ }
+
+ private void populateVisibleWindowHandlesAndNotifyWindowsChangeIfNeededLocked() {
+ final SparseArray<List<InputWindowHandle>> tempWindowHandleList = new SparseArray<>();
+
+ for (final InputWindowHandle windowHandle : mVisibleWindows) {
+ List<InputWindowHandle> inputWindowHandles = tempWindowHandleList.get(
+ windowHandle.displayId);
+
+ if (inputWindowHandles == null) {
+ inputWindowHandles = new ArrayList<>();
+ tempWindowHandleList.put(windowHandle.displayId, inputWindowHandles);
+ generateMagnificationSpecInverseMatrixLocked(windowHandle.displayId);
+ }
+ inputWindowHandles.add(windowHandle);
+ }
+
+ final List<Integer> displayIdsForWindowsChanged = new ArrayList<>();
+
+ getDisplaysForWindowsChangedLocked(displayIdsForWindowsChanged, tempWindowHandleList,
+ mInputWindowHandlesOnDisplays);
+ // Clones all windows from the callback of the surface flinger.
+ mInputWindowHandlesOnDisplays.clear();
+ for (int i = 0; i < tempWindowHandleList.size(); i++) {
+ final int displayId = tempWindowHandleList.keyAt(i);
+ mInputWindowHandlesOnDisplays.put(displayId, tempWindowHandleList.get(displayId));
+ }
+
+ if (displayIdsForWindowsChanged.size() > 0) {
+ if (!mHandler.hasMessages(MyHandler.MESSAGE_NOTIFY_WINDOWS_CHANGED)) {
+ mHandler.obtainMessage(MyHandler.MESSAGE_NOTIFY_WINDOWS_CHANGED,
+ displayIdsForWindowsChanged).sendToTarget();
+ }
+
+ return;
+ }
+ mHandler.removeMessages(MyHandler.MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_UI_STABLE);
+ mHandler.sendEmptyMessageDelayed(MyHandler.MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_UI_STABLE,
+ SURFACE_FLINGER_CALLBACK_WINDOWS_STABLE_TIMES_MS);
+ }
+
+ private void getDisplaysForWindowsChangedLocked(List<Integer> outDisplayIdsForWindowsChanged,
+ SparseArray<List<InputWindowHandle>> newWindowsList,
+ SparseArray<List<InputWindowHandle>> oldWindowsList) {
+ for (int i = 0; i < newWindowsList.size(); i++) {
+ final int displayId = newWindowsList.keyAt(i);
+ final List<InputWindowHandle> newWindows = newWindowsList.get(displayId);
+ final List<InputWindowHandle> oldWindows = oldWindowsList.get(displayId);
+
+ if (hasWindowsChangedLocked(newWindows, oldWindows)) {
+ outDisplayIdsForWindowsChanged.add(displayId);
+ }
+ }
+ }
+
+ private boolean hasWindowsChangedLocked(List<InputWindowHandle> newWindows,
+ List<InputWindowHandle> oldWindows) {
+ if (oldWindows == null || oldWindows.size() != newWindows.size()) {
+ return true;
+ }
+
+ final int windowsCount = newWindows.size();
+ // Since we always traverse windows from high to low layer,
+ // the old and new windows at the same index should be the
+ // same, otherwise something changed.
+ for (int i = 0; i < windowsCount; i++) {
+ final InputWindowHandle newWindow = newWindows.get(i);
+ final InputWindowHandle oldWindow = oldWindows.get(i);
+
+ if (!newWindow.getWindow().asBinder().equals(oldWindow.getWindow().asBinder())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private void generateMagnificationSpecInverseMatrixLocked(int displayId) {
+ MagnificationSpec spec = new MagnificationSpec();
+ if (!mAccessibilityController.getMagnificationSpecForDisplay(displayId, spec)) {
+ return;
+ }
+ sTempFloats[Matrix.MSCALE_X] = spec.scale;
+ sTempFloats[Matrix.MSKEW_Y] = 0;
+ sTempFloats[Matrix.MSKEW_X] = 0;
+ sTempFloats[Matrix.MSCALE_Y] = spec.scale;
+ sTempFloats[Matrix.MTRANS_X] = spec.offsetX;
+ sTempFloats[Matrix.MTRANS_Y] = spec.offsetY;
+ sTempFloats[Matrix.MPERSP_0] = 0;
+ sTempFloats[Matrix.MPERSP_1] = 0;
+ sTempFloats[Matrix.MPERSP_2] = 1;
+
+ final Matrix tempMatrix = new Matrix();
+ tempMatrix.setValues(sTempFloats);
+
+ final Matrix inverseMatrix = new Matrix();
+ final boolean result = tempMatrix.invert(inverseMatrix);
+
+ if (!result) {
+ Slog.e(TAG, "Can't inverse the magnification spec matrix with the "
+ + "magnification spec = " + spec + " on the displayId = " + displayId);
+ return;
+ }
+ mMagnificationSpecInverseMatrix.set(displayId, inverseMatrix);
+ }
+
+ private void notifyWindowsChanged(@NonNull List<Integer> displayIdsForWindowsChanged) {
+ mHandler.removeMessages(MyHandler.MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_TIMEOUT);
+
+ for (int i = 0; i < displayIdsForWindowsChanged.size(); i++) {
+ mAccessibilityController.performComputeChangedWindowsNot(
+ displayIdsForWindowsChanged.get(i), false);
+ }
+ }
+
+ private void forceUpdateWindows() {
+ final List<Integer> displayIdsForWindowsChanged = new ArrayList<>();
+
+ synchronized (mLock) {
+ for (int i = 0; i < mInputWindowHandlesOnDisplays.size(); i++) {
+ final int displayId = mInputWindowHandlesOnDisplays.keyAt(i);
+ displayIdsForWindowsChanged.add(displayId);
+ }
+ }
+ notifyWindowsChanged(displayIdsForWindowsChanged);
+ }
+
+ @GuardedBy("mLock")
+ private void releaseResources() {
+ mInputWindowHandlesOnDisplays.clear();
+ mMagnificationSpecInverseMatrix.clear();
+ mVisibleWindows.clear();
+ mDisplayInfos.clear();
+ mWindowsNotificationEnabled = false;
+ mHandler.removeCallbacksAndMessages(null);
+ }
+
+ private class MyHandler extends Handler {
+ public static final int MESSAGE_NOTIFY_WINDOWS_CHANGED = 1;
+ public static final int MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_UI_STABLE = 2;
+ public static final int MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_TIMEOUT = 3;
+
+ MyHandler(Looper looper) {
+ super(looper, null, false);
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MESSAGE_NOTIFY_WINDOWS_CHANGED: {
+ final List<Integer> displayIdsForWindowsChanged = (List<Integer>) message.obj;
+ notifyWindowsChanged(displayIdsForWindowsChanged);
+ } break;
+
+ case MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_UI_STABLE: {
+ forceUpdateWindows();
+ } break;
+
+ case MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_TIMEOUT: {
+ Slog.w(TAG, "Windows change within in 2 frames continuously over 500 ms "
+ + "and notify windows changed immediately");
+ mHandler.removeMessages(
+ MyHandler.MESSAGE_NOTIFY_WINDOWS_CHANGED_BY_UI_STABLE);
+
+ forceUpdateWindows();
+ } break;
+ }
+ }
+ }
+
+ /**
+ * This class represents information about a window from the
+ * surface flinger to the accessibility framework.
+ */
+ public static class AccessibilityWindow {
+ private static final Region TEMP_REGION = new Region();
+ private static final RectF TEMP_RECTF = new RectF();
+ // Data
+ private IWindow mWindow;
+ private int mDisplayId;
+ private int mFlags;
+ private int mType;
+ private int mPrivateFlags;
+ private boolean mIsPIPMenu;
+ private boolean mIsFocused;
+ private boolean mShouldMagnify;
+ private boolean mIgnoreDuetoRecentsAnimation;
+ private boolean mIsTrustedOverlay;
+ private final Region mTouchableRegionInScreen = new Region();
+ private final Region mTouchableRegionInWindow = new Region();
+ private final Region mLetterBoxBounds = new Region();
+ private WindowInfo mWindowInfo;
+
+ /**
+ * Returns the instance after initializing the internal data.
+ * @param service The window manager service.
+ * @param inputWindowHandle The window from the surface flinger.
+ * @param inverseMatrix The magnification spec inverse matrix.
+ */
+ public static AccessibilityWindow initializeData(WindowManagerService service,
+ InputWindowHandle inputWindowHandle, Matrix inverseMatrix, IBinder pipIBinder,
+ Matrix displayMatrix) {
+ final IWindow window = inputWindowHandle.getWindow();
+ final WindowState windowState = window != null ? service.mWindowMap.get(
+ window.asBinder()) : null;
+
+ final AccessibilityWindow instance = new AccessibilityWindow();
+
+ instance.mWindow = inputWindowHandle.getWindow();
+ instance.mDisplayId = inputWindowHandle.displayId;
+ instance.mFlags = inputWindowHandle.layoutParamsFlags;
+ instance.mType = inputWindowHandle.layoutParamsType;
+ instance.mIsPIPMenu = inputWindowHandle.getWindow().asBinder().equals(pipIBinder);
+
+ // TODO (b/199357848): gets the private flag of the window from other way.
+ instance.mPrivateFlags = windowState != null ? windowState.mAttrs.privateFlags : 0;
+ // TODO (b/199358208) : using new way to implement the focused window.
+ instance.mIsFocused = windowState != null && windowState.isFocused();
+ instance.mShouldMagnify = windowState == null || windowState.shouldMagnify();
+
+ final RecentsAnimationController controller = service.getRecentsAnimationController();
+ instance.mIgnoreDuetoRecentsAnimation = windowState != null && controller != null
+ && controller.shouldIgnoreForAccessibility(windowState);
+ instance.mIsTrustedOverlay = inputWindowHandle.trustedOverlay;
+
+ // TODO (b/199358388) : gets the letterbox bounds of the window from other way.
+ if (windowState != null && windowState.areAppWindowBoundsLetterboxed()) {
+ getLetterBoxBounds(windowState, instance.mLetterBoxBounds);
+ }
+
+ final Rect windowFrame = new Rect(inputWindowHandle.frameLeft,
+ inputWindowHandle.frameTop, inputWindowHandle.frameRight,
+ inputWindowHandle.frameBottom);
+ getTouchableRegionInWindow(instance.mShouldMagnify, inputWindowHandle.touchableRegion,
+ instance.mTouchableRegionInWindow, windowFrame, inverseMatrix, displayMatrix);
+ getUnMagnifiedTouchableRegion(instance.mShouldMagnify,
+ inputWindowHandle.touchableRegion, instance.mTouchableRegionInScreen,
+ inverseMatrix, displayMatrix);
+ instance.mWindowInfo = windowState != null
+ ? windowState.getWindowInfo() : getWindowInfoForWindowlessWindows(instance);
+
+ return instance;
+ }
+
+ /**
+ * Returns the touchable region in the screen.
+ * @param outRegion The touchable region.
+ */
+ public void getTouchableRegionInScreen(Region outRegion) {
+ outRegion.set(mTouchableRegionInScreen);
+ }
+
+ /**
+ * Returns the touchable region in the window.
+ * @param outRegion The touchable region.
+ */
+ public void getTouchableRegionInWindow(Region outRegion) {
+ outRegion.set(mTouchableRegionInWindow);
+ }
+
+ /**
+ * @return the layout parameter flag {@link android.view.WindowManager.LayoutParams#flags}.
+ */
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * @return the layout parameter type {@link android.view.WindowManager.LayoutParams#type}.
+ */
+ public int getType() {
+ return mType;
+ }
+
+ /**
+ * @return the layout parameter private flag
+ * {@link android.view.WindowManager.LayoutParams#privateFlags}.
+ */
+ public int getPrivateFlag() {
+ return mPrivateFlags;
+ }
+
+ /**
+ * @return the windowInfo {@link WindowInfo}.
+ */
+ public WindowInfo getWindowInfo() {
+ return mWindowInfo;
+ }
+
+ /**
+ * Gets the letter box bounds if activity bounds are letterboxed
+ * or letterboxed for display cutout.
+ *
+ * @return {@code true} there's a letter box bounds.
+ */
+ public Boolean setLetterBoxBoundsIfNeeded(Region outBounds) {
+ if (mLetterBoxBounds.isEmpty()) {
+ return false;
+ }
+
+ outBounds.set(mLetterBoxBounds);
+ return true;
+ }
+
+ /**
+ * @return true if this window should be magnified.
+ */
+ public boolean shouldMagnify() {
+ return mShouldMagnify;
+ }
+
+ /**
+ * @return true if this window is focused.
+ */
+ public boolean isFocused() {
+ return mIsFocused;
+ }
+
+ /**
+ * @return true if it's running the recent animation but not the target app.
+ */
+ public boolean ignoreRecentsAnimationForAccessibility() {
+ return mIgnoreDuetoRecentsAnimation;
+ }
+
+ /**
+ * @return true if this window is the trusted overlay.
+ */
+ public boolean isTrustedOverlay() {
+ return mIsTrustedOverlay;
+ }
+
+ /**
+ * @return true if this window is the navigation bar with the gesture mode.
+ */
+ public boolean isUntouchableNavigationBar() {
+ if (mType != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR) {
+ return false;
+ }
+
+ return mTouchableRegionInScreen.isEmpty();
+ }
+
+ /**
+ * @return true if this window is PIP menu.
+ */
+ public boolean isPIPMenu() {
+ return mIsPIPMenu;
+ }
+
+ private static void getTouchableRegionInWindow(boolean shouldMagnify, Region inRegion,
+ Region outRegion, Rect frame, Matrix inverseMatrix, Matrix displayMatrix) {
+ // Some modal windows, like the activity with Theme.dialog, has the full screen
+ // as its touchable region, but its window frame is smaller than the touchable
+ // region. The region we report should be the touchable area in the window frame
+ // for the consistency and match developers expectation.
+ // So we need to make the intersection between the frame and touchable region to
+ // obtain the real touch region in the screen.
+ Region touchRegion = TEMP_REGION;
+ touchRegion.set(inRegion);
+ touchRegion.op(frame, Region.Op.INTERSECT);
+
+ getUnMagnifiedTouchableRegion(shouldMagnify, touchRegion, outRegion, inverseMatrix,
+ displayMatrix);
+ }
+
+ /**
+ * Gets the un-magnified touchable region. If this window can be magnified and magnifying,
+ * we will transform the input touchable region by applying the inverse matrix of the
+ * magnification spec to get the un-magnified touchable region.
+ * @param shouldMagnify The window can be magnified.
+ * @param inRegion The touchable region of this window.
+ * @param outRegion The un-magnified touchable region of this window.
+ * @param inverseMatrix The inverse matrix of the magnification spec.
+ * @param displayMatrix The display transform matrix which takes display coordinates to
+ * logical display coordinates.
+ */
+ private static void getUnMagnifiedTouchableRegion(boolean shouldMagnify, Region inRegion,
+ Region outRegion, Matrix inverseMatrix, Matrix displayMatrix) {
+ if ((!shouldMagnify || inverseMatrix.isIdentity()) && displayMatrix.isIdentity()) {
+ outRegion.set(inRegion);
+ return;
+ }
+
+ forEachRect(inRegion, rect -> {
+ // Move to origin as all transforms are captured by the matrix.
+ RectF windowFrame = TEMP_RECTF;
+ windowFrame.set(rect);
+
+ inverseMatrix.mapRect(windowFrame);
+ displayMatrix.mapRect(windowFrame);
+ // Union all rects.
+ outRegion.union(new Rect((int) windowFrame.left, (int) windowFrame.top,
+ (int) windowFrame.right, (int) windowFrame.bottom));
+ });
+ }
+
+ private static WindowInfo getWindowInfoForWindowlessWindows(AccessibilityWindow window) {
+ WindowInfo windowInfo = WindowInfo.obtain();
+ windowInfo.displayId = window.mDisplayId;
+ windowInfo.type = window.mType;
+ windowInfo.token = window.mWindow.asBinder();
+ windowInfo.hasFlagWatchOutsideTouch = (window.mFlags
+ & WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH) != 0;
+ windowInfo.inPictureInPicture = false;
+
+ // There only are two windowless windows now, one is split window, and the other
+ // one is PIP.
+ if (windowInfo.type == TYPE_DOCK_DIVIDER) {
+ windowInfo.title = "Splitscreen Divider";
+ } else if (window.mIsPIPMenu) {
+ windowInfo.title = "Picture-in-Picture menu";
+ }
+ return windowInfo;
+ }
+
+ private static void getLetterBoxBounds(WindowState windowState, Region outRegion) {
+ final Rect letterboxInsets = windowState.mActivityRecord.getLetterboxInsets();
+ final Rect nonLetterboxRect = windowState.getBounds();
+
+ nonLetterboxRect.inset(letterboxInsets);
+ outRegion.set(windowState.getBounds());
+ outRegion.op(nonLetterboxRect, Region.Op.DIFFERENCE);
+ }
+
+ @Override
+ public String toString() {
+ String builder = "A11yWindow=[" + mWindow.asBinder()
+ + ", displayId=" + mDisplayId
+ + ", flag=0x" + Integer.toHexString(mFlags)
+ + ", type=" + mType
+ + ", privateFlag=0x" + Integer.toHexString(mPrivateFlags)
+ + ", focused=" + mIsFocused
+ + ", shouldMagnify=" + mShouldMagnify
+ + ", ignoreDuetoRecentsAnimation=" + mIgnoreDuetoRecentsAnimation
+ + ", isTrustedOverlay=" + mIsTrustedOverlay
+ + ", regionInScreen=" + mTouchableRegionInScreen
+ + ", touchableRegion=" + mTouchableRegionInWindow
+ + ", letterBoxBounds=" + mLetterBoxBounds
+ + ", isPIPMenu=" + mIsPIPMenu
+ + ", windowInfo=" + mWindowInfo
+ + "]";
+
+ return builder;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
index 30cd3c4ab8bf..1bb9ca770c45 100644
--- a/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
+++ b/services/core/java/com/android/server/wm/ActivityInterceptorCallback.java
@@ -54,6 +54,7 @@ public abstract class ActivityInterceptorCallback {
@IntDef(suffix = { "_ORDERED_ID" }, value = {
FIRST_ORDERED_ID,
COMMUNAL_MODE_ORDERED_ID,
+ PERMISSION_POLICY_ORDERED_ID,
LAST_ORDERED_ID // Update this when adding new ids
})
@Retention(RetentionPolicy.SOURCE)
@@ -70,10 +71,15 @@ public abstract class ActivityInterceptorCallback {
public static final int COMMUNAL_MODE_ORDERED_ID = 1;
/**
+ * The identifier for {@link com.android.server.policy.PermissionPolicyService} interceptor
+ */
+ public static final int PERMISSION_POLICY_ORDERED_ID = 2;
+
+ /**
* The final id, used by the framework to determine the valid range of ids. Update this when
* adding new ids.
*/
- static final int LAST_ORDERED_ID = COMMUNAL_MODE_ORDERED_ID;
+ static final int LAST_ORDERED_ID = PERMISSION_POLICY_ORDERED_ID;
/**
* Data class for storing the various arguments needed for activity interception.
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 0b0b70481589..c929cbbac263 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2134,7 +2134,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return activityInfo != null ? activityInfo.applicationInfo : null;
});
- final int typeParameter = mWmService.mStartingSurfaceController
+ final int typeParameter = StartingSurfaceController
.makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
allowTaskSnapshot, activityCreated, useEmpty, useLegacy, activityAllDrawn);
@@ -6616,13 +6616,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return splashScreenThemeResId;
}
+ void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
+ boolean startActivity, ActivityRecord sourceRecord) {
+ showStartingWindow(prev, newTask, taskSwitch, isProcessRunning(), startActivity,
+ sourceRecord);
+ }
+
/**
* @param prev Previous activity which contains a starting window.
+ * @param processRunning Whether the client process is running.
* @param startActivity Whether this activity is just created from starter.
* @param sourceRecord The source activity which start this activity.
*/
void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
- boolean startActivity, ActivityRecord sourceRecord) {
+ boolean processRunning, boolean startActivity, ActivityRecord sourceRecord) {
if (mTaskOverlay) {
// We don't show starting window for overlay activities.
return;
@@ -6647,7 +6654,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
&& task.getActivity((r) -> !r.finishing && r != this) == null;
final boolean scheduled = addStartingWindow(packageName, resolvedTheme,
- prev, newTask || newSingleActivity, taskSwitch, isProcessRunning(),
+ prev, newTask || newSingleActivity, taskSwitch, processRunning,
allowTaskSnapshot(), activityCreated, mSplashScreenStyleEmpty, allDrawn);
if (DEBUG_STARTING_WINDOW_VERBOSE && scheduled) {
Slog.d(TAG, "Scheduled starting window for " + this);
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index ecc85878353a..87fb2902dddb 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -455,6 +455,10 @@ public class ActivityStartController {
// Lock the loop to ensure the activities launched in a sequence.
synchronized (mService.mGlobalLock) {
mService.deferWindowLayout();
+ // To avoid creating multiple starting window when creating starting multiples
+ // activities, we defer the creation of the starting window once all start request
+ // are processed
+ mService.mWindowManager.mStartingSurfaceController.beginDeferAddStartingWindow();
try {
for (int i = 0; i < starters.length; i++) {
final int startResult = starters[i].setResultTo(resultTo)
@@ -480,6 +484,7 @@ public class ActivityStartController {
}
}
} finally {
+ mService.mWindowManager.mStartingSurfaceController.endDeferAddStartingWindow();
mService.continueWindowLayout();
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index a9142ef85608..23508d961b63 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -687,4 +687,7 @@ public abstract class ActivityTaskManagerInternal {
/** Get the most recent task excluding the first running task (the one on the front most). */
public abstract ActivityManager.RecentTaskInfo getMostRecentTaskFromBackground();
+
+ /** Get the app tasks for a package */
+ public abstract List<ActivityManager.AppTask> getAppTasks(String pkgName, int uid);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 15ebe2846513..ddd624d115c3 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -135,6 +135,7 @@ import android.app.Dialog;
import android.app.IActivityClientController;
import android.app.IActivityController;
import android.app.IActivityTaskManager;
+import android.app.IAppTask;
import android.app.IApplicationThread;
import android.app.IAssistDataReceiver;
import android.app.INotificationManager;
@@ -436,9 +437,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
private static final long START_AS_CALLER_TOKEN_EXPIRED_TIMEOUT =
START_AS_CALLER_TOKEN_TIMEOUT_IMPL + 20 * MINUTE_IN_MILLIS;
- // Activity tokens of system activities that are delegating their call to
- // #startActivityByCaller, keyed by the permissionToken granted to the delegate.
- final HashMap<IBinder, IBinder> mStartActivitySources = new HashMap<>();
+ // The component name of the delegated activities that are allowed to call
+ // #startActivityAsCaller with the one-time used permission token.
+ final HashMap<IBinder, ComponentName> mStartActivitySources = new HashMap<>();
// Permission tokens that have expired, but we remember for error reporting.
final ArrayList<IBinder> mExpiredStartAsCallerTokens = new ArrayList<>();
@@ -1512,7 +1513,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
- public IBinder requestStartActivityPermissionToken(IBinder delegatorToken) {
+ public IBinder requestStartActivityPermissionToken(ComponentName componentName) {
int callingUid = Binder.getCallingUid();
if (UserHandle.getAppId(callingUid) != SYSTEM_UID) {
throw new SecurityException("Only the system process can request a permission token, "
@@ -1520,7 +1521,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
IBinder permissionToken = new Binder();
synchronized (mGlobalLock) {
- mStartActivitySources.put(permissionToken, delegatorToken);
+ mStartActivitySources.put(permissionToken, componentName);
}
Message expireMsg = PooledLambda.obtainMessage(
@@ -1545,7 +1546,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// 1) The caller is an activity that is part of the core framework, and then only when it
// is running as the system.
// 2) The caller provides a valid permissionToken. Permission tokens are one-time use and
- // can only be requested by a system activity, which may then delegate this call to
+ // can only be requested from system uid, which may then delegate this call to
// another app.
final ActivityRecord sourceRecord;
final int targetUid;
@@ -1556,18 +1557,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
if (resultTo == null) {
throw new SecurityException("Must be called from an activity");
}
- final IBinder sourceToken;
+
+ sourceRecord = ActivityRecord.isInAnyTask(resultTo);
+ if (sourceRecord == null) {
+ throw new SecurityException("Called with bad activity token: " + resultTo);
+ }
+ if (sourceRecord.app == null) {
+ throw new SecurityException("Called without a process attached to activity");
+ }
+
+ final ComponentName componentName;
if (permissionToken != null) {
// To even attempt to use a permissionToken, an app must also have this signature
// permission.
mAmInternal.enforceCallingPermission(
android.Manifest.permission.START_ACTIVITY_AS_CALLER,
"startActivityAsCaller");
- // If called with a permissionToken, we want the sourceRecord from the delegator
- // activity that requested this token.
- sourceToken = mStartActivitySources.remove(permissionToken);
- if (sourceToken == null) {
- // Invalid permissionToken, check if it recently expired.
+ // If called with a permissionToken, the caller must be the same component that
+ // was allowed to use the permissionToken.
+ componentName = mStartActivitySources.remove(permissionToken);
+ if (!sourceRecord.mActivityComponent.equals(componentName)) {
if (mExpiredStartAsCallerTokens.contains(permissionToken)) {
throw new SecurityException("Called with expired permission token: "
+ permissionToken);
@@ -1577,33 +1586,21 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
} else {
- // This method was called directly by the source.
- sourceToken = resultTo;
- }
-
- sourceRecord = ActivityRecord.isInAnyTask(sourceToken);
- if (sourceRecord == null) {
- throw new SecurityException("Called with bad activity token: " + sourceToken);
- }
- if (sourceRecord.app == null) {
- throw new SecurityException("Called without a process attached to activity");
- }
-
- // Whether called directly or from a delegate, the source activity must be from the
- // android package.
- if (!sourceRecord.info.packageName.equals("android")) {
- throw new SecurityException("Must be called from an activity that is "
- + "declared in the android package");
- }
-
- if (UserHandle.getAppId(sourceRecord.app.mUid) != SYSTEM_UID) {
- // This is still okay, as long as this activity is running under the
- // uid of the original calling activity.
- if (sourceRecord.app.mUid != sourceRecord.launchedFromUid) {
- throw new SecurityException(
- "Calling activity in uid " + sourceRecord.app.mUid
- + " must be system uid or original calling uid "
- + sourceRecord.launchedFromUid);
+ // Whether called directly or from a delegate, the source activity must be from the
+ // android package.
+ if (!sourceRecord.info.packageName.equals("android")) {
+ throw new SecurityException("Must be called from an activity that is "
+ + "declared in the android package");
+ }
+ if (UserHandle.getAppId(sourceRecord.app.mUid) != SYSTEM_UID) {
+ // This is still okay, as long as this activity is running under the
+ // uid of the original calling activity.
+ if (sourceRecord.app.mUid != sourceRecord.launchedFromUid) {
+ throw new SecurityException(
+ "Calling activity in uid " + sourceRecord.app.mUid
+ + " must be system uid or original calling uid "
+ + sourceRecord.launchedFromUid);
+ }
}
}
if (ignoreTargetSecurity) {
@@ -2558,12 +2555,15 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public List<IBinder> getAppTasks(String callingPackage) {
- int callingUid = Binder.getCallingUid();
assertPackageMatchesCallingUid(callingPackage);
+ return getAppTasks(callingPackage, Binder.getCallingUid());
+ }
+
+ private List<IBinder> getAppTasks(String pkgName, int uid) {
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- return mRecentTasks.getAppTasksList(callingUid, callingPackage);
+ return mRecentTasks.getAppTasksList(uid, pkgName);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -6668,5 +6668,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
return targetTask;
}
+
+ @Override
+ public List<ActivityManager.AppTask> getAppTasks(String pkgName, int uid) {
+ ArrayList<ActivityManager.AppTask> tasks = new ArrayList<>();
+ List<IBinder> appTasks = ActivityTaskManagerService.this.getAppTasks(pkgName, uid);
+ int numAppTasks = appTasks.size();
+ for (int i = 0; i < numAppTasks; i++) {
+ tasks.add(new ActivityManager.AppTask(IAppTask.Stub.asInterface(appTasks.get(i))));
+ }
+ return tasks;
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 3d37278cd400..475a9fb36f92 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -799,19 +799,18 @@ public class AppTransitionController {
}
/**
- * Returns {@code true} if a given {@link WindowContainer} is an embedded Task.
+ * Returns {@code true} if a given {@link WindowContainer} is an embedded Task in
+ * {@link com.android.wm.shell.TaskView}.
*
* Note that this is a short term workaround to support Android Auto until it migrate to
* ShellTransition. This should only be used by {@link #getAnimationTargets}.
*
* TODO(b/213312721): Remove this predicate and its callers once ShellTransition is enabled.
*/
- private static boolean isEmbeddedTask(WindowContainer wc) {
+ private static boolean isTaskViewTask(WindowContainer wc) {
// We use Task#mRemoveWithTaskOrganizer to identify an embedded Task, but this is a hack and
// it is not guaranteed to work this logic in the future version.
- return !WindowManagerService.sEnableShellTransitions
- && wc instanceof Task
- && ((Task) wc).mRemoveWithTaskOrganizer;
+ return wc instanceof Task && ((Task) wc).mRemoveWithTaskOrganizer;
}
/**
@@ -860,7 +859,7 @@ public class AppTransitionController {
siblings.add(current);
boolean canPromote = true;
- if (isEmbeddedTask(current)) {
+ if (isTaskViewTask(current)) {
// Don't animate an embedded Task in app transition. This is a short term workaround
// to prevent conflict of surface hierarchy changes between legacy app transition
// and TaskView (b/205189147).
@@ -909,7 +908,7 @@ public class AppTransitionController {
for (int j = 0; j < parent.getChildCount(); ++j) {
final WindowContainer sibling = parent.getChildAt(j);
if (candidates.remove(sibling)) {
- if (!isEmbeddedTask(sibling)) {
+ if (!isTaskViewTask(sibling)) {
// Don't animate an embedded Task in app transition. This is a short
// term workaround to prevent conflict of surface hierarchy changes
// between legacy app transition and TaskView (b/205189147).
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
index 47622bc83417..9661e8d30b22 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
@@ -24,13 +24,11 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
-import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
import static android.window.DisplayAreaOrganizer.FEATURE_FULLSCREEN_MAGNIFICATION;
import static android.window.DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT;
import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER;
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED;
-import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL;
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature;
@@ -134,11 +132,6 @@ public abstract class DisplayAreaPolicy {
.except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR,
TYPE_NOTIFICATION_SHADE)
.build())
- .addFeature(new Feature.Builder(wmService.mPolicy,
- "OneHandedBackgroundPanel",
- FEATURE_ONE_HANDED_BACKGROUND_PANEL)
- .upTo(TYPE_WALLPAPER)
- .build())
.addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded",
FEATURE_ONE_HANDED)
.all()
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index c740f7b7c2e2..8e0435f1908f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -218,7 +218,6 @@ import android.view.Surface.Rotation;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;
-import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.WindowManager.DisplayImePolicy;
@@ -1425,7 +1424,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mWaitingForConfig = true;
if (mTransitionController.isShellTransitionsEnabled()) {
requestChangeTransitionIfNeeded(changes, null /* displayChange */);
- } else {
+ } else if (mLastHasContent) {
mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */, this);
}
sendNewConfiguration();
@@ -1702,8 +1701,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
case SOFT_INPUT_STATE_HIDDEN:
return false;
}
- return r.mLastImeShown && mInputMethodWindow != null && mInputMethodWindow.mHasSurface
- && mInputMethodWindow.mViewVisibility == View.VISIBLE;
+ return r.mLastImeShown;
}
/** Returns {@code true} if the top activity is transformed with the new rotation of display. */
@@ -3222,6 +3220,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
void requestChangeTransitionIfNeeded(@ActivityInfo.Config int changes,
@Nullable TransitionRequestInfo.DisplayChange displayChange) {
+ if (!mLastHasContent) return;
final TransitionController controller = mTransitionController;
if (controller.isCollecting()) {
if (displayChange != null) {
@@ -4198,10 +4197,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
final SurfaceControl newParent = computeImeParent();
if (newParent != null && newParent != mInputMethodSurfaceParent) {
mInputMethodSurfaceParent = newParent;
- getPendingTransaction().reparent(mImeWindowsContainer.mSurfaceControl, newParent);
+ getSyncTransaction().reparent(mImeWindowsContainer.mSurfaceControl, newParent);
// When surface parent is removed, the relative layer will also be removed. We need to
// do a force update to make sure there is a layer set for the new parent.
- assignRelativeLayerForIme(getPendingTransaction(), true /* forceUpdate */);
+ assignRelativeLayerForIme(getSyncTransaction(), true /* forceUpdate */);
scheduleAnimation();
}
}
@@ -4995,8 +4994,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// exists so it get's layered above the starting window.
if (imeTarget != null && !(imeTarget.mActivityRecord != null
&& imeTarget.mActivityRecord.hasStartingWindow())) {
+ final WindowToken imeControlTargetToken =
+ mImeControlTarget != null && mImeControlTarget.getWindow() != null
+ ? mImeControlTarget.getWindow().mToken : null;
final boolean canImeTargetSetRelativeLayer = imeTarget.getSurfaceControl() != null
- && imeTarget == mImeControlTarget
+ && imeTarget.mToken == imeControlTargetToken
&& !imeTarget.inMultiWindowMode()
&& imeTarget.mToken.getActivity(app -> app.isAnimating(TRANSITION | PARENTS,
ANIMATION_TYPE_ALL & ~ANIMATION_TYPE_RECENTS)) == null;
@@ -5087,6 +5089,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return mLastHasContent;
}
+ @VisibleForTesting
+ void setLastHasContent() {
+ mLastHasContent = true;
+ }
+
void registerPointerEventListener(@NonNull PointerEventListener listener) {
mPointerEventDispatcher.registerInputEventListener(listener);
}
diff --git a/services/core/java/com/android/server/wm/FadeRotationAnimationController.java b/services/core/java/com/android/server/wm/FadeRotationAnimationController.java
index c85e04dbfa15..2cefd9935870 100644
--- a/services/core/java/com/android/server/wm/FadeRotationAnimationController.java
+++ b/services/core/java/com/android/server/wm/FadeRotationAnimationController.java
@@ -256,7 +256,7 @@ public class FadeRotationAnimationController extends FadeAnimationController {
false /* applyFixedTransformationHint */);
for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
final SurfaceControl leash = mTargetWindowTokens.valueAt(i);
- if (leash != null) {
+ if (leash != null && leash.isValid()) {
rotator.applyTransform(t, leash);
}
}
@@ -265,7 +265,7 @@ public class FadeRotationAnimationController extends FadeAnimationController {
// Hide the windows immediately because a screenshot layer should cover the screen.
for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
final SurfaceControl leash = mTargetWindowTokens.valueAt(i);
- if (leash != null) {
+ if (leash != null && leash.isValid()) {
t.setAlpha(leash, 0f);
}
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 3f2e97505765..5a420caa176c 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -983,29 +983,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mWmService.checkDrawnWindowsLocked();
}
- final int N = mWmService.mPendingRemove.size();
- if (N > 0) {
- if (mWmService.mPendingRemoveTmp.length < N) {
- mWmService.mPendingRemoveTmp = new WindowState[N + 10];
- }
- mWmService.mPendingRemove.toArray(mWmService.mPendingRemoveTmp);
- mWmService.mPendingRemove.clear();
- ArrayList<DisplayContent> displayList = new ArrayList();
- for (i = 0; i < N; i++) {
- final WindowState w = mWmService.mPendingRemoveTmp[i];
- w.removeImmediately();
- final DisplayContent displayContent = w.getDisplayContent();
- if (displayContent != null && !displayList.contains(displayContent)) {
- displayList.add(displayContent);
- }
- }
-
- for (int j = displayList.size() - 1; j >= 0; --j) {
- final DisplayContent dc = displayList.get(j);
- dc.assignWindowLayers(true /*setLayoutNeeded*/);
- }
- }
-
forAllDisplays(dc -> {
dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
dc.updateSystemGestureExclusion();
@@ -2052,24 +2029,29 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
try {
final Task task = r.getTask();
- // If the activity in current PIP task needs to be moved back to the parent Task of next
- // PIP activity, we can't use that parent Task as the next PIP Task.
- // Because we need to start the Shell transition from the root Task, we delay to dismiss
- // the current PIP task until root Task is ready.
- boolean origPipWillBeMovedToTask = false;
+ // Create a transition now to collect the current pinned Task dismiss. Only do the
+ // create here as the Task (trigger) to enter PIP is not ready yet.
+ final TransitionController transitionController = task.mTransitionController;
+ Transition newTransition = null;
+ if (transitionController.isCollecting()) {
+ transitionController.setReady(task, false /* ready */);
+ } else if (transitionController.getTransitionPlayer() != null) {
+ newTransition = transitionController.createTransition(TRANSIT_PIP);
+ }
+
+ // This will change the root pinned task's windowing mode to its original mode, ensuring
+ // we only have one root task that is in pinned mode.
final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask();
if (rootPinnedTask != null) {
- final ActivityRecord topPipActivity = rootPinnedTask.getTopMostActivity();
- if (topPipActivity != null && topPipActivity.getLastParentBeforePip() == task) {
- origPipWillBeMovedToTask = true;
- }
+ transitionController.collect(rootPinnedTask);
+ rootPinnedTask.dismissPip();
}
// Set a transition to ensure that we don't immediately try and update the visibility
// of the activity entering PIP
r.getDisplayContent().prepareAppTransition(TRANSIT_NONE);
- final boolean singleActivity = task.getChildCount() == 1 && !origPipWillBeMovedToTask;
+ final boolean singleActivity = task.getChildCount() == 1;
final Task rootTask;
if (singleActivity) {
rootTask = task;
@@ -2123,7 +2105,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
final ActivityRecord oldTopActivity = task.getTopMostActivity();
if (oldTopActivity != null && oldTopActivity.isState(STOPPED)
&& task.getDisplayContent().mAppTransition.containsTransitRequest(
- TRANSIT_TO_BACK) && !origPipWillBeMovedToTask) {
+ TRANSIT_TO_BACK)) {
task.getDisplayContent().mClosingApps.add(oldTopActivity);
oldTopActivity.mRequestForceTransition = true;
}
@@ -2137,14 +2119,13 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// display area, so reparent.
rootTask.reparent(taskDisplayArea, true /* onTop */);
}
- rootTask.mTransitionController.requestTransitionIfNeeded(TRANSIT_PIP, rootTask);
- // This will change the root pinned task's windowing mode to its original mode, ensuring
- // we only have one root task that is in pinned mode.
- if (rootPinnedTask != null) {
- rootTask.mTransitionController.collect(rootPinnedTask);
- rootPinnedTask.dismissPip();
+ // The new PIP Task is ready, start the transition before updating the windowing mode.
+ if (newTransition != null) {
+ transitionController.requestStartTransition(newTransition, rootTask,
+ null /* remoteTransition */, null /* displayChange */);
}
+ transitionController.collect(rootTask);
// Defer the windowing mode change until after the transition to prevent the activity
// from doing work and changing the activity visuals while animating
diff --git a/services/core/java/com/android/server/wm/ShellRoot.java b/services/core/java/com/android/server/wm/ShellRoot.java
index 6ed59e96c700..f9d7b53e4e78 100644
--- a/services/core/java/com/android/server/wm/ShellRoot.java
+++ b/services/core/java/com/android/server/wm/ShellRoot.java
@@ -25,15 +25,14 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMAT
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.Point;
-import android.graphics.Rect;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.IWindow;
import android.view.SurfaceControl;
-import android.view.WindowInfo;
import android.view.WindowManager;
import android.view.animation.Animation;
@@ -136,47 +135,12 @@ public class ShellRoot {
ANIMATION_TYPE_WINDOW_ANIMATION);
}
- WindowInfo getWindowInfo() {
- if (mShellRootLayer != SHELL_ROOT_LAYER_DIVIDER
- && mShellRootLayer != SHELL_ROOT_LAYER_PIP) {
- return null;
- }
- if (mShellRootLayer == SHELL_ROOT_LAYER_DIVIDER
- && !mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
- return null;
- }
- if (mShellRootLayer == SHELL_ROOT_LAYER_PIP
- && mDisplayContent.getDefaultTaskDisplayArea().getRootPinnedTask() == null) {
- return null;
- }
- if (mAccessibilityWindow == null) {
- return null;
- }
- WindowInfo windowInfo = WindowInfo.obtain();
- windowInfo.displayId = mToken.getDisplayArea().getDisplayContent().mDisplayId;
- windowInfo.type = mToken.windowType;
- windowInfo.layer = mToken.getWindowLayerFromType();
- windowInfo.token = mAccessibilityWindow.asBinder();
- windowInfo.focused = false;
- windowInfo.hasFlagWatchOutsideTouch = false;
- final Rect regionRect = new Rect();
-
-
- // DividerView
- if (mShellRootLayer == SHELL_ROOT_LAYER_DIVIDER) {
- windowInfo.inPictureInPicture = false;
- mDisplayContent.getDockedDividerController().getTouchRegion(regionRect);
- windowInfo.regionInScreen.set(regionRect);
- windowInfo.title = "Splitscreen Divider";
- }
- // PipMenuView
- if (mShellRootLayer == SHELL_ROOT_LAYER_PIP) {
- windowInfo.inPictureInPicture = true;
- mDisplayContent.getDefaultTaskDisplayArea().getRootPinnedTask().getBounds(regionRect);
- windowInfo.regionInScreen.set(regionRect);
- windowInfo.title = "Picture-in-Picture menu";
+ @Nullable
+ IBinder getAccessibilityWindowToken() {
+ if (mAccessibilityWindow != null) {
+ return mAccessibilityWindow.asBinder();
}
- return windowInfo;
+ return null;
}
void setAccessibilityWindow(IWindow window) {
@@ -197,9 +161,5 @@ public class ShellRoot {
mAccessibilityWindow = null;
}
}
- if (mDisplayContent.mWmService.mAccessibilityController.hasCallbacks()) {
- mDisplayContent.mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(
- mDisplayContent.getDisplayId());
- }
}
}
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index 5fe40766fb66..eb73cd807204 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -34,6 +34,7 @@ import android.content.pm.ApplicationInfo;
import android.util.Slog;
import android.window.TaskSnapshot;
+import java.util.ArrayList;
import java.util.function.Supplier;
/**
@@ -45,6 +46,14 @@ public class StartingSurfaceController {
private final WindowManagerService mService;
private final SplashScreenExceptionList mSplashScreenExceptionsList;
+ // Cache status while deferring add starting window
+ boolean mInitProcessRunning;
+ boolean mInitNewTask;
+ boolean mInitTaskSwitch;
+ private final ArrayList<DeferringStartingWindowRecord> mDeferringAddStartActivities =
+ new ArrayList<>();
+ private boolean mDeferringAddStartingWindow;
+
public StartingSurfaceController(WindowManagerService wm) {
mService = wm;
mSplashScreenExceptionsList = new SplashScreenExceptionList(wm.mContext.getMainExecutor());
@@ -70,7 +79,7 @@ public class StartingSurfaceController {
return mSplashScreenExceptionsList.isException(packageName, targetSdk, infoProvider);
}
- int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
+ static int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
boolean useEmpty, boolean useLegacy, boolean activityDrawn) {
int parameter = 0;
@@ -142,6 +151,82 @@ public class StartingSurfaceController {
}
}
+ private static final class DeferringStartingWindowRecord {
+ final ActivityRecord mDeferring;
+ final ActivityRecord mPrev;
+ final ActivityRecord mSource;
+
+ DeferringStartingWindowRecord(ActivityRecord deferring, ActivityRecord prev,
+ ActivityRecord source) {
+ mDeferring = deferring;
+ mPrev = prev;
+ mSource = source;
+ }
+ }
+
+ /**
+ * Shows a starting window while starting a new activity. Do not use this method to create a
+ * starting window for an existing activity.
+ */
+ void showStartingWindow(ActivityRecord target, ActivityRecord prev,
+ boolean newTask, boolean isTaskSwitch, ActivityRecord source) {
+ if (mDeferringAddStartingWindow) {
+ addDeferringRecord(target, prev, newTask, isTaskSwitch, source);
+ } else {
+ target.showStartingWindow(prev, newTask, isTaskSwitch, true /* startActivity */,
+ source);
+ }
+ }
+
+ /**
+ * Queueing the starting activity status while deferring add starting window.
+ * @see Task#startActivityLocked
+ */
+ private void addDeferringRecord(ActivityRecord deferring, ActivityRecord prev,
+ boolean newTask, boolean isTaskSwitch, ActivityRecord source) {
+ // Set newTask, taskSwitch, processRunning form first activity because those can change
+ // after first activity started.
+ if (mDeferringAddStartActivities.isEmpty()) {
+ mInitProcessRunning = deferring.isProcessRunning();
+ mInitNewTask = newTask;
+ mInitTaskSwitch = isTaskSwitch;
+ }
+ mDeferringAddStartActivities.add(new DeferringStartingWindowRecord(
+ deferring, prev, source));
+ }
+
+ private void showStartingWindowFromDeferringActivities() {
+ // Attempt to add starting window from the top-most activity.
+ for (int i = mDeferringAddStartActivities.size() - 1; i >= 0; --i) {
+ final DeferringStartingWindowRecord next = mDeferringAddStartActivities.get(i);
+ next.mDeferring.showStartingWindow(next.mPrev, mInitNewTask, mInitTaskSwitch,
+ mInitProcessRunning, true /* startActivity */, next.mSource);
+ // If one succeeds, it is done.
+ if (next.mDeferring.mStartingData != null) {
+ break;
+ }
+ }
+ mDeferringAddStartActivities.clear();
+ }
+
+ /**
+ * Begin deferring add starting window in one pass.
+ * This is used to deferring add starting window while starting multiples activities because
+ * system only need to provide a starting window to the top-visible activity.
+ * Most call {@link #endDeferAddStartingWindow} when starting activities process finished.
+ * @see #endDeferAddStartingWindow()
+ */
+ void beginDeferAddStartingWindow() {
+ mDeferringAddStartingWindow = true;
+ }
+
+ /**
+ * End deferring add starting window.
+ */
+ void endDeferAddStartingWindow() {
+ mDeferringAddStartingWindow = false;
+ showStartingWindowFromDeferringActivities();
+ }
final class StartingSurface {
private final Task mTask;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7617726e1fcd..43038ce32649 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -5149,8 +5149,8 @@ class Task extends TaskFragment {
final ActivityRecord prev = baseTask.getActivity(
a -> a.mStartingData != null && a.showToCurrentUser());
- r.showStartingWindow(prev, newTask, isTaskSwitch,
- true /* startActivity */, sourceRecord);
+ mWmService.mStartingSurfaceController.showStartingWindow(r, prev, newTask,
+ isTaskSwitch, sourceRecord);
}
} else {
// If this is the first activity, don't do any fancy animations,
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index fe405e5b3af8..fc154a8b3179 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -107,7 +107,7 @@ class WallpaperWindowToken extends WindowToken {
/** Returns {@code true} if visibility is changed. */
boolean updateWallpaperWindows(boolean visible) {
boolean changed = false;
- if (isVisible() != visible) {
+ if (mVisibleRequested != visible) {
ProtoLog.d(WM_DEBUG_WALLPAPER, "Wallpaper token %s visible=%b",
token, visible);
setVisibility(visible);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7be128b53f8c..b5e6f49146f1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -222,7 +222,6 @@ import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.MergedConfiguration;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.TimeUtils;
import android.util.TypedValue;
@@ -588,20 +587,6 @@ public class WindowManagerService extends IWindowManager.Stub
final ArrayList<WindowState> mResizingWindows = new ArrayList<>();
/**
- * Windows whose animations have ended and now must be removed.
- */
- final ArrayList<WindowState> mPendingRemove = new ArrayList<>();
-
- /**
- * Used when processing mPendingRemove to avoid working on the original array.
- */
- WindowState[] mPendingRemoveTmp = new WindowState[20];
-
- // TODO: use WindowProcessController once go/wm-unified is done.
- /** Mapping of process pids to configurations */
- final SparseArray<Configuration> mProcessConfigurations = new SparseArray<>();
-
- /**
* Windows whose surface should be destroyed.
*/
final ArrayList<WindowState> mDestroySurface = new ArrayList<>();
@@ -2038,7 +2023,6 @@ public class WindowManagerService extends IWindowManager.Stub
dc.mWinRemovedSinceNullFocus.add(win);
}
mEmbeddedWindowController.onWindowRemoved(win);
- mPendingRemove.remove(win);
mResizingWindows.remove(win);
updateNonSystemOverlayWindowsVisibilityIfNeeded(win, false /* surfaceShown */);
mWindowsChanged = true;
@@ -6342,23 +6326,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
- if (mPendingRemove.size() > 0) {
- pw.println();
- pw.println(" Remove pending for:");
- for (int i=mPendingRemove.size()-1; i>=0; i--) {
- WindowState w = mPendingRemove.get(i);
- if (windows == null || windows.contains(w)) {
- pw.print(" Remove #"); pw.print(i); pw.print(' ');
- pw.print(w);
- if (dumpAll) {
- pw.println(":");
- w.dump(pw, " ", true);
- } else {
- pw.println();
- }
- }
- }
- }
if (mForceRemoves != null && mForceRemoves.size() > 0) {
pw.println();
pw.println(" Windows force removing:");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 573ff2ff9963..5bbe2cd853f6 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4809,9 +4809,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (isAnimating()) {
return;
}
- if (mWmService.mAccessibilityController.hasCallbacks()) {
- mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(getDisplayId());
- }
if (!isSelfOrAncestorWindowAnimatingExit()) {
return;
@@ -4838,15 +4835,20 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (hasSurface) {
mWmService.mDestroySurface.add(this);
}
- if (mRemoveOnExit) {
- mWmService.mPendingRemove.add(this);
- mRemoveOnExit = false;
- }
}
mAnimatingExit = false;
getDisplayContent().mWallpaperController.hideWallpapers(this);
}
+ @Override
+ boolean handleCompleteDeferredRemoval() {
+ if (mRemoveOnExit) {
+ mRemoveOnExit = false;
+ removeImmediately();
+ }
+ return super.handleCompleteDeferredRemoval();
+ }
+
boolean clearAnimatingFlags() {
boolean didSomething = false;
// We don't want to clear it out for windows that get replaced, because the
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 4190a91710fc..94bc22a05d7a 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -59,6 +59,9 @@ using android::base::unique_fd;
namespace android {
+static bool cancelRunningCompaction;
+static bool compactionInProgress;
+
// Legacy method for compacting processes, any new code should
// use compactProcess instead.
static inline void compactProcessProcfs(int pid, const std::string& compactionType) {
@@ -83,9 +86,18 @@ static int64_t compactMemory(const std::vector<Vma>& vmas, int pid, int madviseT
// Skip compaction if failed to open pidfd with any error
return -errno;
}
+ compactionInProgress = true;
+ cancelRunningCompaction = false;
int64_t totalBytesCompacted = 0;
for (int iBase = 0; iBase < vmas.size(); iBase += UIO_MAXIOV) {
+ if (CC_UNLIKELY(cancelRunningCompaction)) {
+ // There could be a significant delay betweenwhen a compaction
+ // is requested and when it is handled during this time
+ // our OOM adjust could have improved.
+ cancelRunningCompaction = false;
+ break;
+ }
int totalVmasToKernel = std::min(UIO_MAXIOV, (int)(vmas.size() - iBase));
for (int iVec = 0, iVma = iBase; iVec < totalVmasToKernel; ++iVec, ++iVma) {
vmasToKernel[iVec].iov_base = (void*)vmas[iVma].start;
@@ -95,11 +107,13 @@ static int64_t compactMemory(const std::vector<Vma>& vmas, int pid, int madviseT
auto bytesCompacted =
process_madvise(pidfd, vmasToKernel, totalVmasToKernel, madviseType, 0);
if (CC_UNLIKELY(bytesCompacted == -1)) {
+ compactionInProgress = false;
return -errno;
}
totalBytesCompacted += bytesCompacted;
}
+ compactionInProgress = false;
return totalBytesCompacted;
}
@@ -228,6 +242,12 @@ static void com_android_server_am_CachedAppOptimizer_compactSystem(JNIEnv *, job
}
}
+static void com_android_server_am_CachedAppOptimizer_cancelCompaction(JNIEnv*, jobject) {
+ if (compactionInProgress) {
+ cancelRunningCompaction = true;
+ }
+}
+
static void com_android_server_am_CachedAppOptimizer_compactProcess(JNIEnv*, jobject, jint pid,
jint compactionFlags) {
compactProcessOrFallback(pid, compactionFlags);
@@ -279,6 +299,8 @@ static jstring com_android_server_am_CachedAppOptimizer_getFreezerCheckPath(JNIE
static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
+ {"cancelCompaction", "()V",
+ (void*)com_android_server_am_CachedAppOptimizer_cancelCompaction},
{"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem},
{"compactProcess", "(II)V", (void*)com_android_server_am_CachedAppOptimizer_compactProcess},
{"freezeBinder", "(IZ)I", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder},
diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
index 546b075ea0be..b484796af6e2 100644
--- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp
+++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp
@@ -61,8 +61,8 @@ static struct {
static struct {
jfieldID startAmplitude;
jfieldID endAmplitude;
- jfieldID startFrequency;
- jfieldID endFrequency;
+ jfieldID startFrequencyHz;
+ jfieldID endFrequencyHz;
jfieldID duration;
} sRampClassInfo;
@@ -157,8 +157,8 @@ static aidl::ActivePwle activePwleFromJavaPrimitive(JNIEnv* env, jobject ramp) {
static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.startAmplitude));
pwle.endAmplitude = static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.endAmplitude));
pwle.startFrequency =
- static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.startFrequency));
- pwle.endFrequency = static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.endFrequency));
+ static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.startFrequencyHz));
+ pwle.endFrequency = static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.endFrequencyHz));
pwle.duration = static_cast<int32_t>(env->GetIntField(ramp, sRampClassInfo.duration));
return pwle;
}
@@ -363,7 +363,7 @@ static void vibratorAlwaysOnDisable(JNIEnv* env, jclass /* clazz */, jlong ptr,
}
static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr,
- jfloat suggestedSafeRange, jobject vibratorInfoBuilder) {
+ jobject vibratorInfoBuilder) {
VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
if (wrapper == nullptr) {
ALOGE("vibratorGetInfo failed because native wrapper was not initialized");
@@ -437,9 +437,9 @@ static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr,
env->SetFloatArrayRegion(maxAmplitudes, 0, amplitudes.size(),
reinterpret_cast<jfloat*>(amplitudes.data()));
}
- jobject frequencyMapping = env->NewObject(sFrequencyMappingClass, sFrequencyMappingCtor,
- minFrequency, resonantFrequency, frequencyResolution,
- suggestedSafeRange, maxAmplitudes);
+ jobject frequencyMapping =
+ env->NewObject(sFrequencyMappingClass, sFrequencyMappingCtor, resonantFrequency,
+ minFrequency, frequencyResolution, maxAmplitudes);
env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setFrequencyMapping,
frequencyMapping);
@@ -463,7 +463,7 @@ static const JNINativeMethod method_table[] = {
{"setExternalControl", "(JZ)V", (void*)vibratorSetExternalControl},
{"alwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable},
{"alwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable},
- {"getInfo", "(JFLandroid/os/VibratorInfo$Builder;)Z", (void*)vibratorGetInfo},
+ {"getInfo", "(JLandroid/os/VibratorInfo$Builder;)Z", (void*)vibratorGetInfo},
};
int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env) {
@@ -481,13 +481,13 @@ int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env
jclass rampClass = FindClassOrDie(env, "android/os/vibrator/RampSegment");
sRampClassInfo.startAmplitude = GetFieldIDOrDie(env, rampClass, "mStartAmplitude", "F");
sRampClassInfo.endAmplitude = GetFieldIDOrDie(env, rampClass, "mEndAmplitude", "F");
- sRampClassInfo.startFrequency = GetFieldIDOrDie(env, rampClass, "mStartFrequency", "F");
- sRampClassInfo.endFrequency = GetFieldIDOrDie(env, rampClass, "mEndFrequency", "F");
+ sRampClassInfo.startFrequencyHz = GetFieldIDOrDie(env, rampClass, "mStartFrequencyHz", "F");
+ sRampClassInfo.endFrequencyHz = GetFieldIDOrDie(env, rampClass, "mEndFrequencyHz", "F");
sRampClassInfo.duration = GetFieldIDOrDie(env, rampClass, "mDuration", "I");
jclass frequencyMappingClass = FindClassOrDie(env, "android/os/VibratorInfo$FrequencyMapping");
sFrequencyMappingClass = static_cast<jclass>(env->NewGlobalRef(frequencyMappingClass));
- sFrequencyMappingCtor = GetMethodIDOrDie(env, sFrequencyMappingClass, "<init>", "(FFFF[F)V");
+ sFrequencyMappingCtor = GetMethodIDOrDie(env, sFrequencyMappingClass, "<init>", "(FFF[F)V");
jclass vibratorInfoBuilderClass = FindClassOrDie(env, "android/os/VibratorInfo$Builder");
sVibratorInfoBuilderClassInfo.setCapabilities =
diff --git a/services/incremental/TEST_MAPPING b/services/incremental/TEST_MAPPING
index f2ad068854c4..9fe090a400c8 100644
--- a/services/incremental/TEST_MAPPING
+++ b/services/incremental/TEST_MAPPING
@@ -10,6 +10,12 @@
},
{
"name": "CtsIncrementalInstallHostTestCases"
+ },
+ {
+ "name": "libincfs-test"
+ },
+ {
+ "name": "service.incremental_test"
}
],
"presubmit-large": [
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 29797a549e49..5fcee9b4f69e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -310,6 +310,8 @@ public final class SystemServer implements Dumpable {
"com.android.clockwork.connectivity.WearConnectivityService";
private static final String WEAR_POWER_SERVICE_CLASS =
"com.android.clockwork.power.WearPowerService";
+ private static final String HEALTH_SERVICE_CLASS =
+ "com.google.android.clockwork.healthservices.HealthService";
private static final String WEAR_SIDEKICK_SERVICE_CLASS =
"com.google.android.clockwork.sidekick.SidekickService";
private static final String WEAR_DISPLAYOFFLOAD_SERVICE_CLASS =
@@ -920,12 +922,6 @@ public final class SystemServer implements Dumpable {
startBootstrapServices(t);
startCoreServices(t);
startOtherServices(t);
- // Apex services must be the last category of services to start. No other service must
- // be starting after this point. This is to prevent unnessary stability issues when
- // these apexes are updated outside of OTA; and to avoid breaking dependencies from
- // system into apexes.
- // TODO(satayev): lock mSystemServiceManager.startService to stop accepting new services
- // after this step
startApexServices(t);
} catch (Throwable ex) {
Slog.e("System", "******************************************");
@@ -1460,13 +1456,18 @@ public final class SystemServer implements Dumpable {
ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
t.traceEnd();
- t.traceBegin("StartTelecomLoaderService");
- mSystemServiceManager.startService(TelecomLoaderService.class);
- t.traceEnd();
+ // TelecomLoader hooks into classes with defined HFP logic,
+ // so check for either telephony or microphone.
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_MICROPHONE) ||
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ t.traceBegin("StartTelecomLoaderService");
+ mSystemServiceManager.startService(TelecomLoaderService.class);
+ t.traceEnd();
+ }
t.traceBegin("StartTelephonyRegistry");
telephonyRegistry = new TelephonyRegistry(
- context, new TelephonyRegistry.ConfigurationProvider());
+ context, new TelephonyRegistry.ConfigurationProvider());
ServiceManager.addService("telephony.registry", telephonyRegistry);
t.traceEnd();
@@ -1903,7 +1904,7 @@ public final class SystemServer implements Dumpable {
t.traceBegin("StartNetworkStatsService");
try {
- networkStats = NetworkStatsService.create(context, networkManagement);
+ networkStats = NetworkStatsService.create(context);
ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
} catch (Throwable e) {
reportWtf("starting NetworkStats Service", e);
@@ -2500,6 +2501,10 @@ public final class SystemServer implements Dumpable {
mSystemServiceManager.startService(WEAR_POWER_SERVICE_CLASS);
t.traceEnd();
+ t.traceBegin("StartHealthService");
+ mSystemServiceManager.startService(HEALTH_SERVICE_CLASS);
+ t.traceEnd();
+
t.traceBegin("StartWearConnectivityService");
mSystemServiceManager.startService(WEAR_CONNECTIVITY_SERVICE_CLASS);
t.traceEnd();
@@ -2572,10 +2577,12 @@ public final class SystemServer implements Dumpable {
mActivityManagerService.enterSafeMode();
}
- // MMS service broker
- t.traceBegin("StartMmsService");
- mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
- t.traceEnd();
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ // MMS service broker
+ t.traceBegin("StartMmsService");
+ mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
+ t.traceEnd();
+ }
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOFILL)) {
t.traceBegin("StartAutoFillService");
@@ -2991,9 +2998,7 @@ public final class SystemServer implements Dumpable {
t.traceEnd();
t.traceBegin("MakeTelephonyRegistryReady");
try {
- if (telephonyRegistryF != null) {
- telephonyRegistryF.systemRunning();
- }
+ if (telephonyRegistryF != null) telephonyRegistryF.systemRunning();
} catch (Throwable e) {
reportWtf("Notifying TelephonyRegistry running", e);
}
@@ -3007,15 +3012,15 @@ public final class SystemServer implements Dumpable {
reportWtf("Notifying MediaRouterService running", e);
}
t.traceEnd();
- t.traceBegin("MakeMmsServiceReady");
- try {
- if (mmsServiceF != null) {
- mmsServiceF.systemRunning();
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ t.traceBegin("MakeMmsServiceReady");
+ try {
+ if (mmsServiceF != null) mmsServiceF.systemRunning();
+ } catch (Throwable e) {
+ reportWtf("Notifying MmsService running", e);
}
- } catch (Throwable e) {
- reportWtf("Notifying MmsService running", e);
+ t.traceEnd();
}
- t.traceEnd();
t.traceBegin("IncidentDaemonReady");
try {
@@ -3051,11 +3056,14 @@ public final class SystemServer implements Dumpable {
/**
* Starts system services defined in apexes.
+ *
+ * <p>Apex services must be the last category of services to start. No other service must be
+ * starting after this point. This is to prevent unnecessary stability issues when these apexes
+ * are updated outside of OTA; and to avoid breaking dependencies from system into apexes.
*/
private void startApexServices(@NonNull TimingsTraceAndSlog t) {
t.traceBegin("startApexServices");
Map<String, String> services = ApexManager.getInstance().getApexSystemServices();
- // TODO(satayev): filter out already started services
// TODO(satayev): introduce android:order for services coming the same apexes
for (String name : new TreeSet<>(services.keySet())) {
String jarPath = services.get(name);
@@ -3067,6 +3075,10 @@ public final class SystemServer implements Dumpable {
}
t.traceEnd();
}
+
+ // make sure no other services are started after this point
+ mSystemServiceManager.sealStartedServices();
+
t.traceEnd(); // startApexServices
}
diff --git a/services/midi/OWNERS b/services/midi/OWNERS
new file mode 100644
index 000000000000..f4d51f91b51b
--- /dev/null
+++ b/services/midi/OWNERS
@@ -0,0 +1 @@
+philburk@google.com
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 8538603d4180..635f1360ff73 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -40,26 +40,26 @@ android_test {
],
static_libs: [
- "frameworks-base-testutils",
- "services.core",
- "services.devicepolicy",
- "services.net",
- "services.usage",
- "service-jobscheduler",
- "service-permission.impl",
- "service-blobstore",
"androidx.test.core",
"androidx.test.runner",
"androidx.test.ext.truth",
- "mockito-target-extended-minus-junit4",
- "platform-test-annotations",
- "truth-prebuilt",
+ "frameworks-base-testutils",
"hamcrest-library",
- "servicestests-utils-mockito-extended",
+ "kotlin-test",
"mockingservicestests-utils-mockito",
+ "mockito-target-extended-minus-junit4",
+ "platform-test-annotations",
+ "service-blobstore",
+ "service-jobscheduler",
+ "service-permission.impl",
+ "services.core",
+ "services.devicepolicy",
+ "services.net",
+ "services.usage",
"servicestests-core-utils",
+ "servicestests-utils-mockito-extended",
"testables",
- "kotlin-test",
+ "truth-prebuilt",
// TODO: remove once Android migrates to JUnit 4.12, which provides assertThrows
"testng",
],
diff --git a/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java
deleted file mode 100644
index c46884f51651..000000000000
--- a/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.communal;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.spy;
-
-import android.Manifest;
-import android.app.communal.ICommunalManager;
-import android.content.ContextWrapper;
-import android.os.RemoteException;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoSession;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.mockito.quality.Strictness;
-
-/**
- * Test class for {@link CommunalManagerService}.
- *
- * Build/Install/Run:
- * atest FrameworksMockingServicesTests:CommunalManagerServiceTest
- */
-@RunWith(MockitoJUnitRunner.class)
-@SmallTest
-@Presubmit
-public class CommunalManagerServiceTest {
- private MockitoSession mMockingSession;
- private CommunalManagerService mService;
-
- private ICommunalManager mBinder;
- private ContextWrapper mContextSpy;
-
- @Before
- public final void setUp() {
- mMockingSession = mockitoSession()
- .initMocks(this)
- .strictness(Strictness.WARN)
- .startMocking();
-
- mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
-
- doNothing().when(mContextSpy).enforceCallingPermission(
- eq(Manifest.permission.WRITE_COMMUNAL_STATE), anyString());
- doNothing().when(mContextSpy).enforceCallingPermission(
- eq(Manifest.permission.READ_COMMUNAL_STATE), anyString());
-
- mService = new CommunalManagerService(mContextSpy);
- mBinder = mService.getBinderServiceInstance();
- }
-
- @After
- public void tearDown() {
- if (mMockingSession != null) {
- mMockingSession.finishMocking();
- }
- }
-
- @Test
- public void testIsCommunalMode_isTrue() throws RemoteException {
- mBinder.setCommunalViewShowing(true);
- assertThat(mBinder.isCommunalMode()).isTrue();
- }
-
- @Test
- public void testIsCommunalMode_isFalse() throws RemoteException {
- mBinder.setCommunalViewShowing(false);
- assertThat(mBinder.isCommunalMode()).isFalse();
- }
-}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index 0c3e472b46a8..bdeb2b4fd839 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -122,15 +122,14 @@ public class JobSchedulerServiceTest {
.when(() -> LocalServices.getService(ActivityManagerInternal.class));
doReturn(mock(AppStandbyInternal.class))
.when(() -> LocalServices.getService(AppStandbyInternal.class));
+ doReturn(mock(BatteryManagerInternal.class))
+ .when(() -> LocalServices.getService(BatteryManagerInternal.class));
doReturn(mock(UsageStatsManagerInternal.class))
.when(() -> LocalServices.getService(UsageStatsManagerInternal.class));
when(mContext.getString(anyInt())).thenReturn("some_test_string");
// Called in BackgroundJobsController constructor.
doReturn(mock(AppStateTrackerImpl.class))
.when(() -> LocalServices.getService(AppStateTracker.class));
- // Called in BatteryController constructor.
- doReturn(mock(BatteryManagerInternal.class))
- .when(() -> LocalServices.getService(BatteryManagerInternal.class));
// Called in ConnectivityController constructor.
when(mContext.getSystemService(ConnectivityManager.class))
.thenReturn(mock(ConnectivityManager.class));
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index a9853bf94eeb..f61d6ca750cd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -48,18 +48,14 @@ import static org.mockito.Mockito.verify;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.job.JobInfo;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManagerInternal;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkPolicyManager;
-import android.os.BatteryManager;
-import android.os.BatteryManagerInternal;
import android.os.Build;
import android.os.Looper;
import android.os.SystemClock;
@@ -74,7 +70,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.ArgumentMatchers;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@@ -88,8 +83,6 @@ public class ConnectivityControllerTest {
@Mock
private Context mContext;
@Mock
- private BatteryManagerInternal mBatteryManagerInternal;
- @Mock
private ConnectivityManager mConnManager;
@Mock
private NetworkPolicyManager mNetPolicyManager;
@@ -115,9 +108,6 @@ public class ConnectivityControllerTest {
LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
LocalServices.addService(NetworkPolicyManagerInternal.class, mNetPolicyManagerInternal);
- LocalServices.removeServiceForTest(BatteryManagerInternal.class);
- LocalServices.addService(BatteryManagerInternal.class, mBatteryManagerInternal);
-
when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
// Freeze the clocks at this moment in time
@@ -158,18 +148,10 @@ public class ConnectivityControllerTest {
.setMinimumNetworkChunkBytes(DataUnit.KIBIBYTES.toBytes(100))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
- final ArgumentCaptor<BroadcastReceiver> chargingCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- when(mBatteryManagerInternal.isPowered(eq(BatteryManager.BATTERY_PLUGGED_ANY)))
- .thenReturn(false);
+ when(mService.isBatteryCharging()).thenReturn(false);
final ConnectivityController controller = new ConnectivityController(mService);
- verify(mContext).registerReceiver(chargingCaptor.capture(),
- ArgumentMatchers.argThat(filter ->
- filter.hasAction(BatteryManager.ACTION_CHARGING)
- && filter.hasAction(BatteryManager.ACTION_DISCHARGING)));
when(mService.getMaxJobExecutionTimeMs(any())).thenReturn(10 * 60_000L);
- final BroadcastReceiver chargingReceiver = chargingCaptor.getValue();
- chargingReceiver.onReceive(mContext, new Intent(BatteryManager.ACTION_DISCHARGING));
+ controller.onBatteryStateChangedLocked();
// Slow network is too slow
assertFalse(controller.isSatisfied(createJobStatus(job), net,
@@ -225,17 +207,15 @@ public class ConnectivityControllerTest {
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(130)
.setLinkDownstreamBandwidthKbps(130).build(), mConstants));
// Slow network is too slow, but device is charging and network is unmetered.
- when(mBatteryManagerInternal.isPowered(eq(BatteryManager.BATTERY_PLUGGED_ANY)))
- .thenReturn(true);
- chargingReceiver.onReceive(mContext, new Intent(BatteryManager.ACTION_CHARGING));
+ when(mService.isBatteryCharging()).thenReturn(true);
+ controller.onBatteryStateChangedLocked();
assertTrue(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().addCapability(NET_CAPABILITY_NOT_METERED)
.setLinkUpstreamBandwidthKbps(1).setLinkDownstreamBandwidthKbps(1).build(),
mConstants));
- when(mBatteryManagerInternal.isPowered(eq(BatteryManager.BATTERY_PLUGGED_ANY)))
- .thenReturn(false);
- chargingReceiver.onReceive(mContext, new Intent(BatteryManager.ACTION_DISCHARGING));
+ when(mService.isBatteryCharging()).thenReturn(false);
+ controller.onBatteryStateChangedLocked();
when(mService.getMaxJobExecutionTimeMs(any())).thenReturn(60_000L);
// Slow network is too slow
@@ -259,9 +239,8 @@ public class ConnectivityControllerTest {
createCapabilitiesBuilder().setLinkUpstreamBandwidthKbps(130)
.setLinkDownstreamBandwidthKbps(130).build(), mConstants));
// Slow network is too slow, but device is charging and network is unmetered.
- when(mBatteryManagerInternal.isPowered(eq(BatteryManager.BATTERY_PLUGGED_ANY)))
- .thenReturn(true);
- chargingReceiver.onReceive(mContext, new Intent(BatteryManager.ACTION_CHARGING));
+ when(mService.isBatteryCharging()).thenReturn(true);
+ controller.onBatteryStateChangedLocked();
assertTrue(controller.isSatisfied(createJobStatus(job), net,
createCapabilitiesBuilder().addCapability(NET_CAPABILITY_NOT_METERED)
.setLinkUpstreamBandwidthKbps(1).setLinkDownstreamBandwidthKbps(1).build(),
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 300f93feed28..cfae9a3d586a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -63,16 +63,13 @@ import android.app.job.JobInfo;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ServiceInfo;
-import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.Handler;
import android.os.Looper;
@@ -126,7 +123,6 @@ public class QuotaControllerTest {
private static final String SOURCE_PACKAGE = "com.android.frameworks.mockingservicestests";
private static final int SOURCE_USER_ID = 0;
- private BroadcastReceiver mChargingReceiver;
private QuotaController mQuotaController;
private QuotaController.QcConstants mQcConstants;
private JobSchedulerService.Constants mConstants = new JobSchedulerService.Constants();
@@ -225,8 +221,6 @@ public class QuotaControllerTest {
// Initialize real objects.
// Capture the listeners.
- ArgumentCaptor<BroadcastReceiver> receiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
ArgumentCaptor<IUidObserver> uidObserverCaptor =
ArgumentCaptor.forClass(IUidObserver.class);
ArgumentCaptor<PowerAllowlistInternal.TempAllowlistChangeListener> taChangeCaptor =
@@ -236,11 +230,6 @@ public class QuotaControllerTest {
mQuotaController = new QuotaController(mJobSchedulerService,
mock(BackgroundJobsController.class), mock(ConnectivityController.class));
- verify(mContext).registerReceiver(receiverCaptor.capture(),
- ArgumentMatchers.argThat(filter ->
- filter.hasAction(BatteryManager.ACTION_CHARGING)
- && filter.hasAction(BatteryManager.ACTION_DISCHARGING)));
- mChargingReceiver = receiverCaptor.getValue();
verify(mPowerAllowlistInternal)
.registerTempAllowlistChangeListener(taChangeCaptor.capture());
mTempAllowlistListener = taChangeCaptor.getValue();
@@ -280,13 +269,17 @@ public class QuotaControllerTest {
}
private void setCharging() {
- Intent intent = new Intent(BatteryManager.ACTION_CHARGING);
- mChargingReceiver.onReceive(mContext, intent);
+ doReturn(true).when(mJobSchedulerService).isBatteryCharging();
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.onBatteryStateChangedLocked();
+ }
}
private void setDischarging() {
- Intent intent = new Intent(BatteryManager.ACTION_DISCHARGING);
- mChargingReceiver.onReceive(mContext, intent);
+ doReturn(false).when(mJobSchedulerService).isBatteryCharging();
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.onBatteryStateChangedLocked();
+ }
}
private void setProcessState(int procState) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
index f2415b4665d5..bdfdf7723c02 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -158,10 +158,10 @@ public class StagingManagerTest {
mStagingManager.restoreSessions(Arrays.asList(session1, session2), true);
- assertThat(session1.getErrorCode()).isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ assertThat(session1.getErrorCode()).isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(session1.getErrorMessage()).isEqualTo("Build fingerprint has changed");
- assertThat(session2.getErrorCode()).isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ assertThat(session2.getErrorCode()).isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(session2.getErrorMessage()).isEqualTo("Build fingerprint has changed");
}
@@ -247,12 +247,12 @@ public class StagingManagerTest {
verify(mStorageManager, never()).abortChanges(eq("abort-staged-install"), eq(false));
assertThat(apexSession.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apexSession.getErrorMessage()).isEqualTo("apexd did not know anything about a "
+ "staged session supposed to be activated");
assertThat(apkSession.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apkSession.getErrorMessage()).isEqualTo("Another apex session failed");
}
@@ -303,22 +303,22 @@ public class StagingManagerTest {
verify(mStorageManager, never()).abortChanges(eq("abort-staged-install"), eq(false));
assertThat(apexSession1.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apexSession1.getErrorMessage()).isEqualTo("APEX activation failed. "
+ "Error: Failed for test");
assertThat(apexSession2.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apexSession2.getErrorMessage()).isEqualTo("Staged session 101 at boot didn't "
+ "activate nor fail. Marking it as failed anyway.");
assertThat(apexSession3.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apexSession3.getErrorMessage()).isEqualTo("apexd did not know anything about a "
+ "staged session supposed to be activated");
assertThat(apkSession.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apkSession.getErrorMessage()).isEqualTo("Another apex session failed");
}
@@ -351,12 +351,12 @@ public class StagingManagerTest {
verify(mStorageManager, never()).abortChanges(eq("abort-staged-install"), eq(false));
assertThat(apexSession.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apexSession.getErrorMessage()).isEqualTo("Staged session 1543 at boot didn't "
+ "activate nor fail. Marking it as failed anyway.");
assertThat(apkSession.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apkSession.getErrorMessage()).isEqualTo("Another apex session failed");
}
@@ -445,11 +445,11 @@ public class StagingManagerTest {
verify(mStorageManager, never()).abortChanges(eq("abort-staged-install"), eq(false));
assertThat(apexSession.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apexSession.getErrorMessage()).isEqualTo("Impossible state");
assertThat(apkSession.getErrorCode())
- .isEqualTo(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED);
+ .isEqualTo(SessionInfo.SESSION_ACTIVATION_FAILED);
assertThat(apkSession.getErrorMessage()).isEqualTo("Another apex session failed");
}
@@ -754,7 +754,7 @@ public class StagingManagerTest {
/* isReady */ false,
/* isFailed */ false,
/* isApplied */false,
- /* stagedSessionErrorCode */ PackageInstaller.SessionInfo.STAGED_SESSION_NO_ERROR,
+ /* stagedSessionErrorCode */ PackageInstaller.SessionInfo.SESSION_NO_ERROR,
/* stagedSessionErrorMessage */ "no error");
StagingManager.StagedSession stagedSession = spy(session.mStagedSession);
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java b/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java
new file mode 100644
index 000000000000..b65c3e939954
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManagerInternal;
+import android.attention.AttentionManagerInternal;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.res.Resources;
+import android.hardware.SensorManager;
+import android.hardware.devicestate.DeviceStateManager;
+import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback;
+import android.hardware.display.AmbientDisplayConfiguration;
+import android.hardware.display.DisplayManagerInternal;
+import android.os.BatteryManagerInternal;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.PowerSaveState;
+import android.os.test.TestLooper;
+import android.provider.Settings;
+import android.service.dreams.DreamManagerInternal;
+import android.test.mock.MockContentResolver;
+import android.view.Display;
+import android.view.DisplayInfo;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.lights.LightsManager;
+import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.power.PowerManagerService.BatteryReceiver;
+import com.android.server.power.PowerManagerService.Injector;
+import com.android.server.power.PowerManagerService.NativeWrapper;
+import com.android.server.power.PowerManagerService.UserSwitchedReceiver;
+import com.android.server.power.batterysaver.BatterySaverController;
+import com.android.server.power.batterysaver.BatterySaverPolicy;
+import com.android.server.power.batterysaver.BatterySaverStateMachine;
+import com.android.server.power.batterysaver.BatterySavingStats;
+import com.android.server.testutils.OffsettableClock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link com.android.server.power.PowerManagerService}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksServicesTests:PowerManagerServiceMockingTest
+ */
+public class PowerManagerServiceMockingTest {
+ private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
+ private static final String SYSTEM_PROPERTY_REBOOT_REASON = "sys.boot.reason";
+
+ private static final float BRIGHTNESS_FACTOR = 0.7f;
+ private static final boolean BATTERY_SAVER_ENABLED = true;
+
+ @Mock private BatterySaverController mBatterySaverControllerMock;
+ @Mock private BatterySaverPolicy mBatterySaverPolicyMock;
+ @Mock private BatterySaverStateMachine mBatterySaverStateMachineMock;
+ @Mock private LightsManager mLightsManagerMock;
+ @Mock private DisplayManagerInternal mDisplayManagerInternalMock;
+ @Mock private BatteryManagerInternal mBatteryManagerInternalMock;
+ @Mock private ActivityManagerInternal mActivityManagerInternalMock;
+ @Mock private AttentionManagerInternal mAttentionManagerInternalMock;
+ @Mock private DreamManagerInternal mDreamManagerInternalMock;
+ @Mock private PowerManagerService.NativeWrapper mNativeWrapperMock;
+ @Mock private Notifier mNotifierMock;
+ @Mock private WirelessChargerDetector mWirelessChargerDetectorMock;
+ @Mock private AmbientDisplayConfiguration mAmbientDisplayConfigurationMock;
+ @Mock private SystemPropertiesWrapper mSystemPropertiesMock;
+ @Mock private DeviceStateManager mDeviceStateManagerMock;
+
+ @Mock
+ private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
+
+ private PowerManagerService mService;
+ private PowerSaveState mPowerSaveState;
+ private ContextWrapper mContextSpy;
+ private BatteryReceiver mBatteryReceiver;
+ private UserSwitchedReceiver mUserSwitchedReceiver;
+ private Resources mResourcesSpy;
+ private OffsettableClock mClock;
+ private TestLooper mTestLooper;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ FakeSettingsProvider.clearSettingsProvider();
+
+ mPowerSaveState = new PowerSaveState.Builder()
+ .setBatterySaverEnabled(BATTERY_SAVER_ENABLED)
+ .setBrightnessFactor(BRIGHTNESS_FACTOR)
+ .build();
+ when(mBatterySaverPolicyMock.getBatterySaverPolicy(
+ eq(PowerManager.ServiceType.SCREEN_BRIGHTNESS)))
+ .thenReturn(mPowerSaveState);
+ when(mBatteryManagerInternalMock.isPowered(anyInt())).thenReturn(false);
+ when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(false);
+ when(mDisplayManagerInternalMock.requestPowerState(anyInt(), any(), anyBoolean()))
+ .thenReturn(true);
+ when(mSystemPropertiesMock.get(eq(SYSTEM_PROPERTY_QUIESCENT), anyString())).thenReturn("");
+ when(mAmbientDisplayConfigurationMock.ambientDisplayAvailable()).thenReturn(true);
+
+ addLocalServiceMock(LightsManager.class, mLightsManagerMock);
+ addLocalServiceMock(DisplayManagerInternal.class, mDisplayManagerInternalMock);
+ addLocalServiceMock(BatteryManagerInternal.class, mBatteryManagerInternalMock);
+ addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
+ addLocalServiceMock(AttentionManagerInternal.class, mAttentionManagerInternalMock);
+ addLocalServiceMock(DreamManagerInternal.class, mDreamManagerInternalMock);
+
+ mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
+ mResourcesSpy = spy(mContextSpy.getResources());
+ when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
+
+ MockContentResolver cr = new MockContentResolver(mContextSpy);
+ cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ when(mContextSpy.getContentResolver()).thenReturn(cr);
+
+ when(mContextSpy.getSystemService(DeviceStateManager.class))
+ .thenReturn(mDeviceStateManagerMock);
+
+ Settings.Global.putInt(mContextSpy.getContentResolver(),
+ Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
+
+ mClock = new OffsettableClock.Stopped();
+ mTestLooper = new TestLooper(mClock::now);
+ }
+
+ private PowerManagerService createService() {
+ mService = new PowerManagerService(mContextSpy, new Injector() {
+ @Override
+ Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
+ SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
+ return mNotifierMock;
+ }
+
+ @Override
+ SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
+ return super.createSuspendBlocker(service, name);
+ }
+
+ @Override
+ BatterySaverPolicy createBatterySaverPolicy(
+ Object lock, Context context, BatterySavingStats batterySavingStats) {
+ return mBatterySaverPolicyMock;
+ }
+
+ @Override
+ BatterySaverController createBatterySaverController(
+ Object lock, Context context, BatterySaverPolicy batterySaverPolicy,
+ BatterySavingStats batterySavingStats) {
+ return mBatterySaverControllerMock;
+ }
+
+ @Override
+ BatterySaverStateMachine createBatterySaverStateMachine(Object lock, Context context,
+ BatterySaverController batterySaverController) {
+ return mBatterySaverStateMachineMock;
+ }
+
+ @Override
+ NativeWrapper createNativeWrapper() {
+ return mNativeWrapperMock;
+ }
+
+ @Override
+ WirelessChargerDetector createWirelessChargerDetector(
+ SensorManager sensorManager, SuspendBlocker suspendBlocker, Handler handler) {
+ return mWirelessChargerDetectorMock;
+ }
+
+ @Override
+ AmbientDisplayConfiguration createAmbientDisplayConfiguration(Context context) {
+ return mAmbientDisplayConfigurationMock;
+ }
+
+ @Override
+ InattentiveSleepWarningController createInattentiveSleepWarningController() {
+ return mInattentiveSleepWarningControllerMock;
+ }
+
+ @Override
+ public SystemPropertiesWrapper createSystemPropertiesWrapper() {
+ return mSystemPropertiesMock;
+ }
+
+ @Override
+ PowerManagerService.Clock createClock() {
+ return () -> mClock.now();
+ }
+
+ @Override
+ Handler createHandler(Looper looper, Handler.Callback callback) {
+ return new Handler(mTestLooper.getLooper(), callback);
+ }
+
+ @Override
+ void invalidateIsInteractiveCaches() {
+ // Avoids an SELinux failure.
+ }
+ });
+ return mService;
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ LocalServices.removeServiceForTest(LightsManager.class);
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ LocalServices.removeServiceForTest(BatteryManagerInternal.class);
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.removeServiceForTest(AttentionManagerInternal.class);
+ LocalServices.removeServiceForTest(DreamManagerInternal.class);
+ FakeSettingsProvider.clearSettingsProvider();
+ }
+
+ /**
+ * Creates a mock and registers it to {@link LocalServices}.
+ */
+ private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
+ LocalServices.removeServiceForTest(clazz);
+ LocalServices.addService(clazz, mock);
+ }
+
+ private void advanceTime(long timeMs) {
+ mClock.fastForward(timeMs);
+ mTestLooper.dispatchAll();
+ }
+
+ @Test
+ public void testUserActivityOnDeviceStateChange() {
+ createService();
+ mService.systemReady(null);
+ mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+
+ final DisplayInfo info = new DisplayInfo();
+ info.displayGroupId = Display.DEFAULT_DISPLAY_GROUP;
+ when(mDisplayManagerInternalMock.getDisplayInfo(Display.DEFAULT_DISPLAY)).thenReturn(info);
+
+ final ArgumentCaptor<DeviceStateCallback> deviceStateCallbackCaptor =
+ ArgumentCaptor.forClass(DeviceStateCallback.class);
+ verify(mDeviceStateManagerMock).registerCallback(any(),
+ deviceStateCallbackCaptor.capture());
+
+ // Advance the time 10001 and verify that the device thinks it has been idle
+ // for just less than that.
+ mService.onUserActivity();
+ advanceTime(10001);
+ assertThat(mService.wasDeviceIdleForInternal(10000)).isTrue();
+
+ // Send a display state change event and advance the clock 10.
+ final DeviceStateCallback deviceStateCallback = deviceStateCallbackCaptor.getValue();
+ deviceStateCallback.onStateChanged(1);
+ final long timeToAdvance = 10;
+ advanceTime(timeToAdvance);
+
+ // Ensure that the device has been idle for only 10 (doesn't include the idle time
+ // before the display state event).
+ assertThat(mService.wasDeviceIdleForInternal(timeToAdvance - 1)).isTrue();
+ assertThat(mService.wasDeviceIdleForInternal(timeToAdvance)).isFalse();
+
+ // Send the same state and ensure that does not trigger an update.
+ deviceStateCallback.onStateChanged(1);
+ advanceTime(timeToAdvance);
+ final long newTime = timeToAdvance * 2;
+
+ assertThat(mService.wasDeviceIdleForInternal(newTime - 1)).isTrue();
+ assertThat(mService.wasDeviceIdleForInternal(newTime)).isFalse();
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
index 6a3548178cba..234d70b98580 100644
--- a/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/power/ScreenUndimDetectorTest.java
@@ -22,6 +22,7 @@ import static android.hardware.display.DisplayManagerInternal.DisplayPowerReques
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_OFF;
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_VR;
import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
+import static android.view.Display.DEFAULT_DISPLAY_GROUP;
import static com.android.server.power.ScreenUndimDetector.DEFAULT_MAX_DURATION_BETWEEN_UNDIMS_MILLIS;
import static com.android.server.power.ScreenUndimDetector.KEY_KEEP_SCREEN_ON_ENABLED;
@@ -60,6 +61,7 @@ public class ScreenUndimDetectorTest {
POLICY_DIM,
POLICY_BRIGHT,
POLICY_VR);
+ private static final int OTHER_DISPLAY_GROUP = DEFAULT_DISPLAY_GROUP + 1;
@ClassRule
public static final TestableContext sContext = new TestableContext(
@@ -106,8 +108,8 @@ public class ScreenUndimDetectorTest {
KEY_KEEP_SCREEN_ON_ENABLED, Boolean.FALSE.toString(), false /*makeDefault*/);
setup();
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
}
@@ -116,8 +118,8 @@ public class ScreenUndimDetectorTest {
public void recordScreenPolicy_samePolicy_noop() {
for (int policy : ALL_POLICIES) {
setup();
- mScreenUndimDetector.recordScreenPolicy(policy);
- mScreenUndimDetector.recordScreenPolicy(policy);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, policy);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, policy);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
}
@@ -125,13 +127,24 @@ public class ScreenUndimDetectorTest {
@Test
public void recordScreenPolicy_dimToBright_extends() {
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isTrue();
}
@Test
+ public void recordScreenPolicy_dimToBright_ignoresOtherDisplayGroup() {
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+
+ mScreenUndimDetector.recordScreenPolicy(OTHER_DISPLAY_GROUP, POLICY_BRIGHT);
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isTrue();
+ }
+
+ @Test
public void recordScreenPolicy_otherTransitions_doesNotExtend() {
for (int from : ALL_POLICIES) {
for (int to : ALL_POLICIES) {
@@ -139,8 +152,8 @@ public class ScreenUndimDetectorTest {
continue;
}
setup();
- mScreenUndimDetector.recordScreenPolicy(from);
- mScreenUndimDetector.recordScreenPolicy(to);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, from);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, to);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
@@ -155,14 +168,35 @@ public class ScreenUndimDetectorTest {
Integer.toString(2), false /*makeDefault*/);
mScreenUndimDetector.readValuesFromDeviceConfig();
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isTrue();
+ }
+
+ @Test
+ public void recordScreenPolicy_dimToBright_twoUndimsNeeded_otherDisplayDoesNotExtend() {
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ Integer.toString(2), false /*makeDefault*/);
+ mScreenUndimDetector.readValuesFromDeviceConfig();
+
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(OTHER_DISPLAY_GROUP, POLICY_BRIGHT);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isTrue();
}
@@ -173,10 +207,10 @@ public class ScreenUndimDetectorTest {
Integer.toString(2), false /*makeDefault*/);
mScreenUndimDetector.readValuesFromDeviceConfig();
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_OFF);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_OFF);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
@@ -189,10 +223,27 @@ public class ScreenUndimDetectorTest {
Integer.toString(2), false /*makeDefault*/);
mScreenUndimDetector.readValuesFromDeviceConfig();
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
- mScreenUndimDetector.recordScreenPolicy(POLICY_OFF);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_OFF);
+
+ assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
+ assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
+ }
+
+ @Test
+ public void recordScreenPolicy_undimToOff_otherDisplayDoesNotResetCounter() {
+ DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_UNDIMS_REQUIRED,
+ Integer.toString(2), false /*makeDefault*/);
+ mScreenUndimDetector.readValuesFromDeviceConfig();
+
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_OFF);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
@@ -206,15 +257,15 @@ public class ScreenUndimDetectorTest {
mScreenUndimDetector.readValuesFromDeviceConfig();
// undim
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
// off
- mScreenUndimDetector.recordScreenPolicy(POLICY_OFF);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_OFF);
// second undim
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(1);
@@ -227,12 +278,12 @@ public class ScreenUndimDetectorTest {
Integer.toString(2), false /*makeDefault*/);
mScreenUndimDetector.readValuesFromDeviceConfig();
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
mClock.advanceTime(DEFAULT_MAX_DURATION_BETWEEN_UNDIMS_MILLIS + 5);
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
assertThat(mScreenUndimDetector.mWakeLock.isHeld()).isFalse();
assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(1);
@@ -246,8 +297,8 @@ public class ScreenUndimDetectorTest {
mScreenUndimDetector.mUndimCounterStartedMillis = 123;
mScreenUndimDetector.mWakeLock.acquire();
- mScreenUndimDetector.recordScreenPolicy(POLICY_DIM);
- mScreenUndimDetector.recordScreenPolicy(to);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_DIM);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, to);
assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
assertThat(mScreenUndimDetector.mUndimCounterStartedMillis).isEqualTo(0);
@@ -264,8 +315,8 @@ public class ScreenUndimDetectorTest {
mScreenUndimDetector.mUndimCounterStartedMillis = 123;
mScreenUndimDetector.mWakeLock.acquire();
- mScreenUndimDetector.recordScreenPolicy(POLICY_BRIGHT);
- mScreenUndimDetector.recordScreenPolicy(to);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, POLICY_BRIGHT);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, to);
assertThat(mScreenUndimDetector.mUndimCounter).isEqualTo(0);
assertThat(mScreenUndimDetector.mUndimCounterStartedMillis).isEqualTo(0);
@@ -294,8 +345,8 @@ public class ScreenUndimDetectorTest {
mScreenUndimDetector.mUndimCounterStartedMillis =
SystemClock.currentThreadTimeMillis();
- mScreenUndimDetector.recordScreenPolicy(from);
- mScreenUndimDetector.recordScreenPolicy(to);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, from);
+ mScreenUndimDetector.recordScreenPolicy(DEFAULT_DISPLAY_GROUP, to);
assertThat(mScreenUndimDetector.mUndimCounter).isNotEqualTo(0);
assertThat(mScreenUndimDetector.mUndimCounterStartedMillis).isNotEqualTo(0);
diff --git a/services/tests/servicestests/src/com/android/server/SystemServiceManagerTest.java b/services/tests/servicestests/src/com/android/server/SystemServiceManagerTest.java
new file mode 100644
index 000000000000..f92f5ead2c3b
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/SystemServiceManagerTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static org.junit.Assert.assertThrows;
+
+import android.test.AndroidTestCase;
+
+import org.junit.Test;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+/**
+ * Tests for {@link SystemServiceManager}.
+ */
+public class SystemServiceManagerTest extends AndroidTestCase {
+
+ private static final String TAG = "SystemServiceManagerTest";
+
+ private final SystemServiceManager mSystemServiceManager =
+ new SystemServiceManager(getContext());
+
+ @Test
+ public void testSealStartedServices() throws Exception {
+ // must be effectively final, since it's changed from inner class below
+ AtomicBoolean serviceStarted = new AtomicBoolean(false);
+ SystemService service1 = new SystemService(getContext()) {
+ @Override
+ public void onStart() {
+ serviceStarted.set(true);
+ }
+ };
+ SystemService service2 = new SystemService(getContext()) {
+ @Override
+ public void onStart() {
+ throw new IllegalStateException("Second service must not be called");
+ }
+ };
+
+ // started services have their #onStart methods called
+ mSystemServiceManager.startService(service1);
+ assertTrue(serviceStarted.get());
+
+ // however, after locking started services, it is not possible to start a new service
+ mSystemServiceManager.sealStartedServices();
+ assertThrows(UnsupportedOperationException.class,
+ () -> mSystemServiceManager.startService(service2));
+ }
+
+ @Test
+ public void testDuplicateServices() throws Exception {
+ AtomicInteger counter = new AtomicInteger(0);
+ SystemService service = new SystemService(getContext()) {
+ @Override
+ public void onStart() {
+ counter.incrementAndGet();
+ }
+ };
+
+ mSystemServiceManager.startService(service);
+ assertEquals(1, counter.get());
+
+ // manager does not start the same service twice
+ mSystemServiceManager.startService(service);
+ assertEquals(1, counter.get());
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
index cffff66b64f1..02cf971a8076 100644
--- a/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/adb/AdbDebuggingManagerTest.java
@@ -23,7 +23,14 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.debug.AdbManager;
+import android.debug.IAdbManager;
+import android.os.ServiceManager;
import android.provider.Settings;
import android.util.Log;
@@ -105,6 +112,7 @@ public final class AdbDebuggingManagerTest {
public void tearDown() throws Exception {
mKeyStore.deleteKeyStore();
setAllowedConnectionTime(mOriginalAllowedConnectionTime);
+ dropShellPermissionIdentity();
}
/**
@@ -813,6 +821,108 @@ public final class AdbDebuggingManagerTest {
return hasAtLeastOneLetter;
}
+ CountDownLatch mAdbActionLatch = new CountDownLatch(1);
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ Log.i(TAG, "Received intent action=" + action);
+ if (AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION.equals(action)) {
+ assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+ context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ Log.i(TAG, "action=" + action + " paired_device=" + intent.getSerializableExtra(
+ AdbManager.WIRELESS_DEVICES_EXTRA).toString());
+ mAdbActionLatch.countDown();
+ } else if (AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION.equals(action)) {
+ assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+ context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ int status = intent.getIntExtra(AdbManager.WIRELESS_STATUS_EXTRA,
+ AdbManager.WIRELESS_STATUS_DISCONNECTED);
+ Log.i(TAG, "action=" + action + " status=" + status);
+ mAdbActionLatch.countDown();
+ } else if (AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION.equals(action)) {
+ assertEquals("Received broadcast without MANAGE_DEBUGGING permission.",
+ context.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ Integer res = intent.getIntExtra(
+ AdbManager.WIRELESS_STATUS_EXTRA,
+ AdbManager.WIRELESS_STATUS_FAIL);
+ Log.i(TAG, "action=" + action + " result=" + res);
+
+ if (res.equals(AdbManager.WIRELESS_STATUS_PAIRING_CODE)) {
+ String pairingCode = intent.getStringExtra(
+ AdbManager.WIRELESS_PAIRING_CODE_EXTRA);
+ Log.i(TAG, "pairingCode=" + pairingCode);
+ } else if (res.equals(AdbManager.WIRELESS_STATUS_CONNECTED)) {
+ int port = intent.getIntExtra(AdbManager.WIRELESS_DEBUG_PORT_EXTRA, 0);
+ Log.i(TAG, "port=" + port);
+ }
+ mAdbActionLatch.countDown();
+ }
+ }
+ };
+
+ private void adoptShellPermissionIdentity() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.MANAGE_DEBUGGING);
+ }
+
+ private void dropShellPermissionIdentity() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ @Test
+ public void testBroadcastReceiverWithPermissions() throws Exception {
+ adoptShellPermissionIdentity();
+ final IAdbManager mAdbManager = IAdbManager.Stub.asInterface(
+ ServiceManager.getService(Context.ADB_SERVICE));
+ IntentFilter intentFilter =
+ new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ assertEquals("Context does not have MANAGE_DEBUGGING permission.",
+ mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_GRANTED);
+ try {
+ mContext.registerReceiver(mReceiver, intentFilter);
+ mAdbManager.enablePairingByPairingCode();
+ if (!mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
+ fail("Receiver did not receive adb intent action within the timeout duration");
+ }
+ } finally {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
+ @Test
+ public void testBroadcastReceiverWithoutPermissions() throws Exception {
+ adoptShellPermissionIdentity();
+ final IAdbManager mAdbManager = IAdbManager.Stub.asInterface(
+ ServiceManager.getService(Context.ADB_SERVICE));
+ IntentFilter intentFilter =
+ new IntentFilter(AdbManager.WIRELESS_DEBUG_PAIRED_DEVICES_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_STATE_CHANGED_ACTION);
+ intentFilter.addAction(AdbManager.WIRELESS_DEBUG_PAIRING_RESULT_ACTION);
+ mAdbManager.enablePairingByPairingCode();
+
+ dropShellPermissionIdentity();
+ assertEquals("Context has MANAGE_DEBUGGING permission.",
+ mContext.checkSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING),
+ PackageManager.PERMISSION_DENIED);
+ try {
+ mContext.registerReceiver(mReceiver, intentFilter);
+
+ if (mAdbActionLatch.await(TIMEOUT, TIMEOUT_TIME_UNIT)) {
+ fail("Broadcast receiver received adb action intent without debug permissions");
+ }
+ } finally {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ }
+
/**
* Runs an adb test with the provided configuration.
*
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java
deleted file mode 100644
index d4bac2c0402d..000000000000
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors;
-
-import static android.testing.TestableLooper.RunWithLooper;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.testng.Assert.assertThrows;
-
-import android.os.Handler;
-import android.platform.test.annotations.Presubmit;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@Presubmit
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-@SmallTest
-public class BiometricSchedulerOperationTest {
-
- public interface FakeHal {}
- public abstract static class InterruptableMonitor<T>
- extends HalClientMonitor<T> implements Interruptable {
- public InterruptableMonitor() {
- super(null, null, null, null, 0, null, 0, 0, 0, 0, 0);
- }
- }
-
- @Mock
- private InterruptableMonitor<FakeHal> mClientMonitor;
- @Mock
- private BaseClientMonitor.Callback mClientCallback;
- @Mock
- private FakeHal mHal;
- @Captor
- ArgumentCaptor<BaseClientMonitor.Callback> mStartCallback;
-
- private Handler mHandler;
- private BiometricSchedulerOperation mOperation;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mHandler = new Handler(TestableLooper.get(this).getLooper());
- mOperation = new BiometricSchedulerOperation(mClientMonitor, mClientCallback);
- }
-
- @Test
- public void testStartWithCookie() {
- final int cookie = 200;
- when(mClientMonitor.getCookie()).thenReturn(cookie);
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- assertThat(mOperation.isReadyToStart()).isEqualTo(cookie);
- assertThat(mOperation.isStarted()).isFalse();
- assertThat(mOperation.isCanceling()).isFalse();
- assertThat(mOperation.isFinished()).isFalse();
-
- final boolean started = mOperation.startWithCookie(
- mock(BaseClientMonitor.Callback.class), cookie);
-
- assertThat(started).isTrue();
- verify(mClientMonitor).start(mStartCallback.capture());
- mStartCallback.getValue().onClientStarted(mClientMonitor);
- assertThat(mOperation.isStarted()).isTrue();
- }
-
- @Test
- public void testNoStartWithoutCookie() {
- final int goodCookie = 20;
- final int badCookie = 22;
- when(mClientMonitor.getCookie()).thenReturn(goodCookie);
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- assertThat(mOperation.isReadyToStart()).isEqualTo(goodCookie);
- final boolean started = mOperation.startWithCookie(
- mock(BaseClientMonitor.Callback.class), badCookie);
-
- assertThat(started).isFalse();
- assertThat(mOperation.isStarted()).isFalse();
- assertThat(mOperation.isCanceling()).isFalse();
- assertThat(mOperation.isFinished()).isFalse();
- }
-
- @Test
- public void startsWhenReadyAndHalAvailable() {
- when(mClientMonitor.getCookie()).thenReturn(0);
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- final BaseClientMonitor.Callback cb = mock(BaseClientMonitor.Callback.class);
- mOperation.start(cb);
- verify(mClientMonitor).start(mStartCallback.capture());
- mStartCallback.getValue().onClientStarted(mClientMonitor);
-
- assertThat(mOperation.isStarted()).isTrue();
- assertThat(mOperation.isCanceling()).isFalse();
- assertThat(mOperation.isFinished()).isFalse();
-
- verify(mClientCallback).onClientStarted(eq(mClientMonitor));
- verify(cb).onClientStarted(eq(mClientMonitor));
- verify(mClientCallback, never()).onClientFinished(any(), anyBoolean());
- verify(cb, never()).onClientFinished(any(), anyBoolean());
-
- mStartCallback.getValue().onClientFinished(mClientMonitor, true);
-
- assertThat(mOperation.isFinished()).isTrue();
- assertThat(mOperation.isCanceling()).isFalse();
- verify(mClientMonitor).destroy();
- verify(cb).onClientFinished(eq(mClientMonitor), eq(true));
- }
-
- @Test
- public void startFailsWhenReadyButHalNotAvailable() {
- when(mClientMonitor.getCookie()).thenReturn(0);
- when(mClientMonitor.getFreshDaemon()).thenReturn(null);
-
- final BaseClientMonitor.Callback cb = mock(BaseClientMonitor.Callback.class);
- mOperation.start(cb);
- verify(mClientMonitor, never()).start(any());
-
- assertThat(mOperation.isStarted()).isFalse();
- assertThat(mOperation.isCanceling()).isFalse();
- assertThat(mOperation.isFinished()).isTrue();
-
- verify(mClientCallback, never()).onClientStarted(eq(mClientMonitor));
- verify(cb, never()).onClientStarted(eq(mClientMonitor));
- verify(mClientCallback).onClientFinished(eq(mClientMonitor), eq(false));
- verify(cb).onClientFinished(eq(mClientMonitor), eq(false));
- }
-
- @Test
- public void doesNotStartWithCookie() {
- when(mClientMonitor.getCookie()).thenReturn(9);
- assertThrows(IllegalStateException.class,
- () -> mOperation.start(mock(BaseClientMonitor.Callback.class)));
- }
-
- @Test
- public void cannotRestart() {
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- mOperation.start(mock(BaseClientMonitor.Callback.class));
-
- assertThrows(IllegalStateException.class,
- () -> mOperation.start(mock(BaseClientMonitor.Callback.class)));
- }
-
- @Test
- public void abortsNotRunning() {
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- mOperation.abort();
-
- assertThat(mOperation.isFinished()).isTrue();
- verify(mClientMonitor).unableToStart();
- verify(mClientMonitor).destroy();
- assertThrows(IllegalStateException.class,
- () -> mOperation.start(mock(BaseClientMonitor.Callback.class)));
- }
-
- @Test
- public void cannotAbortRunning() {
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- mOperation.start(mock(BaseClientMonitor.Callback.class));
-
- assertThrows(IllegalStateException.class, () -> mOperation.abort());
- }
-
- @Test
- public void cancel() {
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- final BaseClientMonitor.Callback startCb = mock(BaseClientMonitor.Callback.class);
- final BaseClientMonitor.Callback cancelCb = mock(BaseClientMonitor.Callback.class);
- mOperation.start(startCb);
- verify(mClientMonitor).start(mStartCallback.capture());
- mStartCallback.getValue().onClientStarted(mClientMonitor);
- mOperation.cancel(mHandler, cancelCb);
-
- assertThat(mOperation.isCanceling()).isTrue();
- verify(mClientMonitor).cancel();
- verify(mClientMonitor, never()).cancelWithoutStarting(any());
- verify(mClientMonitor, never()).destroy();
-
- mStartCallback.getValue().onClientFinished(mClientMonitor, true);
-
- assertThat(mOperation.isFinished()).isTrue();
- assertThat(mOperation.isCanceling()).isFalse();
- verify(mClientMonitor).destroy();
-
- // should be unused since the operation was started
- verify(cancelCb, never()).onClientStarted(any());
- verify(cancelCb, never()).onClientFinished(any(), anyBoolean());
- }
-
- @Test
- public void cancelWithoutStarting() {
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- final BaseClientMonitor.Callback cancelCb = mock(BaseClientMonitor.Callback.class);
- mOperation.cancel(mHandler, cancelCb);
-
- assertThat(mOperation.isCanceling()).isTrue();
- ArgumentCaptor<BaseClientMonitor.Callback> cbCaptor =
- ArgumentCaptor.forClass(BaseClientMonitor.Callback.class);
- verify(mClientMonitor).cancelWithoutStarting(cbCaptor.capture());
-
- cbCaptor.getValue().onClientFinished(mClientMonitor, true);
- verify(cancelCb).onClientFinished(eq(mClientMonitor), eq(true));
- verify(mClientMonitor, never()).start(any());
- verify(mClientMonitor, never()).cancel();
- verify(mClientMonitor).destroy();
- }
-
- @Test
- public void markCanceling() {
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- mOperation.markCanceling();
-
- assertThat(mOperation.isMarkedCanceling()).isTrue();
- assertThat(mOperation.isCanceling()).isFalse();
- assertThat(mOperation.isFinished()).isFalse();
- verify(mClientMonitor, never()).start(any());
- verify(mClientMonitor, never()).cancel();
- verify(mClientMonitor, never()).cancelWithoutStarting(any());
- verify(mClientMonitor, never()).unableToStart();
- verify(mClientMonitor, never()).destroy();
- }
-
- @Test
- public void cancelPendingWithCookie() {
- markCancellingAndStart(2);
- }
-
- @Test
- public void cancelPendingWithoutCookie() {
- markCancellingAndStart(null);
- }
-
- private void markCancellingAndStart(Integer withCookie) {
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
- if (withCookie != null) {
- when(mClientMonitor.getCookie()).thenReturn(withCookie);
- }
-
- mOperation.markCanceling();
- final BaseClientMonitor.Callback cb = mock(BaseClientMonitor.Callback.class);
- if (withCookie != null) {
- mOperation.startWithCookie(cb, withCookie);
- } else {
- mOperation.start(cb);
- }
-
- assertThat(mOperation.isFinished()).isTrue();
- verify(cb).onClientFinished(eq(mClientMonitor), eq(true));
- verify(mClientMonitor, never()).start(any());
- verify(mClientMonitor, never()).cancel();
- verify(mClientMonitor, never()).cancelWithoutStarting(any());
- verify(mClientMonitor, never()).unableToStart();
- verify(mClientMonitor).destroy();
- }
-
- @Test
- public void cancelWatchdogWhenStarted() {
- cancelWatchdog(true);
- }
-
- @Test
- public void cancelWatchdogWithoutStarting() {
- cancelWatchdog(false);
- }
-
- private void cancelWatchdog(boolean start) {
- when(mClientMonitor.getFreshDaemon()).thenReturn(mHal);
-
- mOperation.start(mock(BaseClientMonitor.Callback.class));
- if (start) {
- verify(mClientMonitor).start(mStartCallback.capture());
- mStartCallback.getValue().onClientStarted(mClientMonitor);
- }
- mOperation.cancel(mHandler, mock(BaseClientMonitor.Callback.class));
-
- assertThat(mOperation.isCanceling()).isTrue();
-
- // omit call to onClientFinished and trigger watchdog
- mOperation.mCancelWatchdog.run();
-
- assertThat(mOperation.isFinished()).isTrue();
- assertThat(mOperation.isCanceling()).isFalse();
- verify(mClientMonitor).destroy();
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index ac0831983262..d192697827f6 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -16,14 +16,10 @@
package com.android.server.biometrics.sensors;
-import static android.testing.TestableLooper.RunWithLooper;
-
import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -38,13 +34,10 @@ import android.content.Context;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.IBiometricService;
import android.os.Binder;
-import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
-import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
-import android.testing.TestableLooper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -53,18 +46,16 @@ import androidx.test.filters.SmallTest;
import com.android.server.biometrics.nano.BiometricSchedulerProto;
import com.android.server.biometrics.nano.BiometricsProto;
+import com.android.server.biometrics.sensors.BiometricScheduler.Operation;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@Presubmit
@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
public class BiometricSchedulerTest {
private static final String TAG = "BiometricSchedulerTest";
@@ -85,9 +76,8 @@ public class BiometricSchedulerTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
mToken = new Binder();
- mScheduler = new BiometricScheduler(TAG, new Handler(TestableLooper.get(this).getLooper()),
- BiometricScheduler.SENSOR_TYPE_UNKNOWN, null /* gestureAvailabilityTracker */,
- mBiometricService, LOG_NUM_RECENT_OPERATIONS,
+ mScheduler = new BiometricScheduler(TAG, BiometricScheduler.SENSOR_TYPE_UNKNOWN,
+ null /* gestureAvailabilityTracker */, mBiometricService, LOG_NUM_RECENT_OPERATIONS,
CoexCoordinator.getInstance());
}
@@ -96,9 +86,9 @@ public class BiometricSchedulerTest {
final HalClientMonitor.LazyDaemon<Object> nonNullDaemon = () -> mock(Object.class);
final HalClientMonitor<Object> client1 =
- new TestHalClientMonitor(mContext, mToken, nonNullDaemon);
+ new TestClientMonitor(mContext, mToken, nonNullDaemon);
final HalClientMonitor<Object> client2 =
- new TestHalClientMonitor(mContext, mToken, nonNullDaemon);
+ new TestClientMonitor(mContext, mToken, nonNullDaemon);
mScheduler.scheduleClientMonitor(client1);
mScheduler.scheduleClientMonitor(client2);
@@ -109,17 +99,20 @@ public class BiometricSchedulerTest {
@Test
public void testRemovesPendingOperations_whenNullHal_andNotBiometricPrompt() {
// Even if second client has a non-null daemon, it needs to be canceled.
- final TestHalClientMonitor client1 = new TestHalClientMonitor(
- mContext, mToken, () -> null);
- final TestHalClientMonitor client2 = new TestHalClientMonitor(
- mContext, mToken, () -> mock(Object.class));
+ Object daemon2 = mock(Object.class);
+
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null;
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2;
+
+ final TestClientMonitor client1 = new TestClientMonitor(mContext, mToken, lazyDaemon1);
+ final TestClientMonitor client2 = new TestClientMonitor(mContext, mToken, lazyDaemon2);
final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
final BaseClientMonitor.Callback callback2 = mock(BaseClientMonitor.Callback.class);
// Pretend the scheduler is busy so the first operation doesn't start right away. We want
// to pretend like there are two operations in the queue before kicking things off
- mScheduler.mCurrentOperation = new BiometricSchedulerOperation(
+ mScheduler.mCurrentOperation = new BiometricScheduler.Operation(
mock(BaseClientMonitor.class), mock(BaseClientMonitor.Callback.class));
mScheduler.scheduleClientMonitor(client1, callback1);
@@ -129,11 +122,11 @@ public class BiometricSchedulerTest {
mScheduler.scheduleClientMonitor(client2, callback2);
waitForIdle();
- assertTrue(client1.mUnableToStart);
+ assertTrue(client1.wasUnableToStart());
verify(callback1).onClientFinished(eq(client1), eq(false) /* success */);
verify(callback1, never()).onClientStarted(any());
- assertTrue(client2.mUnableToStart);
+ assertTrue(client2.wasUnableToStart());
verify(callback2).onClientFinished(eq(client2), eq(false) /* success */);
verify(callback2, never()).onClientStarted(any());
@@ -145,19 +138,21 @@ public class BiometricSchedulerTest {
// Second non-BiometricPrompt client has a valid daemon
final Object daemon2 = mock(Object.class);
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null;
+ final HalClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2;
+
final ClientMonitorCallbackConverter listener1 = mock(ClientMonitorCallbackConverter.class);
final TestAuthenticationClient client1 =
- new TestAuthenticationClient(mContext, () -> null, mToken, listener1);
- final TestHalClientMonitor client2 =
- new TestHalClientMonitor(mContext, mToken, () -> daemon2);
+ new TestAuthenticationClient(mContext, lazyDaemon1, mToken, listener1);
+ final TestClientMonitor client2 = new TestClientMonitor(mContext, mToken, lazyDaemon2);
final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
final BaseClientMonitor.Callback callback2 = mock(BaseClientMonitor.Callback.class);
// Pretend the scheduler is busy so the first operation doesn't start right away. We want
// to pretend like there are two operations in the queue before kicking things off
- mScheduler.mCurrentOperation = new BiometricSchedulerOperation(
+ mScheduler.mCurrentOperation = new BiometricScheduler.Operation(
mock(BaseClientMonitor.class), mock(BaseClientMonitor.Callback.class));
mScheduler.scheduleClientMonitor(client1, callback1);
@@ -177,8 +172,8 @@ public class BiometricSchedulerTest {
verify(callback1, never()).onClientStarted(any());
// Client 2 was able to start
- assertFalse(client2.mUnableToStart);
- assertTrue(client2.mStarted);
+ assertFalse(client2.wasUnableToStart());
+ assertTrue(client2.hasStarted());
verify(callback2).onClientStarted(eq(client2));
}
@@ -192,18 +187,16 @@ public class BiometricSchedulerTest {
// Schedule a BiometricPrompt authentication request
mScheduler.scheduleClientMonitor(client1, callback1);
- assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart());
- assertEquals(client1, mScheduler.mCurrentOperation.getClientMonitor());
+ assertEquals(Operation.STATE_WAITING_FOR_COOKIE, mScheduler.mCurrentOperation.mState);
+ assertEquals(client1, mScheduler.mCurrentOperation.mClientMonitor);
assertEquals(0, mScheduler.mPendingOperations.size());
// Request it to be canceled. The operation can be canceled immediately, and the scheduler
// should go back to idle, since in this case the framework has not even requested the HAL
// to authenticate yet.
mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */);
- waitForIdle();
assertTrue(client1.isAlreadyDone());
assertTrue(client1.mDestroyed);
- assertFalse(client1.mStartedHal);
assertNull(mScheduler.mCurrentOperation);
}
@@ -217,8 +210,8 @@ public class BiometricSchedulerTest {
// assertEquals(0, bsp.recentOperations.length);
// Pretend the scheduler is busy enrolling, and check the proto dump again.
- final TestHalClientMonitor client = new TestHalClientMonitor(mContext, mToken,
- () -> mock(Object.class), 0, BiometricsProto.CM_ENROLL);
+ final TestClientMonitor2 client = new TestClientMonitor2(mContext, mToken,
+ () -> mock(Object.class), BiometricsProto.CM_ENROLL);
mScheduler.scheduleClientMonitor(client);
waitForIdle();
bsp = getDump(true /* clearSchedulerBuffer */);
@@ -237,8 +230,8 @@ public class BiometricSchedulerTest {
@Test
public void testProtoDump_fifo() throws Exception {
// Add the first operation
- final TestHalClientMonitor client = new TestHalClientMonitor(mContext, mToken,
- () -> mock(Object.class), 0, BiometricsProto.CM_ENROLL);
+ final TestClientMonitor2 client = new TestClientMonitor2(mContext, mToken,
+ () -> mock(Object.class), BiometricsProto.CM_ENROLL);
mScheduler.scheduleClientMonitor(client);
waitForIdle();
BiometricSchedulerProto bsp = getDump(false /* clearSchedulerBuffer */);
@@ -251,8 +244,8 @@ public class BiometricSchedulerTest {
client.getCallback().onClientFinished(client, true);
// Add another operation
- final TestHalClientMonitor client2 = new TestHalClientMonitor(mContext, mToken,
- () -> mock(Object.class), 0, BiometricsProto.CM_REMOVE);
+ final TestClientMonitor2 client2 = new TestClientMonitor2(mContext, mToken,
+ () -> mock(Object.class), BiometricsProto.CM_REMOVE);
mScheduler.scheduleClientMonitor(client2);
waitForIdle();
bsp = getDump(false /* clearSchedulerBuffer */);
@@ -263,8 +256,8 @@ public class BiometricSchedulerTest {
client2.getCallback().onClientFinished(client2, true);
// And another operation
- final TestHalClientMonitor client3 = new TestHalClientMonitor(mContext, mToken,
- () -> mock(Object.class), 0, BiometricsProto.CM_AUTHENTICATE);
+ final TestClientMonitor2 client3 = new TestClientMonitor2(mContext, mToken,
+ () -> mock(Object.class), BiometricsProto.CM_AUTHENTICATE);
mScheduler.scheduleClientMonitor(client3);
waitForIdle();
bsp = getDump(false /* clearSchedulerBuffer */);
@@ -297,7 +290,8 @@ public class BiometricSchedulerTest {
@Test
public void testCancelPendingAuth() throws RemoteException {
final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class);
- final TestHalClientMonitor client1 = new TestHalClientMonitor(mContext, mToken, lazyDaemon);
+
+ final TestClientMonitor client1 = new TestClientMonitor(mContext, mToken, lazyDaemon);
final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class);
final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, lazyDaemon,
mToken, callback);
@@ -308,12 +302,14 @@ public class BiometricSchedulerTest {
waitForIdle();
assertEquals(mScheduler.getCurrentClient(), client1);
- assertFalse(mScheduler.mPendingOperations.getFirst().isStarted());
+ assertEquals(Operation.STATE_WAITING_IN_QUEUE,
+ mScheduler.mPendingOperations.getFirst().mState);
// Request cancel before the authentication client has started
mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */);
waitForIdle();
- assertTrue(mScheduler.mPendingOperations.getFirst().isMarkedCanceling());
+ assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING,
+ mScheduler.mPendingOperations.getFirst().mState);
// Finish the blocking client. The authentication client should send ERROR_CANCELED
client1.getCallback().onClientFinished(client1, true /* success */);
@@ -330,109 +326,67 @@ public class BiometricSchedulerTest {
@Test
public void testCancels_whenAuthRequestIdNotSet() {
- testCancelsAuthDetectWhenRequestId(null /* requestId */, 2, true /* started */);
+ testCancelsWhenRequestId(null /* requestId */, 2, true /* started */);
}
@Test
public void testCancels_whenAuthRequestIdNotSet_notStarted() {
- testCancelsAuthDetectWhenRequestId(null /* requestId */, 2, false /* started */);
+ testCancelsWhenRequestId(null /* requestId */, 2, false /* started */);
}
@Test
public void testCancels_whenAuthRequestIdMatches() {
- testCancelsAuthDetectWhenRequestId(200L, 200, true /* started */);
+ testCancelsWhenRequestId(200L, 200, true /* started */);
}
@Test
public void testCancels_whenAuthRequestIdMatches_noStarted() {
- testCancelsAuthDetectWhenRequestId(200L, 200, false /* started */);
+ testCancelsWhenRequestId(200L, 200, false /* started */);
}
@Test
public void testDoesNotCancel_whenAuthRequestIdMismatched() {
- testCancelsAuthDetectWhenRequestId(10L, 20, true /* started */);
+ testCancelsWhenRequestId(10L, 20, true /* started */);
}
@Test
public void testDoesNotCancel_whenAuthRequestIdMismatched_notStarted() {
- testCancelsAuthDetectWhenRequestId(10L, 20, false /* started */);
- }
-
- private void testCancelsAuthDetectWhenRequestId(@Nullable Long requestId, long cancelRequestId,
- boolean started) {
- final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class);
- final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class);
- testCancelsWhenRequestId(requestId, cancelRequestId, started,
- new TestAuthenticationClient(mContext, lazyDaemon, mToken, callback));
- }
-
- @Test
- public void testCancels_whenEnrollRequestIdNotSet() {
- testCancelsEnrollWhenRequestId(null /* requestId */, 2, false /* started */);
- }
-
- @Test
- public void testCancels_whenEnrollRequestIdMatches() {
- testCancelsEnrollWhenRequestId(200L, 200, false /* started */);
- }
-
- @Test
- public void testDoesNotCancel_whenEnrollRequestIdMismatched() {
- testCancelsEnrollWhenRequestId(10L, 20, false /* started */);
+ testCancelsWhenRequestId(10L, 20, false /* started */);
}
- private void testCancelsEnrollWhenRequestId(@Nullable Long requestId, long cancelRequestId,
+ private void testCancelsWhenRequestId(@Nullable Long requestId, long cancelRequestId,
boolean started) {
+ final boolean matches = requestId == null || requestId == cancelRequestId;
final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class);
final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class);
- testCancelsWhenRequestId(requestId, cancelRequestId, started,
- new TestEnrollClient(mContext, lazyDaemon, mToken, callback));
- }
-
- private void testCancelsWhenRequestId(@Nullable Long requestId, long cancelRequestId,
- boolean started, HalClientMonitor<?> client) {
- final boolean matches = requestId == null || requestId == cancelRequestId;
+ final TestAuthenticationClient client = new TestAuthenticationClient(
+ mContext, lazyDaemon, mToken, callback);
if (requestId != null) {
client.setRequestId(requestId);
}
- final boolean isAuth = client instanceof TestAuthenticationClient;
- final boolean isEnroll = client instanceof TestEnrollClient;
-
mScheduler.scheduleClientMonitor(client);
if (started) {
mScheduler.startPreparedClient(client.getCookie());
}
waitForIdle();
- if (isAuth) {
- mScheduler.cancelAuthenticationOrDetection(mToken, cancelRequestId);
- } else if (isEnroll) {
- mScheduler.cancelEnrollment(mToken, cancelRequestId);
- } else {
- fail("unexpected operation type");
- }
+ mScheduler.cancelAuthenticationOrDetection(mToken, cancelRequestId);
waitForIdle();
- if (isAuth) {
- // auth clients that were waiting for cookie when canceled should never invoke the hal
- final TestAuthenticationClient authClient = (TestAuthenticationClient) client;
- assertEquals(matches && started ? 1 : 0, authClient.mNumCancels);
- assertEquals(started, authClient.mStartedHal);
- } else if (isEnroll) {
- final TestEnrollClient enrollClient = (TestEnrollClient) client;
- assertEquals(matches ? 1 : 0, enrollClient.mNumCancels);
- assertTrue(enrollClient.mStartedHal);
- }
+ assertEquals(matches && started ? 1 : 0, client.mNumCancels);
if (matches) {
- if (started || isEnroll) { // prep'd auth clients and enroll clients
- assertTrue(mScheduler.mCurrentOperation.isCanceling());
+ if (started) {
+ assertEquals(Operation.STATE_STARTED_CANCELING,
+ mScheduler.mCurrentOperation.mState);
}
} else {
- if (started || isEnroll) { // prep'd auth clients and enroll clients
- assertTrue(mScheduler.mCurrentOperation.isStarted());
+ if (started) {
+ assertEquals(Operation.STATE_STARTED,
+ mScheduler.mCurrentOperation.mState);
} else {
- assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart());
+ assertEquals(Operation.STATE_WAITING_FOR_COOKIE,
+ mScheduler.mCurrentOperation.mState);
}
}
}
@@ -457,14 +411,18 @@ public class BiometricSchedulerTest {
mScheduler.cancelAuthenticationOrDetection(mToken, 9999);
waitForIdle();
- assertTrue(mScheduler.mCurrentOperation.isStarted());
- assertFalse(mScheduler.mPendingOperations.getFirst().isStarted());
+ assertEquals(Operation.STATE_STARTED,
+ mScheduler.mCurrentOperation.mState);
+ assertEquals(Operation.STATE_WAITING_IN_QUEUE,
+ mScheduler.mPendingOperations.getFirst().mState);
mScheduler.cancelAuthenticationOrDetection(mToken, requestId2);
waitForIdle();
- assertTrue(mScheduler.mCurrentOperation.isStarted());
- assertTrue(mScheduler.mPendingOperations.getFirst().isMarkedCanceling());
+ assertEquals(Operation.STATE_STARTED,
+ mScheduler.mCurrentOperation.mState);
+ assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING,
+ mScheduler.mPendingOperations.getFirst().mState);
}
@Test
@@ -501,12 +459,12 @@ public class BiometricSchedulerTest {
@Test
public void testClientDestroyed_afterFinish() {
final HalClientMonitor.LazyDaemon<Object> nonNullDaemon = () -> mock(Object.class);
- final TestHalClientMonitor client =
- new TestHalClientMonitor(mContext, mToken, nonNullDaemon);
+ final TestClientMonitor client =
+ new TestClientMonitor(mContext, mToken, nonNullDaemon);
mScheduler.scheduleClientMonitor(client);
client.mCallback.onClientFinished(client, true /* success */);
waitForIdle();
- assertTrue(client.mDestroyed);
+ assertTrue(client.wasDestroyed());
}
private BiometricSchedulerProto getDump(boolean clearSchedulerBuffer) throws Exception {
@@ -514,10 +472,8 @@ public class BiometricSchedulerTest {
}
private static class TestAuthenticationClient extends AuthenticationClient<Object> {
- boolean mStartedHal = false;
- boolean mStoppedHal = false;
- boolean mDestroyed = false;
int mNumCancels = 0;
+ boolean mDestroyed = false;
public TestAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token,
@@ -532,16 +488,18 @@ public class BiometricSchedulerTest {
@Override
protected void stopHalOperation() {
- mStoppedHal = true;
+
}
@Override
protected void startHalOperation() {
- mStartedHal = true;
+
}
@Override
- protected void handleLifecycleAfterAuth(boolean authenticated) {}
+ protected void handleLifecycleAfterAuth(boolean authenticated) {
+
+ }
@Override
public boolean wasUserDetected() {
@@ -561,59 +519,36 @@ public class BiometricSchedulerTest {
}
}
- private static class TestEnrollClient extends EnrollClient<Object> {
- boolean mStartedHal = false;
- boolean mStoppedHal = false;
- int mNumCancels = 0;
-
- TestEnrollClient(@NonNull Context context,
- @NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token,
- @NonNull ClientMonitorCallbackConverter listener) {
- super(context, lazyDaemon, token, listener, 0 /* userId */, new byte[69],
- "test" /* owner */, mock(BiometricUtils.class),
- 5 /* timeoutSec */, 0 /* statsModality */, TEST_SENSOR_ID,
- true /* shouldVibrate */);
- }
-
- @Override
- protected void stopHalOperation() {
- mStoppedHal = true;
- }
-
- @Override
- protected void startHalOperation() {
- mStartedHal = true;
- }
+ private static class TestClientMonitor2 extends TestClientMonitor {
+ private final int mProtoEnum;
- @Override
- protected boolean hasReachedEnrollmentLimit() {
- return false;
+ public TestClientMonitor2(@NonNull Context context, @NonNull IBinder token,
+ @NonNull LazyDaemon<Object> lazyDaemon, int protoEnum) {
+ super(context, token, lazyDaemon);
+ mProtoEnum = protoEnum;
}
@Override
- public void cancel() {
- mNumCancels++;
- super.cancel();
+ public int getProtoEnum() {
+ return mProtoEnum;
}
}
- private static class TestHalClientMonitor extends HalClientMonitor<Object> {
- private final int mProtoEnum;
+ private static class TestClientMonitor extends HalClientMonitor<Object> {
private boolean mUnableToStart;
private boolean mStarted;
private boolean mDestroyed;
- TestHalClientMonitor(@NonNull Context context, @NonNull IBinder token,
+ public TestClientMonitor(@NonNull Context context, @NonNull IBinder token,
@NonNull LazyDaemon<Object> lazyDaemon) {
- this(context, token, lazyDaemon, 0 /* cookie */, BiometricsProto.CM_UPDATE_ACTIVE_USER);
+ this(context, token, lazyDaemon, 0 /* cookie */);
}
- TestHalClientMonitor(@NonNull Context context, @NonNull IBinder token,
- @NonNull LazyDaemon<Object> lazyDaemon, int cookie, int protoEnum) {
+ public TestClientMonitor(@NonNull Context context, @NonNull IBinder token,
+ @NonNull LazyDaemon<Object> lazyDaemon, int cookie) {
super(context, lazyDaemon, token /* token */, null /* listener */, 0 /* userId */,
TAG, cookie, TEST_SENSOR_ID, 0 /* statsModality */,
0 /* statsAction */, 0 /* statsClient */);
- mProtoEnum = protoEnum;
}
@Override
@@ -624,7 +559,9 @@ public class BiometricSchedulerTest {
@Override
public int getProtoEnum() {
- return mProtoEnum;
+ // Anything other than CM_NONE, which is used to represent "idle". Tests that need
+ // real proto enums should use TestClientMonitor2
+ return BiometricsProto.CM_UPDATE_ACTIVE_USER;
}
@Override
@@ -636,7 +573,7 @@ public class BiometricSchedulerTest {
@Override
protected void startHalOperation() {
- mStarted = true;
+
}
@Override
@@ -644,9 +581,22 @@ public class BiometricSchedulerTest {
super.destroy();
mDestroyed = true;
}
+
+ public boolean wasUnableToStart() {
+ return mUnableToStart;
+ }
+
+ public boolean hasStarted() {
+ return mStarted;
+ }
+
+ public boolean wasDestroyed() {
+ return mDestroyed;
+ }
+
}
- private void waitForIdle() {
- TestableLooper.get(this).processAllMessages();
+ private static void waitForIdle() {
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/LockoutResetDispatcherTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/LockoutResetDispatcherTest.java
new file mode 100644
index 000000000000..a53e22e6e58e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/LockoutResetDispatcherTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IRemoteCallback;
+import android.platform.test.annotations.Presubmit;
+import android.testing.TestableContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@Presubmit
+@SmallTest
+public class LockoutResetDispatcherTest {
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Rule
+ public final TestableContext mContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
+ @Mock
+ private IBinder mBinder;
+ @Mock
+ private IBiometricServiceLockoutResetCallback mCallback;
+
+ private LockoutResetDispatcher mDispatcher;
+
+ @Before
+ public void setup() {
+ when(mCallback.asBinder()).thenReturn(mBinder);
+ mDispatcher = new LockoutResetDispatcher(mContext);
+ }
+
+ @Test
+ public void linksToDeath() throws Exception {
+ mDispatcher.addCallback(mCallback, "package");
+ verify(mBinder).linkToDeath(eq(mDispatcher), anyInt());
+ }
+
+ @Test
+ public void notifyLockoutReset() throws Exception {
+ final int sensorId = 24;
+
+ mDispatcher.addCallback(mCallback, "some.package");
+ mDispatcher.notifyLockoutResetCallbacks(sensorId);
+
+ final ArgumentCaptor<IRemoteCallback> captor =
+ ArgumentCaptor.forClass(IRemoteCallback.class);
+ verify(mCallback).onLockoutReset(eq(sensorId), captor.capture());
+ captor.getValue().sendResult(new Bundle());
+ }
+
+ @Test
+ public void releaseWakeLockOnDeath() {
+ mDispatcher.addCallback(mCallback, "a.b.cee");
+ mDispatcher.binderDied(mBinder);
+
+ // would be better to check the wake lock
+ // but this project lacks the extended mockito support to do it
+ assertThat(mDispatcher.mClientCallbacks).isEmpty();
+ }
+
+ @Test
+ public void releaseCorrectWakeLockOnDeath() {
+ mDispatcher.addCallback(mCallback, "a.b");
+ mDispatcher.binderDied(mock(IBinder.class));
+
+ assertThat(mDispatcher.mClientCallbacks).hasSize(1);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
index 407f5fb04adf..7fccd49db04b 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
@@ -16,8 +16,6 @@
package com.android.server.biometrics.sensors;
-import static android.testing.TestableLooper.RunWithLooper;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
@@ -30,53 +28,52 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.biometrics.IBiometricService;
import android.os.Binder;
-import android.os.Handler;
import android.os.IBinder;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@Presubmit
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
@SmallTest
public class UserAwareBiometricSchedulerTest {
- private static final String TAG = "UserAwareBiometricSchedulerTest";
+ private static final String TAG = "BiometricSchedulerTest";
private static final int TEST_SENSOR_ID = 0;
- private Handler mHandler;
private UserAwareBiometricScheduler mScheduler;
- private IBinder mToken = new Binder();
+ private IBinder mToken;
@Mock
private Context mContext;
@Mock
private IBiometricService mBiometricService;
- private TestUserStartedCallback mUserStartedCallback = new TestUserStartedCallback();
- private TestUserStoppedCallback mUserStoppedCallback = new TestUserStoppedCallback();
+ private TestUserStartedCallback mUserStartedCallback;
+ private TestUserStoppedCallback mUserStoppedCallback;
private int mCurrentUserId = UserHandle.USER_NULL;
- private boolean mStartOperationsFinish = true;
- private int mStartUserClientCount = 0;
+ private boolean mStartOperationsFinish;
+ private int mStartUserClientCount;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mHandler = new Handler(TestableLooper.get(this).getLooper());
+
+ mToken = new Binder();
+ mStartOperationsFinish = true;
+ mStartUserClientCount = 0;
+ mUserStartedCallback = new TestUserStartedCallback();
+ mUserStoppedCallback = new TestUserStoppedCallback();
+
mScheduler = new UserAwareBiometricScheduler(TAG,
- mHandler,
BiometricScheduler.SENSOR_TYPE_UNKNOWN,
null /* gestureAvailabilityDispatcher */,
mBiometricService,
@@ -120,7 +117,7 @@ public class UserAwareBiometricSchedulerTest {
mCurrentUserId = UserHandle.USER_NULL;
mStartOperationsFinish = false;
- final BaseClientMonitor[] nextClients = new BaseClientMonitor[]{
+ final BaseClientMonitor[] nextClients = new BaseClientMonitor[] {
mock(BaseClientMonitor.class),
mock(BaseClientMonitor.class),
mock(BaseClientMonitor.class)
@@ -150,11 +147,11 @@ public class UserAwareBiometricSchedulerTest {
waitForIdle();
final TestStartUserClient startUserClient =
- (TestStartUserClient) mScheduler.mCurrentOperation.getClientMonitor();
+ (TestStartUserClient) mScheduler.mCurrentOperation.mClientMonitor;
mScheduler.reset();
assertNull(mScheduler.mCurrentOperation);
- final BiometricSchedulerOperation fakeOperation = new BiometricSchedulerOperation(
+ final BiometricScheduler.Operation fakeOperation = new BiometricScheduler.Operation(
mock(BaseClientMonitor.class), new BaseClientMonitor.Callback() {});
mScheduler.mCurrentOperation = fakeOperation;
startUserClient.mCallback.onClientFinished(startUserClient, true);
@@ -197,8 +194,8 @@ public class UserAwareBiometricSchedulerTest {
verify(nextClient).start(any());
}
- private void waitForIdle() {
- TestableLooper.get(this).processAllMessages();
+ private static void waitForIdle() {
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
private class TestUserStoppedCallback implements StopUserClient.UserStoppedCallback {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
index 0891eca9f61c..a13dff21439d 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
@@ -79,7 +79,6 @@ public class SensorTest {
when(mContext.getSystemService(Context.BIOMETRIC_SERVICE)).thenReturn(mBiometricService);
mScheduler = new UserAwareBiometricScheduler(TAG,
- new Handler(mLooper.getLooper()),
BiometricScheduler.SENSOR_TYPE_FACE,
null /* gestureAvailabilityDispatcher */,
() -> USER_ID,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
index 21a7a8ae65b9..39c51d5f5e5e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java
@@ -32,9 +32,7 @@ import android.hardware.face.FaceSensorProperties;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
-import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
@@ -71,7 +69,6 @@ public class Face10Test {
@Mock
private BiometricScheduler mScheduler;
- private final Handler mHandler = new Handler(Looper.getMainLooper());
private LockoutResetDispatcher mLockoutResetDispatcher;
private com.android.server.biometrics.sensors.face.hidl.Face10 mFace10;
private IBinder mBinder;
@@ -100,7 +97,7 @@ public class Face10Test {
resetLockoutRequiresChallenge);
Face10.sSystemClock = Clock.fixed(Instant.ofEpochMilli(100), ZoneId.of("PST"));
- mFace10 = new Face10(mContext, sensorProps, mLockoutResetDispatcher, mHandler, mScheduler);
+ mFace10 = new Face10(mContext, sensorProps, mLockoutResetDispatcher, mScheduler);
mBinder = new Binder();
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
index a012b8b06c7f..0d520ca9a4e4 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
@@ -79,7 +79,6 @@ public class SensorTest {
when(mContext.getSystemService(Context.BIOMETRIC_SERVICE)).thenReturn(mBiometricService);
mScheduler = new UserAwareBiometricScheduler(TAG,
- new Handler(mLooper.getLooper()),
BiometricScheduler.SENSOR_TYPE_FP_OTHER,
null /* gestureAvailabilityDispatcher */,
() -> USER_ID,
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index 62a2b1be139d..59f2ca4f6106 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -187,7 +187,7 @@ public class PackageInstallerSessionTest {
/* isFailed */ false,
/* isApplied */false,
/* stagedSessionErrorCode */
- PackageInstaller.SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+ PackageInstaller.SessionInfo.SESSION_VERIFICATION_FAILED,
/* stagedSessionErrorMessage */ "some error");
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index cf6165fdbd79..e4273dce7893 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -375,7 +375,7 @@ public final class UserManagerTest {
switchUser(user1.id, null, /* ignoreHandle= */ true);
assertThat(mUserManager.removeUserOrSetEphemeral(user1.id, /* evenWhenDisallowed= */ false))
- .isEqualTo(UserManager.REMOVE_RESULT_SET_EPHEMERAL);
+ .isEqualTo(UserManager.REMOVE_RESULT_DEFERRED);
assertThat(hasUser(user1.id)).isTrue();
assertThat(getUser(user1.id).isEphemeral()).isTrue();
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
index 26b34fdd4e04..304fe5a1c9c3 100644
--- a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
@@ -30,6 +30,7 @@ import android.hardware.power.stats.PowerEntity;
import android.hardware.power.stats.State;
import android.hardware.power.stats.StateResidency;
import android.hardware.power.stats.StateResidencyResult;
+import android.os.Looper;
import androidx.test.InstrumentationRegistry;
@@ -145,12 +146,12 @@ public class PowerStatsServiceTest {
}
@Override
- PowerStatsLogger createPowerStatsLogger(Context context, File dataStoragePath,
- String meterFilename, String meterCacheFilename,
+ PowerStatsLogger createPowerStatsLogger(Context context, Looper looper,
+ File dataStoragePath, String meterFilename, String meterCacheFilename,
String modelFilename, String modelCacheFilename,
String residencyFilename, String residencyCacheFilename,
IPowerStatsHALWrapper powerStatsHALWrapper) {
- mPowerStatsLogger = new PowerStatsLogger(context, dataStoragePath,
+ mPowerStatsLogger = new PowerStatsLogger(context, looper, dataStoragePath,
meterFilename, meterCacheFilename,
modelFilename, modelCacheFilename,
residencyFilename, residencyCacheFilename,
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java
index b934ecb80564..739b3b179de7 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java
@@ -54,11 +54,10 @@ public class DeviceVibrationEffectAdapterTest {
/* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f};
private static final VibratorInfo.FrequencyMapping EMPTY_FREQUENCY_MAPPING =
- new VibratorInfo.FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, Float.NaN, null);
+ new VibratorInfo.FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, null);
private static final VibratorInfo.FrequencyMapping TEST_FREQUENCY_MAPPING =
- new VibratorInfo.FrequencyMapping(TEST_MIN_FREQUENCY,
- TEST_RESONANT_FREQUENCY, TEST_FREQUENCY_RESOLUTION,
- /* suggestedSafeRangeHz= */ 50, TEST_AMPLITUDE_MAP);
+ new VibratorInfo.FrequencyMapping(TEST_RESONANT_FREQUENCY, TEST_MIN_FREQUENCY,
+ TEST_FREQUENCY_RESOLUTION, TEST_AMPLITUDE_MAP);
private DeviceVibrationEffectAdapter mAdapter;
@@ -87,14 +86,14 @@ public class DeviceVibrationEffectAdapterTest {
@Test
public void testStepAndRampSegments_withoutPwleCapability_convertsRampsToSteps() {
VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 200, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 150, /* duration= */ 100),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10),
+ /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 300, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 100),
+ /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 0, /* duration= */ 100),
new RampSegment(/* startAmplitude= */ 0.65f, /* endAmplitude= */ 0.65f,
- /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 1000)),
+ /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 1, /* duration= */ 1000)),
/* repeatIndex= */ 3);
VibrationEffect.Composed adaptedEffect = (VibrationEffect.Composed) mAdapter.apply(effect,
@@ -110,23 +109,23 @@ public class DeviceVibrationEffectAdapterTest {
@Test
public void testStepAndRampSegments_withPwleCapability_convertsStepsToRamps() {
VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 175, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 150, /* duration= */ 60),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50),
+ /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)),
+ /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20)),
/* repeatIndex= */ 2);
VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0,
- /* startFrequency= */ 175, /* endFrequency= */ 175, /* duration= */ 10),
+ /* startFrequencyHz= */ 175, /* endFrequencyHz= */ 175, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
- /* startFrequency= */ 150, /* endFrequency= */ 150, /* duration= */ 100),
+ /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 60),
new RampSegment(/* startAmplitude= */ 0.1f, /* endAmplitude= */ 0.8f,
- /* startFrequency= */ 50, /* endFrequency= */ 200, /* duration= */ 50),
+ /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.1f,
- /* startFrequency= */ 200, /* endFrequency= */ 50, /* duration= */ 20)),
+ /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 50, /* duration= */ 20)),
/* repeatIndex= */ 2);
VibratorInfo info = createVibratorInfo(TEST_FREQUENCY_MAPPING,
@@ -135,28 +134,28 @@ public class DeviceVibrationEffectAdapterTest {
}
@Test
- public void testStepAndRampSegments_withEmptyFreqMapping_returnsSameAmplitudesAndZeroFreq() {
+ public void testStepAndRampSegments_withEmptyFreqMapping_returnsAmplitudesWithResonantFreq() {
VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 175, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 1,
- /* startFrequency= */ -1, /* endFrequency= */ 1, /* duration= */ 50),
+ /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.7f, /* endAmplitude= */ 0.5f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)),
+ /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20)),
/* repeatIndex= */ 2);
VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
- /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN,
+ /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN,
/* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
- /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN,
+ /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN,
/* duration= */ 100),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 1,
- /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN,
+ /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN,
/* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.7f, /* endAmplitude= */ 0.5f,
- /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN,
+ /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN,
/* duration= */ 20)),
/* repeatIndex= */ 2);
@@ -168,25 +167,25 @@ public class DeviceVibrationEffectAdapterTest {
@Test
public void testStepAndRampSegments_withValidFreqMapping_returnsClippedValues() {
VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList(
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 1, /* frequency= */ -1, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 125, /* duration= */ 100),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50),
+ /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)),
+ /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20)),
/* repeatIndex= */ 2);
VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList(
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
- /* startFrequency= */ 150, /* endFrequency= */ 150,
+ /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150,
/* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f,
- /* startFrequency= */ 125, /* endFrequency= */ 125,
+ /* startFrequencyHz= */ 125, /* endFrequencyHz= */ 125,
/* duration= */ 100),
new RampSegment(/* startAmplitude= */ 0.1f, /* endAmplitude= */ 0.8f,
- /* startFrequency= */ 50, /* endFrequency= */ 200, /* duration= */ 50),
+ /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.1f,
- /* startFrequency= */ 200, /* endFrequency= */ 50, /* duration= */ 20)),
+ /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 50, /* duration= */ 20)),
/* repeatIndex= */ 2);
VibratorInfo info = createVibratorInfo(TEST_FREQUENCY_MAPPING,
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibrator.java b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibrator.java
index e2a348efa409..4556a4a47017 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibrator.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibrator.java
@@ -17,6 +17,7 @@
package com.android.server.vibrator;
import android.annotation.NonNull;
+import android.content.Context;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
@@ -24,37 +25,8 @@ import android.os.Vibrator;
/** Fake implementation of {@link Vibrator} for service tests. */
final class FakeVibrator extends Vibrator {
- private int mDefaultHapticFeedbackIntensity = Vibrator.VIBRATION_INTENSITY_MEDIUM;
- private int mDefaultNotificationIntensity = Vibrator.VIBRATION_INTENSITY_MEDIUM;
- private int mDefaultRingIntensity = Vibrator.VIBRATION_INTENSITY_MEDIUM;
-
- @Override
- public int getDefaultHapticFeedbackIntensity() {
- return mDefaultHapticFeedbackIntensity;
- }
-
- @Override
- public int getDefaultNotificationVibrationIntensity() {
- return mDefaultNotificationIntensity;
- }
-
- @Override
- public int getDefaultRingVibrationIntensity() {
- return mDefaultRingIntensity;
- }
-
- public void setDefaultHapticFeedbackIntensity(
- @VibrationIntensity int defaultHapticFeedbackIntensity) {
- mDefaultHapticFeedbackIntensity = defaultHapticFeedbackIntensity;
- }
-
- public void setDefaultNotificationVibrationIntensity(
- @VibrationIntensity int defaultNotificationIntensity) {
- mDefaultNotificationIntensity = defaultNotificationIntensity;
- }
-
- public void setDefaultRingVibrationIntensity(@VibrationIntensity int defaultRingIntensity) {
- mDefaultRingIntensity = defaultRingIntensity;
+ FakeVibrator(Context context) {
+ super(context);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java
index 777e3f4e4a01..2ad0e93dd1fb 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java
@@ -87,7 +87,7 @@ final class FakeVibratorControllerProvider {
@Override
public long on(long milliseconds, long vibrationId) {
mEffectSegments.add(new StepSegment(VibrationEffect.DEFAULT_AMPLITUDE,
- /* frequency= */ 0, (int) milliseconds));
+ /* frequencyHz= */ 0, (int) milliseconds));
applyLatency();
scheduleListener(milliseconds, vibrationId);
return milliseconds;
@@ -158,7 +158,7 @@ final class FakeVibratorControllerProvider {
}
@Override
- public boolean getInfo(float suggestedFrequencyRange, VibratorInfo.Builder infoBuilder) {
+ public boolean getInfo(VibratorInfo.Builder infoBuilder) {
infoBuilder.setCapabilities(mCapabilities);
infoBuilder.setSupportedBraking(mSupportedBraking);
infoBuilder.setPwleSizeMax(mPwleSizeMax);
@@ -170,9 +170,8 @@ final class FakeVibratorControllerProvider {
}
infoBuilder.setCompositionSizeMax(mCompositionSizeMax);
infoBuilder.setQFactor(mQFactor);
- infoBuilder.setFrequencyMapping(new VibratorInfo.FrequencyMapping(mMinFrequency,
- mResonantFrequency, mFrequencyResolution, suggestedFrequencyRange,
- mMaxAmplitudes));
+ infoBuilder.setFrequencyMapping(new VibratorInfo.FrequencyMapping(
+ mResonantFrequency, mMinFrequency, mFrequencyResolution, mMaxAmplitudes));
return mIsInfoLoadSuccessful;
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java
index 4c3312c41550..a3edf2345a22 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java
@@ -70,9 +70,9 @@ public class RampDownAdapterTest {
@Test
public void testRampAndStepSegments_withNoOffSegment_keepsListUnchanged() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)));
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 50, /* duration= */ 20)));
List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
@@ -86,12 +86,12 @@ public class RampDownAdapterTest {
mAdapter = new RampDownAdapter(/* rampDownDuration= */ 0, TEST_STEP_DURATION);
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 100),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20),
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 50, /* duration= */ 20),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
- /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 50)));
+ /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 0, /* duration= */ 50)));
List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
@@ -102,12 +102,12 @@ public class RampDownAdapterTest {
@Test
public void testStepSegments_withShortZeroSegment_replaceWithStepsDown() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10)));
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 10)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5));
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5));
assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
assertEquals(expectedSegments, segments);
@@ -116,17 +116,17 @@ public class RampDownAdapterTest {
@Test
public void testStepSegments_withLongZeroSegment_replaceWithStepsDownWithRemainingOffSegment() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
- /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 50),
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)));
+ /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 0, /* duration= */ 50),
+ new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35),
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100));
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35),
+ new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100));
assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO));
assertEquals(expectedSegments, segments);
@@ -135,16 +135,16 @@ public class RampDownAdapterTest {
@Test
public void testStepSegments_withZeroSegmentBeforeRepeat_fixesRepeat() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 50),
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)));
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 50),
+ new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35),
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100));
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35),
+ new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100));
// Repeat index fixed after intermediate steps added
assertEquals(5, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
@@ -154,14 +154,14 @@ public class RampDownAdapterTest {
@Test
public void testStepSegments_withZeroSegmentAfterRepeat_preservesRepeat() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)));
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100));
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100));
assertEquals(3, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
assertEquals(expectedSegments, segments);
@@ -170,22 +170,22 @@ public class RampDownAdapterTest {
@Test
public void testStepSegments_withZeroSegmentAtRepeat_fixesRepeatAndAppendOriginalToListEnd() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 50),
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 100)));
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 50),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 100)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35),
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 100),
// Original zero segment appended to the end of new looping vibration,
// then converted to ramp down as well.
- new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35));
+ new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35));
// Repeat index fixed after intermediate steps added
assertEquals(5, mAdapter.apply(segments, 1, TEST_VIBRATOR_INFO));
@@ -195,8 +195,8 @@ public class RampDownAdapterTest {
@Test
public void testStepSegments_withRepeatToNonZeroSegment_keepsOriginalSteps() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100)));
+ new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100)));
List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
@@ -208,14 +208,14 @@ public class RampDownAdapterTest {
public void testStepSegments_withRepeatToShortZeroSegment_skipAndAppendRampDown() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
- /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30)));
+ /* startfrequencyHz= */ 0, /* endfrequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 30)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
- /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5));
+ /* startfrequencyHz= */ 0, /* endfrequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 30),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5));
// Shift repeat index to the right to use append instead of zero segment.
assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
@@ -226,17 +226,17 @@ public class RampDownAdapterTest {
@Test
public void testStepSegments_withRepeatToLongZeroSegment_splitAndAppendRampDown() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 120),
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30)));
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 120),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 30)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
// Split long zero segment to skip part of it.
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 20),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 100),
- new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30),
- new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5));
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 20),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 30),
+ new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5));
// Shift repeat index to the right to use append with part of the zero segment.
assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
@@ -248,18 +248,20 @@ public class RampDownAdapterTest {
public void testRampSegments_withShortZeroSegment_replaceWithRampDown() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10),
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20),
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 20),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)));
+ /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200,
+ /* duration= */ 30)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10),
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20),
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 20),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30));
+ /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200,
+ /* duration= */ 30));
assertEquals(2, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
@@ -269,20 +271,23 @@ public class RampDownAdapterTest {
@Test
public void testRampSegments_withLongZeroSegment_splitAndAddRampDown() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 150),
+ new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 150, /* duration= */ 150),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)));
+ /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200,
+ /* duration= */ 30)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10),
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20),
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 20),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 130),
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100,
+ /* duration= */ 130),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30));
+ /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200,
+ /* duration= */ 30));
// Repeat index fixed after intermediate steps added
assertEquals(3, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO));
@@ -294,9 +299,10 @@ public class RampDownAdapterTest {
public void testRampSegments_withRepeatToNonZeroSegment_keepsOriginalSteps() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10),
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)));
+ /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200,
+ /* duration= */ 30)));
List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
@@ -307,15 +313,15 @@ public class RampDownAdapterTest {
@Test
public void testRampSegments_withRepeatToShortZeroSegment_skipAndAppendRampDown() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 20),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 200, /* duration= */ 20),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 1,
- /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 20)));
+ /* startFrequencyHz= */ 40, /* endFrequencyHz= */ 80, /* duration= */ 20)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 20),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 200, /* duration= */ 20),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1,
- /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 20),
+ /* startFrequencyHz= */ 40, /* endFrequencyHz= */ 80, /* duration= */ 20),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20));
+ /* startFrequencyHz= */ 80, /* endFrequencyHz= */ 80, /* duration= */ 20));
// Shift repeat index to the right to use append instead of zero segment.
assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
@@ -327,19 +333,19 @@ public class RampDownAdapterTest {
public void testRampSegments_withRepeatToLongZeroSegment_splitAndAppendRampDown() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 70),
+ /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 70),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)));
+ /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 30)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
// Split long zero segment to skip part of it.
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20),
+ /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 20),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 50),
+ /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30),
+ /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 30),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20));
+ /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 20));
// Shift repeat index to the right to use append with part of the zero segment.
assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO));
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java
index 95c3bd93e69b..22db91736756 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java
@@ -45,6 +45,12 @@ import java.util.stream.IntStream;
@Presubmit
public class RampToStepAdapterTest {
private static final int TEST_STEP_DURATION = 5;
+ private static final float[] TEST_AMPLITUDE_MAP = new float[]{
+ /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f};
+ private static final VibratorInfo.FrequencyMapping TEST_FREQUENCY_MAPPING =
+ new VibratorInfo.FrequencyMapping(
+ /* resonantFrequencyHz= */ 150f, /* minFrequencyHz= */ 50f,
+ /* frequencyResolutionHz= */ 25f, TEST_AMPLITUDE_MAP);
private RampToStepAdapter mAdapter;
@@ -56,7 +62,7 @@ public class RampToStepAdapterTest {
@Test
public void testStepAndPrebakedAndPrimitiveSegments_keepsListUnchanged() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 1, /* duration= */ 10),
new PrebakedSegment(
VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT),
new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10)));
@@ -71,9 +77,9 @@ public class RampToStepAdapterTest {
@Test
public void testRampSegments_withPwleCapability_keepsListUnchanged() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)));
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 1, /* duration= */ 20)));
List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
@@ -86,27 +92,28 @@ public class RampToStepAdapterTest {
@Test
public void testRampSegments_withoutPwleCapability_convertsRampsToSteps() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 1, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 10, /* duration= */ 100),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10),
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 0, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ -3, /* endFrequency= */ 0, /* duration= */ 11),
+ /* startFrequencyHz= */ 30, /* endFrequencyHz= */ 60, /* duration= */ 11),
new RampSegment(/* startAmplitude= */ 0.65f, /* endAmplitude= */ 0.65f,
- /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 200)));
+ /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 1, /* duration= */ 200)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 1, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 10, /* duration= */ 100),
// 10ms ramp becomes 2 steps
- new StepSegment(/* amplitude= */ 1, /* frequency= */ -4, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.2f, /* frequency= */ 2, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 10, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.2f, /* frequencyHz= */ 150, /* duration= */ 5),
// 11ms ramp becomes 3 steps
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ -3, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.6f, /* frequency= */ -2, /* duration= */ 5),
- new StepSegment(/* amplitude= */ 0.2f, /* frequency= */ 0, /* duration= */ 1),
+ new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 30, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.6f, /* frequencyHz= */ 40, /* duration= */ 5),
+ new StepSegment(/* amplitude= */ 0.2f, /* frequencyHz= */ 60, /* duration= */ 1),
// 200ms ramp with same amplitude becomes a single step
- new StepSegment(/* amplitude= */ 0.65f, /* frequency= */ 0, /* duration= */ 200));
+ new StepSegment(/* amplitude= */ 0.65f, /* frequencyHz= */ 150,
+ /* duration= */ 200));
// Repeat index fixed after intermediate steps added
assertEquals(4, mAdapter.apply(segments, 3, createVibratorInfo()));
@@ -117,6 +124,7 @@ public class RampToStepAdapterTest {
private static VibratorInfo createVibratorInfo(int... capabilities) {
return new VibratorInfo.Builder(0)
.setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0))
+ .setFrequencyMapping(TEST_FREQUENCY_MAPPING)
.build();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java
index 128cd2f9e0a1..18ff953446a2 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java
@@ -44,6 +44,13 @@ import java.util.stream.IntStream;
*/
@Presubmit
public class StepToRampAdapterTest {
+ private static final float[] TEST_AMPLITUDE_MAP = new float[]{
+ /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f};
+ private static final VibratorInfo.FrequencyMapping TEST_FREQUENCY_MAPPING =
+ new VibratorInfo.FrequencyMapping(
+ /* resonantFrequencyHz= */ 150f, /* minFrequencyHz= */ 50f,
+ /* frequencyResolutionHz= */ 25f, TEST_AMPLITUDE_MAP);
+
private StepToRampAdapter mAdapter;
@Before
@@ -55,7 +62,7 @@ public class StepToRampAdapterTest {
public void testRampAndPrebakedAndPrimitiveSegments_returnsOriginalSegments() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10),
+ /* startFrequencyHz= */ 40f, /* endFrequencyHz= */ 20f, /* duration= */ 10),
new PrebakedSegment(
VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT),
new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10)));
@@ -71,27 +78,28 @@ public class StepToRampAdapterTest {
public void testRampSegments_withPwleDurationLimit_splitsLongRamps() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10),
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 10, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1,
- /* startFrequency= */ 0, /* endFrequency= */ -1, /* duration= */ 25),
+ /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 50, /* duration= */ 25),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude*/ 1,
- /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 5)));
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 20, /* duration= */ 5)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10),
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 10, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0.32f,
- /* startFrequency= */ 0, /* endFrequency= */ -0.32f, /* duration= */ 8),
+ /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 118f, /* duration= */ 8),
new RampSegment(/* startAmplitude= */ 0.32f, /* endAmplitude= */ 0.64f,
- /* startFrequency= */ -0.32f, /* endFrequency= */ -0.64f,
+ /* startFrequencyHz= */ 118f, /* endFrequencyHz= */ 86f,
/* duration= */ 8),
new RampSegment(/* startAmplitude= */ 0.64f, /* endAmplitude= */ 1,
- /* startFrequency= */ -0.64f, /* endFrequency= */ -1, /* duration= */ 9),
+ /* startFrequencyHz= */ 86f, /* endFrequencyHz= */ 50f, /* duration= */ 9),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude*/ 1,
- /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 5));
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 20, /* duration= */ 5));
VibratorInfo vibratorInfo = new VibratorInfo.Builder(0)
.setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)
.setPwlePrimitiveDurationMax(10)
+ .setFrequencyMapping(TEST_FREQUENCY_MAPPING)
.build();
// Update repeat index to skip the ramp splits.
@@ -102,9 +110,9 @@ public class StepToRampAdapterTest {
@Test
public void testStepAndRampSegments_withoutPwleCapability_keepsListUnchanged() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 1, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)));
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 50, /* duration= */ 20)));
List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
assertEquals(-1, mAdapter.apply(segments, -1, createVibratorInfo()));
@@ -116,13 +124,13 @@ public class StepToRampAdapterTest {
@Test
public void testStepAndRampSegments_withPwleCapabilityAndNoFrequency_keepsOriginalSteps() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100),
new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50),
+ /* startFrequencyHz= */ 40, /* endFrequencyHz= */ 200, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)));
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 1, /* duration= */ 20)));
List<VibrationEffectSegment> originalSegments = new ArrayList<>(segments);
VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
@@ -135,25 +143,25 @@ public class StepToRampAdapterTest {
@Test
public void testStepAndRampSegments_withPwleCapabilityAndStepNextToRamp_convertsStepsToRamps() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100),
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 200, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 150, /* duration= */ 60),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50),
+ /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 300, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20),
- new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ -1, /* duration= */ 60)));
+ /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20),
+ new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 10, /* duration= */ 60)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 10),
+ /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
- /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 100),
+ /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 60),
new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1,
- /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50),
+ /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 300, /* duration= */ 50),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f,
- /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20),
+ /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20),
new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 60));
+ /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 10, /* duration= */ 60));
VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo));
@@ -165,13 +173,13 @@ public class StepToRampAdapterTest {
@Test
public void testStepSegments_withPwleCapabilityAndFrequency_convertsStepsToRamps() {
List<VibrationEffectSegment> segments = new ArrayList<>(Arrays.asList(
- new StepSegment(/* amplitude= */ 0, /* frequency= */ -1, /* duration= */ 10),
- new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 1, /* duration= */ 100)));
+ new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 100, /* duration= */ 10),
+ new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 6)));
List<VibrationEffectSegment> expectedSegments = Arrays.asList(
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0,
- /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10),
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10),
new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f,
- /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 100));
+ /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 6));
VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo));
@@ -183,6 +191,7 @@ public class StepToRampAdapterTest {
private static VibratorInfo createVibratorInfo(int... capabilities) {
return new VibratorInfo.Builder(0)
.setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0))
+ .setFrequencyMapping(TEST_FREQUENCY_MAPPING)
.build();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
index 59c0b0e96fcd..6369dbc6b171 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java
@@ -16,6 +16,14 @@
package com.android.server.vibrator;
+import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
+import static android.os.VibrationAttributes.USAGE_RINGTONE;
+import static android.os.VibrationAttributes.USAGE_TOUCH;
+import static android.os.Vibrator.VIBRATION_INTENSITY_HIGH;
+import static android.os.Vibrator.VIBRATION_INTENSITY_LOW;
+import static android.os.Vibrator.VIBRATION_INTENSITY_MEDIUM;
+import static android.os.Vibrator.VIBRATION_INTENSITY_OFF;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
@@ -24,7 +32,6 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
-import android.content.Context;
import android.content.ContextWrapper;
import android.os.Handler;
import android.os.IExternalVibratorService;
@@ -37,6 +44,7 @@ import android.os.test.TestLooper;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
import android.os.vibrator.StepSegment;
+import android.os.vibrator.VibrationConfig;
import android.os.vibrator.VibrationEffectSegment;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
@@ -68,29 +76,31 @@ public class VibrationScalerTest {
@Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
@Mock private PowerManagerInternal mPowerManagerInternalMock;
+ @Mock private VibrationConfig mVibrationConfigMock;
private TestLooper mTestLooper;
private ContextWrapper mContextSpy;
- private FakeVibrator mFakeVibrator;
private VibrationSettings mVibrationSettings;
private VibrationScaler mVibrationScaler;
@Before
public void setUp() throws Exception {
mTestLooper = new TestLooper();
- mFakeVibrator = new FakeVibrator();
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
- when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mFakeVibrator);
LocalServices.removeServiceForTest(PowerManagerInternal.class);
LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
+ Settings.System.putInt(contentResolver, Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
+ Settings.System.putInt(contentResolver, Settings.System.VIBRATE_WHEN_RINGING, 1);
+
mVibrationSettings = new VibrationSettings(
- mContextSpy, new Handler(mTestLooper.getLooper()));
+ mContextSpy, new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
mVibrationScaler = new VibrationScaler(mContextSpy, mVibrationSettings);
+
mVibrationSettings.onSystemReady();
}
@@ -101,91 +111,80 @@ public class VibrationScalerTest {
@Test
public void testGetExternalVibrationScale() {
- mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_HIGH);
+ setDefaultIntensity(USAGE_TOUCH, Vibrator.VIBRATION_INTENSITY_LOW);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH);
assertEquals(IExternalVibratorService.SCALE_VERY_HIGH,
- mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
+ mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_MEDIUM);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_MEDIUM);
assertEquals(IExternalVibratorService.SCALE_HIGH,
- mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
+ mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_LOW);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW);
assertEquals(IExternalVibratorService.SCALE_NONE,
- mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
+ mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
- mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+ setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_MEDIUM);
assertEquals(IExternalVibratorService.SCALE_LOW,
- mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
+ mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
- mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
+ setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_HIGH);
assertEquals(IExternalVibratorService.SCALE_VERY_LOW,
- mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
+ mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
// Unexpected vibration intensity will be treated as SCALE_NONE.
assertEquals(IExternalVibratorService.SCALE_NONE,
- mVibrationScaler.getExternalVibrationScale(VibrationAttributes.USAGE_TOUCH));
+ mVibrationScaler.getExternalVibrationScale(USAGE_TOUCH));
}
@Test
public void scale_withPrebakedSegment_setsEffectStrengthBasedOnSettings() {
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_HIGH);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
PrebakedSegment effect = new PrebakedSegment(VibrationEffect.EFFECT_CLICK,
/* shouldFallback= */ false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
- PrebakedSegment scaled = mVibrationScaler.scale(
- effect, VibrationAttributes.USAGE_NOTIFICATION);
+ PrebakedSegment scaled = mVibrationScaler.scale(effect, USAGE_NOTIFICATION);
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_MEDIUM);
- scaled = mVibrationScaler.scale(effect, VibrationAttributes.USAGE_NOTIFICATION);
+ VIBRATION_INTENSITY_MEDIUM);
+ scaled = mVibrationScaler.scale(effect, USAGE_NOTIFICATION);
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_LOW);
- scaled = mVibrationScaler.scale(effect, VibrationAttributes.USAGE_NOTIFICATION);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
+ scaled = mVibrationScaler.scale(effect, USAGE_NOTIFICATION);
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
- scaled = mVibrationScaler.scale(effect, VibrationAttributes.USAGE_NOTIFICATION);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ scaled = mVibrationScaler.scale(effect, USAGE_NOTIFICATION);
// Unexpected intensity setting will be mapped to STRONG.
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
}
@Test
public void scale_withPrebakedEffect_setsEffectStrengthBasedOnSettings() {
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_HIGH);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
VibrationEffect effect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK);
PrebakedSegment scaled = getFirstSegment(mVibrationScaler.scale(
- effect, VibrationAttributes.USAGE_NOTIFICATION));
+ effect, USAGE_NOTIFICATION));
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_MEDIUM);
+ VIBRATION_INTENSITY_MEDIUM);
scaled = getFirstSegment(mVibrationScaler.scale(
- effect, VibrationAttributes.USAGE_NOTIFICATION));
+ effect, USAGE_NOTIFICATION));
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_MEDIUM);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_LOW);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
scaled = getFirstSegment(mVibrationScaler.scale(
- effect, VibrationAttributes.USAGE_NOTIFICATION));
+ effect, USAGE_NOTIFICATION));
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_LIGHT);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
scaled = getFirstSegment(mVibrationScaler.scale(
- effect, VibrationAttributes.USAGE_NOTIFICATION));
+ effect, USAGE_NOTIFICATION));
// Unexpected intensity setting will be mapped to STRONG.
assertEquals(scaled.getEffectStrength(), VibrationEffect.EFFECT_STRENGTH_STRONG);
}
@@ -193,81 +192,77 @@ public class VibrationScalerTest {
@Test
public void scale_withOneShotAndWaveform_resolvesAmplitude() {
// No scale, default amplitude still resolved
- mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_LOW);
+ setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_LOW);
+ setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
StepSegment resolved = getFirstSegment(mVibrationScaler.scale(
VibrationEffect.createOneShot(10, VibrationEffect.DEFAULT_AMPLITUDE),
- VibrationAttributes.USAGE_RINGTONE));
+ USAGE_RINGTONE));
assertTrue(resolved.getAmplitude() > 0);
resolved = getFirstSegment(mVibrationScaler.scale(
VibrationEffect.createWaveform(new long[]{10},
new int[]{VibrationEffect.DEFAULT_AMPLITUDE}, -1),
- VibrationAttributes.USAGE_RINGTONE));
+ USAGE_RINGTONE));
assertTrue(resolved.getAmplitude() > 0);
}
@Test
public void scale_withOneShotAndWaveform_scalesAmplitude() {
- mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_HIGH);
- mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_LOW);
- mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_MEDIUM);
+ setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_LOW);
+ setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
+ setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_HIGH);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
+ setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_MEDIUM);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_MEDIUM);
StepSegment scaled = getFirstSegment(mVibrationScaler.scale(
- VibrationEffect.createOneShot(128, 128), VibrationAttributes.USAGE_RINGTONE));
+ VibrationEffect.createOneShot(128, 128), USAGE_RINGTONE));
// Ringtone scales up.
assertTrue(scaled.getAmplitude() > 0.5);
scaled = getFirstSegment(mVibrationScaler.scale(
VibrationEffect.createWaveform(new long[]{128}, new int[]{128}, -1),
- VibrationAttributes.USAGE_NOTIFICATION));
+ USAGE_NOTIFICATION));
// Notification scales down.
assertTrue(scaled.getAmplitude() < 0.5);
scaled = getFirstSegment(mVibrationScaler.scale(VibrationEffect.createOneShot(128, 128),
- VibrationAttributes.USAGE_TOUCH));
+ USAGE_TOUCH));
// Haptic feedback does not scale.
assertEquals(128f / 255, scaled.getAmplitude(), 1e-5);
}
@Test
public void scale_withComposed_scalesPrimitives() {
- mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_HIGH);
- mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_LOW);
- mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_MEDIUM);
+ setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_LOW);
+ setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
+ setDefaultIntensity(USAGE_NOTIFICATION, VIBRATION_INTENSITY_HIGH);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
+ setDefaultIntensity(USAGE_TOUCH, VIBRATION_INTENSITY_MEDIUM);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_MEDIUM);
VibrationEffect composed = VibrationEffect.startComposition()
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f).compose();
- PrimitiveSegment scaled = getFirstSegment(mVibrationScaler.scale(composed,
- VibrationAttributes.USAGE_RINGTONE));
+ PrimitiveSegment scaled = getFirstSegment(mVibrationScaler.scale(composed, USAGE_RINGTONE));
// Ringtone scales up.
assertTrue(scaled.getScale() > 0.5f);
- scaled = getFirstSegment(mVibrationScaler.scale(composed,
- VibrationAttributes.USAGE_NOTIFICATION));
+ scaled = getFirstSegment(mVibrationScaler.scale(composed, USAGE_NOTIFICATION));
// Notification scales down.
assertTrue(scaled.getScale() < 0.5f);
- scaled = getFirstSegment(mVibrationScaler.scale(composed, VibrationAttributes.USAGE_TOUCH));
+ scaled = getFirstSegment(mVibrationScaler.scale(composed, USAGE_TOUCH));
// Haptic feedback does not scale.
assertEquals(0.5, scaled.getScale(), 1e-5);
}
+ private void setDefaultIntensity(@VibrationAttributes.Usage int usage,
+ @Vibrator.VibrationIntensity int intensity) {
+ when(mVibrationConfigMock.getDefaultVibrationIntensity(eq(usage))).thenReturn(intensity);
+ }
+
private <T extends VibrationEffectSegment> T getFirstSegment(VibrationEffect.Composed effect) {
return (T) effect.getSegments().get(0);
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index ab9fbb581416..ff59d0f22c3c 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -16,9 +16,11 @@
package com.android.server.vibrator;
+import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY;
import static android.os.VibrationAttributes.USAGE_ALARM;
import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
+import static android.os.VibrationAttributes.USAGE_MEDIA;
import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION;
import static android.os.VibrationAttributes.USAGE_RINGTONE;
@@ -35,6 +37,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.spy;
@@ -45,7 +48,6 @@ import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.content.ContentResolver;
-import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.media.AudioManager;
@@ -55,7 +57,9 @@ import android.os.PowerSaveState;
import android.os.UserHandle;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.os.test.TestLooper;
+import android.os.vibrator.VibrationConfig;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
@@ -87,6 +91,19 @@ public class VibrationSettingsTest {
private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder()
.setBatterySaverEnabled(true).build();
+ private static final int[] ALL_USAGES = new int[] {
+ USAGE_UNKNOWN,
+ USAGE_ACCESSIBILITY,
+ USAGE_ALARM,
+ USAGE_COMMUNICATION_REQUEST,
+ USAGE_HARDWARE_FEEDBACK,
+ USAGE_MEDIA,
+ USAGE_NOTIFICATION,
+ USAGE_PHYSICAL_EMULATION,
+ USAGE_RINGTONE,
+ USAGE_TOUCH,
+ };
+
@Rule
public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Rule
@@ -96,23 +113,23 @@ public class VibrationSettingsTest {
private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
@Mock
private PowerManagerInternal mPowerManagerInternalMock;
+ @Mock
+ private VibrationConfig mVibrationConfigMock;
private TestLooper mTestLooper;
private ContextWrapper mContextSpy;
private AudioManager mAudioManager;
- private FakeVibrator mFakeVibrator;
private VibrationSettings mVibrationSettings;
private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener;
@Before
public void setUp() throws Exception {
mTestLooper = new TestLooper();
- mFakeVibrator = new FakeVibrator();
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
- when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mFakeVibrator);
+
doAnswer(invocation -> {
mRegisteredPowerModeListener = invocation.getArgument(0);
return null;
@@ -121,16 +138,18 @@ public class VibrationSettingsTest {
LocalServices.removeServiceForTest(PowerManagerInternal.class);
LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock);
+ setDefaultIntensity(VIBRATION_INTENSITY_MEDIUM);
mAudioManager = mContextSpy.getSystemService(AudioManager.class);
mVibrationSettings = new VibrationSettings(mContextSpy,
- new Handler(mTestLooper.getLooper()));
- mVibrationSettings.onSystemReady();
+ new Handler(mTestLooper.getLooper()), mVibrationConfigMock);
// Simulate System defaults.
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0);
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+ mVibrationSettings.onSystemReady();
}
@After
@@ -145,12 +164,15 @@ public class VibrationSettingsTest {
setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1);
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
+ setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 0);
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
- verify(mListenerMock, times(7)).onChange();
+ verify(mListenerMock, times(10)).onChange();
}
@Test
@@ -192,9 +214,7 @@ public class VibrationSettingsTest {
UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
for (int usage : expectedAllowedVibrations) {
- assertNull("Error for usage " + VibrationAttributes.usageToString(usage),
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(usage)));
+ assertVibrationNotIgnoredForUsage(usage);
}
}
@@ -209,10 +229,7 @@ public class VibrationSettingsTest {
UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
for (int usage : expectedIgnoredVibrations) {
- assertEquals("Error for usage " + VibrationAttributes.usageToString(usage),
- Vibration.Status.IGNORED_BACKGROUND,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(usage)));
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_BACKGROUND);
}
}
@@ -221,10 +238,9 @@ public class VibrationSettingsTest {
mVibrationSettings.mUidObserver.onUidStateChanged(
UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0, 0);
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_ALARM)));
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
}
@Test
@@ -238,9 +254,7 @@ public class VibrationSettingsTest {
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
for (int usage : expectedAllowedVibrations) {
- assertNull("Error for usage " + VibrationAttributes.usageToString(usage),
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(usage)));
+ assertVibrationNotIgnoredForUsage(usage);
}
}
@@ -257,10 +271,7 @@ public class VibrationSettingsTest {
mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
for (int usage : expectedIgnoredVibrations) {
- assertEquals("Error for usage " + VibrationAttributes.usageToString(usage),
- Vibration.Status.IGNORED_FOR_POWER,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(usage)));
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_POWER);
}
}
@@ -268,130 +279,130 @@ public class VibrationSettingsTest {
public void shouldIgnoreVibration_notInBatterySaverMode_allowsAnyUsage() {
mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_COMMUNICATION_REQUEST)));
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
}
@Test
public void shouldIgnoreVibration_withRingerModeSilent_ignoresRingtoneAndTouch() {
// Vibrating settings on are overruled by ringer mode.
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
- setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
+ setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1);
setRingerMode(AudioManager.RINGER_MODE_SILENT);
- assertEquals(Vibration.Status.IGNORED_FOR_RINGER_MODE,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_RINGTONE)));
- assertEquals(Vibration.Status.IGNORED_FOR_RINGER_MODE,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_COMMUNICATION_REQUEST)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_HARDWARE_FEEDBACK)));
+ for (int usage : ALL_USAGES) {
+ if (usage == USAGE_RINGTONE || usage == USAGE_TOUCH) {
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_RINGER_MODE);
+ } else {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
}
@Test
public void shouldIgnoreVibration_withRingerModeVibrate_allowsAllVibrations() {
- // Vibrating settings off are overruled by ringer mode.
- setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
- setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_PHYSICAL_EMULATION)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_RINGTONE)));
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
+
+ @Test
+ public void shouldIgnoreVibration_withRingerModeNormal_allowsAllVibrations() {
+ setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
}
@Test
- public void shouldIgnoreVibration_withRingerModeNormalAndRingSettingsOff_ignoresRingtoneOnly() {
- // Vibrating settings off are respected for normal ringer mode.
+ public void shouldIgnoreVibration_withRingSettingsOff_disableRingtoneVibrations() {
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
- setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- assertEquals(Vibration.Status.IGNORED_FOR_RINGER_MODE,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_RINGTONE)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_NOTIFICATION)));
+ for (int usage : ALL_USAGES) {
+ if (usage == USAGE_RINGTONE) {
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ } else {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
}
@Test
- public void shouldIgnoreVibration_withRingerModeNormalAndRingSettingsOn_allowsAllVibrations() {
+ public void shouldIgnoreVibration_withRingSettingsOn_allowsAllVibrations() {
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
- setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_RINGTONE)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_ALARM)));
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
}
@Test
- public void shouldIgnoreVibration_withRingerModeNormalAndRampingRingerOn_allowsAllVibrations() {
+ public void shouldIgnoreVibration_withRampingRingerOn_allowsAllVibrations() {
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1);
- setRingerMode(AudioManager.RINGER_MODE_NORMAL);
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_RINGTONE)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_COMMUNICATION_REQUEST)));
+ for (int usage : ALL_USAGES) {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
+
+ @Test
+ public void shouldIgnoreVibration_withHapticFeedbackDisabled_ignoresTouchVibration() {
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 0);
+
+ for (int usage : ALL_USAGES) {
+ if (usage == USAGE_TOUCH) {
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ } else {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
}
@Test
public void shouldIgnoreVibration_withHapticFeedbackSettingsOff_ignoresTouchVibration() {
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
- assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_RINGTONE)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_HARDWARE_FEEDBACK)));
+ for (int usage : ALL_USAGES) {
+ if (usage == USAGE_TOUCH) {
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ } else {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
}
@Test
public void shouldIgnoreVibration_withHardwareFeedbackSettingsOff_ignoresHardwareVibrations() {
setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
- assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_HARDWARE_FEEDBACK)));
- assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_PHYSICAL_EMULATION)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_NOTIFICATION)));
+ for (int usage : ALL_USAGES) {
+ if (usage == USAGE_HARDWARE_FEEDBACK || usage == USAGE_PHYSICAL_EMULATION) {
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ } else {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
}
@Test
public void shouldIgnoreVibration_withNotificationSettingsOff_ignoresNotificationVibrations() {
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
- assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_NOTIFICATION)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_ALARM)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_RINGTONE)));
+ for (int usage : ALL_USAGES) {
+ if (usage == USAGE_NOTIFICATION) {
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ } else {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
}
@Test
@@ -402,15 +413,13 @@ public class VibrationSettingsTest {
setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
- assertEquals(Vibration.Status.IGNORED_FOR_SETTINGS,
- mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_RINGTONE)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_NOTIFICATION)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_ALARM)));
- assertNull(mVibrationSettings.shouldIgnoreVibration(UID,
- VibrationAttributes.createForUsage(USAGE_TOUCH)));
+ for (int usage : ALL_USAGES) {
+ if (usage == USAGE_RINGTONE) {
+ assertVibrationIgnoredForUsage(usage, Vibration.Status.IGNORED_FOR_SETTINGS);
+ } else {
+ assertVibrationNotIgnoredForUsage(usage);
+ }
+ }
}
@Test
@@ -423,90 +432,40 @@ public class VibrationSettingsTest {
}
@Test
- public void getDefaultIntensity_beforeSystemReady_returnsMediumToAllExceptAlarm() {
- mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_HIGH);
- mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_HIGH);
- mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_HIGH);
-
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ public void getDefaultIntensity_returnsIntensityFromVibratorConfig() {
+ setDefaultIntensity(VIBRATION_INTENSITY_HIGH);
+ setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
-
- VibrationSettings vibrationSettings = new VibrationSettings(mContextSpy,
- new Handler(mTestLooper.getLooper()));
-
- assertEquals(VIBRATION_INTENSITY_HIGH,
- vibrationSettings.getDefaultIntensity(USAGE_ALARM));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(USAGE_TOUCH));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(USAGE_PHYSICAL_EMULATION));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(USAGE_NOTIFICATION));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(USAGE_UNKNOWN));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- vibrationSettings.getDefaultIntensity(USAGE_RINGTONE));
- }
-
- @Test
- public void getDefaultIntensity_returnsIntensityFromVibratorService() {
- mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_HIGH);
- mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_MEDIUM);
- mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_LOW);
-
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
- assertEquals(VIBRATION_INTENSITY_HIGH,
- mVibrationSettings.getDefaultIntensity(USAGE_ALARM));
- assertEquals(VIBRATION_INTENSITY_HIGH,
- mVibrationSettings.getDefaultIntensity(USAGE_TOUCH));
- assertEquals(VIBRATION_INTENSITY_HIGH,
- mVibrationSettings.getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
- assertEquals(VIBRATION_INTENSITY_HIGH,
- mVibrationSettings.getDefaultIntensity(USAGE_PHYSICAL_EMULATION));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getDefaultIntensity(USAGE_NOTIFICATION));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getDefaultIntensity(USAGE_UNKNOWN));
- assertEquals(VIBRATION_INTENSITY_LOW,
- mVibrationSettings.getDefaultIntensity(USAGE_RINGTONE));
+ for (int usage : ALL_USAGES) {
+ assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getDefaultIntensity(usage));
+ }
}
@Test
public void getCurrentIntensity_returnsIntensityFromSettings() {
- mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_OFF);
- mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_OFF);
- mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_OFF);
-
- setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH);
+ setDefaultIntensity(VIBRATION_INTENSITY_OFF);
+ setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW);
setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW);
- setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- VIBRATION_INTENSITY_MEDIUM);
+ setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
+ setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
- assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getCurrentIntensity(USAGE_ALARM));
- assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
- assertEquals(VIBRATION_INTENSITY_LOW,
- mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
- assertEquals(VIBRATION_INTENSITY_LOW,
- mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getCurrentIntensity(USAGE_NOTIFICATION));
- assertEquals(VIBRATION_INTENSITY_MEDIUM,
- mVibrationSettings.getCurrentIntensity(USAGE_UNKNOWN));
- assertEquals(VIBRATION_INTENSITY_LOW,
- mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
+ for (int usage : ALL_USAGES) {
+ assertEquals(errorMessageForUsage(usage),
+ VIBRATION_INTENSITY_LOW,
+ mVibrationSettings.getCurrentIntensity(usage));
+ }
}
@Test
public void getCurrentIntensity_updateTriggeredAfterUserSwitched() {
- mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_OFF);
+ setDefaultIntensity(USAGE_RINGTONE, VIBRATION_INTENSITY_OFF);
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
assertEquals(VIBRATION_INTENSITY_HIGH,
mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
@@ -524,8 +483,9 @@ public class VibrationSettingsTest {
@Test
public void getCurrentIntensity_noHardwareFeedbackValueUsesHapticFeedbackValue() {
- mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_MEDIUM);
+ setDefaultIntensity(USAGE_HARDWARE_FEEDBACK, VIBRATION_INTENSITY_MEDIUM);
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
+ mVibrationSettings.updateSettings();
assertEquals(VIBRATION_INTENSITY_OFF, mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
// If haptic feedback is off, fallback to default value.
assertEquals(VIBRATION_INTENSITY_MEDIUM,
@@ -533,15 +493,11 @@ public class VibrationSettingsTest {
assertEquals(VIBRATION_INTENSITY_MEDIUM,
mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
- // Switching user is not working with FakeSettingsProvider.
- // Testing the broadcast flow manually.
- Settings.System.putIntForUser(mContextSpy.getContentResolver(),
- Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH,
- UserHandle.USER_CURRENT);
- mVibrationSettings.mUserReceiver.onReceive(mContextSpy,
- new Intent(Intent.ACTION_USER_SWITCHED));
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH);
+ mVibrationSettings.updateSettings();
assertEquals(VIBRATION_INTENSITY_HIGH,
mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
+ // If haptic feedback is on, fallback to that value.
assertEquals(VIBRATION_INTENSITY_HIGH,
mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
assertEquals(VIBRATION_INTENSITY_HIGH,
@@ -557,6 +513,33 @@ public class VibrationSettingsTest {
assertNotNull(mVibrationSettings.getFallbackEffect(VibrationEffect.EFFECT_DOUBLE_CLICK));
}
+ private void assertVibrationIgnoredForUsage(@VibrationAttributes.Usage int usage,
+ Vibration.Status expectedStatus) {
+ assertEquals(errorMessageForUsage(usage),
+ expectedStatus,
+ mVibrationSettings.shouldIgnoreVibration(UID,
+ VibrationAttributes.createForUsage(usage)));
+ }
+
+ private void assertVibrationNotIgnoredForUsage(@VibrationAttributes.Usage int usage) {
+ assertNull(errorMessageForUsage(usage),
+ mVibrationSettings.shouldIgnoreVibration(UID,
+ VibrationAttributes.createForUsage(usage)));
+ }
+
+ private String errorMessageForUsage(int usage) {
+ return "Error for usage " + VibrationAttributes.usageToString(usage);
+ }
+
+ private void setDefaultIntensity(@Vibrator.VibrationIntensity int intensity) {
+ when(mVibrationConfigMock.getDefaultVibrationIntensity(anyInt())).thenReturn(intensity);
+ }
+
+ private void setDefaultIntensity(@VibrationAttributes.Usage int usage,
+ @Vibrator.VibrationIntensity int intensity) {
+ when(mVibrationConfigMock.getDefaultVibrationIntensity(eq(usage))).thenReturn(intensity);
+ }
+
private void setUserSetting(String settingName, int value) {
Settings.System.putIntForUser(
mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT);
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
index 4cc4d55f228d..5dd44ffc664f 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -44,11 +44,13 @@ import android.os.Process;
import android.os.SystemClock;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.os.test.TestLooper;
import android.os.vibrator.PrebakedSegment;
import android.os.vibrator.PrimitiveSegment;
import android.os.vibrator.RampSegment;
import android.os.vibrator.StepSegment;
+import android.os.vibrator.VibrationConfig;
import android.os.vibrator.VibrationEffectSegment;
import android.platform.test.annotations.LargeTest;
import android.platform.test.annotations.Presubmit;
@@ -101,6 +103,8 @@ public class VibrationThreadTest {
private IBinder mVibrationToken;
@Mock
private IBatteryStats mIBatteryStatsMock;
+ @Mock
+ private VibrationConfig mVibrationConfigMock;
private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
private VibrationSettings mVibrationSettings;
@@ -113,9 +117,13 @@ public class VibrationThreadTest {
public void setUp() throws Exception {
mTestLooper = new TestLooper();
+ when(mVibrationConfigMock.getDefaultVibrationIntensity(anyInt()))
+ .thenReturn(Vibrator.VIBRATION_INTENSITY_MEDIUM);
+ when(mVibrationConfigMock.getRampStepDurationMs()).thenReturn(TEST_RAMP_STEP_DURATION);
+
Context context = InstrumentationRegistry.getContext();
mVibrationSettings = new VibrationSettings(context, new Handler(mTestLooper.getLooper()),
- /* rampDownDuration= */ 0, TEST_RAMP_STEP_DURATION);
+ mVibrationConfigMock);
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mWakeLock = context.getSystemService(
PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
@@ -553,8 +561,8 @@ public class VibrationThreadTest {
VibrationEffect effect = VibrationEffect.startWaveform()
.addStep(1, 10)
.addRamp(0, 20)
- .addStep(0.8f, 1, 30)
- .addRamp(0.6f, -1, 40)
+ .addStep(0.8f, 100, 30)
+ .addRamp(0.6f, 200, 40)
.build();
VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
waitForCompletion(thread);
@@ -565,12 +573,13 @@ public class VibrationThreadTest {
verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED);
assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating());
assertEquals(Arrays.asList(
- expectedRamp(/* amplitude= */ 1, /* frequency= */ 150, /* duration= */ 10),
- expectedRamp(/* StartAmplitude= */ 1, /* endAmplitude= */ 0,
- /* startFrequency= */ 150, /* endFrequency= */ 150, /* duration= */ 20),
- expectedRamp(/* amplitude= */ 0.6f, /* frequency= */ 200, /* duration= */ 30),
- expectedRamp(/* StartAmplitude= */ 0.6f, /* endAmplitude= */ 0.5f,
- /* startFrequency= */ 200, /* endFrequency= */ 100, /* duration= */ 40)),
+ expectedRamp(/* amplitude= */ 1, /* frequencyHz= */ 150, /* duration= */ 10),
+ expectedRamp(/* startAmplitude= */ 1, /* endAmplitude= */ 0,
+ /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 20),
+ expectedRamp(/* amplitude= */ 0.5f, /* frequencyHz= */ 100, /* duration= */ 30),
+ expectedRamp(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.6f,
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 200,
+ /* duration= */ 40)),
fakeVibrator.getEffectSegments());
assertEquals(Arrays.asList(Braking.CLAB), fakeVibrator.getBraking());
}
@@ -589,8 +598,8 @@ public class VibrationThreadTest {
VibrationEffect effect = VibrationEffect.startWaveform()
.addStep(1, 10)
.addRamp(0, 20)
- .addStep(0.8f, 1, 30)
- .addRamp(0.6f, -1, 40)
+ .addStep(0.8f, 10, 30)
+ .addRamp(0.6f, 100, 40)
.build();
VibrationThread thread = startThreadAndDispatcher(vibrationId, effect);
waitForCompletion(thread);
@@ -1110,9 +1119,7 @@ public class VibrationThreadTest {
@Test
public void vibrate_waveformWithRampDown_addsRampDownAfterVibrationCompleted() {
- int rampDownDuration = 15;
- mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
- new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
@@ -1138,9 +1145,7 @@ public class VibrationThreadTest {
@Test
public void vibrate_waveformWithRampDown_triggersCallbackWhenOriginalVibrationEnds() {
- int rampDownDuration = 10_000;
- mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
- new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(10_000);
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
@@ -1173,9 +1178,7 @@ public class VibrationThreadTest {
@Test
public void vibrate_waveformCancelledWithRampDown_addsRampDownAfterVibrationCancelled()
throws Exception {
- int rampDownDuration = 15;
- mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
- new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
@@ -1201,9 +1204,7 @@ public class VibrationThreadTest {
@Test
public void vibrate_predefinedWithRampDown_doesNotAddRampDown() {
- int rampDownDuration = 15;
- mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
- new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
mVibratorProviders.get(VIBRATOR_ID).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
@@ -1223,9 +1224,7 @@ public class VibrationThreadTest {
@Test
public void vibrate_composedWithRampDown_doesNotAddRampDown() {
- int rampDownDuration = 15;
- mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
- new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
mVibratorProviders.get(VIBRATOR_ID).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
IVibrator.CAP_COMPOSE_EFFECTS);
@@ -1250,9 +1249,7 @@ public class VibrationThreadTest {
@Test
public void vibrate_pwleWithRampDown_doesNotAddRampDown() {
- int rampDownDuration = 15;
- mVibrationSettings = new VibrationSettings(InstrumentationRegistry.getContext(),
- new Handler(mTestLooper.getLooper()), rampDownDuration, TEST_RAMP_STEP_DURATION);
+ when(mVibrationConfigMock.getRampDownDurationMs()).thenReturn(15);
mEffectAdapter = new DeviceVibrationEffectAdapter(mVibrationSettings);
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(VIBRATOR_ID);
fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
@@ -1345,7 +1342,8 @@ public class VibrationThreadTest {
}
private VibrationEffectSegment expectedOneShot(long millis) {
- return new StepSegment(VibrationEffect.DEFAULT_AMPLITUDE, /* frequency= */ 0, (int) millis);
+ return new StepSegment(VibrationEffect.DEFAULT_AMPLITUDE,
+ /* frequencyHz= */ 0, (int) millis);
}
private VibrationEffectSegment expectedPrebaked(int effectId) {
@@ -1356,13 +1354,13 @@ public class VibrationThreadTest {
return new PrimitiveSegment(primitiveId, scale, delay);
}
- private VibrationEffectSegment expectedRamp(float amplitude, float frequency, int duration) {
- return expectedRamp(amplitude, amplitude, frequency, frequency, duration);
+ private VibrationEffectSegment expectedRamp(float amplitude, float frequencyHz, int duration) {
+ return expectedRamp(amplitude, amplitude, frequencyHz, frequencyHz, duration);
}
private VibrationEffectSegment expectedRamp(float startAmplitude, float endAmplitude,
- float startFrequency, float endFrequency, int duration) {
- return new RampSegment(startAmplitude, endAmplitude, startFrequency, endFrequency,
+ float startFrequencyHz, float endFrequencyHz, int duration) {
+ return new RampSegment(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz,
duration);
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java
index 9fb8b38a706e..cb4982be40c3 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java
@@ -21,7 +21,6 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
@@ -236,7 +235,7 @@ public class VibratorControllerTest {
RampSegment[] primitives = new RampSegment[]{
new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1,
- /* startFrequency= */ -1, /* endFrequency= */ 1, /* duration= */ 10)
+ /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 200, /* duration= */ 10)
};
assertEquals(15L, controller.on(primitives, 12));
assertTrue(controller.isVibrating());
@@ -312,10 +311,10 @@ public class VibratorControllerTest {
private void mockVibratorCapabilities(int capabilities) {
VibratorInfo.FrequencyMapping frequencyMapping = new VibratorInfo.FrequencyMapping(
- Float.NaN, Float.NaN, Float.NaN, Float.NaN, null);
- when(mNativeWrapperMock.getInfo(anyFloat(), any(VibratorInfo.Builder.class)))
+ Float.NaN, Float.NaN, Float.NaN, null);
+ when(mNativeWrapperMock.getInfo(any(VibratorInfo.Builder.class)))
.then(invocation -> {
- ((VibratorInfo.Builder) invocation.getArgument(1))
+ ((VibratorInfo.Builder) invocation.getArgument(0))
.setCapabilities(capabilities)
.setFrequencyMapping(frequencyMapping);
return true;
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index c0f75966bcf2..b0bdaf084b1a 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -19,6 +19,7 @@ package com.android.server.vibrator;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -155,12 +156,13 @@ public class VibratorManagerServiceTest {
@Before
public void setUp() throws Exception {
mTestLooper = new TestLooper();
- mVibrator = new FakeVibrator();
mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
InputManager inputManager = InputManager.resetInstance(mIInputManagerMock);
ContentResolver contentResolver = mSettingsProviderRule.mockContentResolver(mContextSpy);
when(mContextSpy.getContentResolver()).thenReturn(contentResolver);
+
+ mVibrator = new FakeVibrator(mContextSpy);
when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibrator);
when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager);
when(mContextSpy.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManagerMock);
@@ -175,8 +177,13 @@ public class VibratorManagerServiceTest {
}).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any());
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
+ setUserSetting(Settings.System.HAPTIC_FEEDBACK_ENABLED, 1);
+ setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
+ Vibrator.VIBRATION_INTENSITY_MEDIUM);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
Vibrator.VIBRATION_INTENSITY_MEDIUM);
+ setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY,
+ Vibrator.VIBRATION_INTENSITY_MEDIUM);
setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
Vibrator.VIBRATION_INTENSITY_MEDIUM);
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
@@ -437,7 +444,7 @@ public class VibratorManagerServiceTest {
UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
PrebakedSegment expected = new PrebakedSegment(
- VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
+ VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
// Only vibrators 1 and 3 have always-on capabilities.
assertEquals(mVibratorProviders.get(1).getAlwaysOnEffect(1), expected);
@@ -461,10 +468,10 @@ public class VibratorManagerServiceTest {
UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS));
PrebakedSegment expectedClick = new PrebakedSegment(
- VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
+ VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
PrebakedSegment expectedTick = new PrebakedSegment(
- VibrationEffect.EFFECT_TICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
+ VibrationEffect.EFFECT_TICK, false, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
// Enables click on vibrator 1 and tick on vibrator 2 only.
assertEquals(mVibratorProviders.get(1).getAlwaysOnEffect(1), expectedClick);
@@ -539,7 +546,6 @@ public class VibratorManagerServiceTest {
public void vibrate_withRingtone_usesRingtoneSettings() throws Exception {
mockVibrators(1);
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
- mVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK,
VibrationEffect.EFFECT_HEAVY_CLICK, VibrationEffect.EFFECT_DOUBLE_CLICK);
@@ -932,55 +938,67 @@ public class VibratorManagerServiceTest {
@Test
public void vibrate_withIntensitySettings_appliesSettingsToScaleVibrations() throws Exception {
- mVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
+ int defaultNotificationIntensity =
+ mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_NOTIFICATION);
setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_HIGH);
+ defaultNotificationIntensity < Vibrator.VIBRATION_INTENSITY_HIGH
+ ? defaultNotificationIntensity + 1
+ : defaultNotificationIntensity);
+
+ int defaultTouchIntensity =
+ mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_TOUCH);
setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_LOW);
- setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
- Vibrator.VIBRATION_INTENSITY_OFF);
+ defaultTouchIntensity > Vibrator.VIBRATION_INTENSITY_LOW
+ ? defaultTouchIntensity - 1
+ : defaultTouchIntensity);
+
+ setUserSetting(Settings.System.ALARM_VIBRATION_INTENSITY,
+ mVibrator.getDefaultVibrationIntensity(VibrationAttributes.USAGE_ALARM));
+ setUserSetting(Settings.System.MEDIA_VIBRATION_INTENSITY,
+ Vibrator.VIBRATION_INTENSITY_HIGH);
+ setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_OFF);
mockVibrators(1);
FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
fakeVibrator.setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL,
IVibrator.CAP_COMPOSE_EFFECTS);
- fakeVibrator.setSupportedEffects(VibrationEffect.EFFECT_CLICK);
VibratorManagerService service = createSystemReadyService();
vibrate(service, CombinedVibration.startSequential()
- .addNext(1, VibrationEffect.createOneShot(20, 100))
+ .addNext(1, VibrationEffect.createOneShot(100, 125))
.combine(), NOTIFICATION_ATTRS);
assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1,
service, TEST_TIMEOUT_MILLIS));
vibrate(service, VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
.addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 0.5f)
.compose(), HAPTIC_FEEDBACK_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 3,
+ assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 2,
service, TEST_TIMEOUT_MILLIS));
- vibrate(service, CombinedVibration.startParallel()
- .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
- .combine(), ALARM_ATTRS);
- assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 4,
+ vibrate(service, VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
+ .compose(), ALARM_ATTRS);
+ assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 3,
service, TEST_TIMEOUT_MILLIS));
- vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS);
+ vibrate(service, VibrationEffect.createOneShot(100, 125), RINGTONE_ATTRS);
+ assertFalse(waitUntil(s -> fakeVibrator.getEffectSegments().size() > 3,
+ service, TEST_TIMEOUT_MILLIS));
- assertEquals(4, fakeVibrator.getEffectSegments().size());
+ assertEquals(3, fakeVibrator.getEffectSegments().size());
- // Notification vibrations will be scaled with SCALE_VERY_HIGH.
- assertTrue(0.6 < fakeVibrator.getAmplitudes().get(0));
+ // Notification vibrations will be scaled with SCALE_HIGH or none if default is high.
+ assertEquals(defaultNotificationIntensity < Vibrator.VIBRATION_INTENSITY_HIGH,
+ 0.6 < fakeVibrator.getAmplitudes().get(0));
- // Haptic feedback vibrations will be scaled with SCALE_LOW.
- assertTrue(0.5 < ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(1)).getScale());
- assertTrue(0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale());
+ // Haptic feedback vibrations will be scaled with SCALE_LOW or none if default is low.
+ assertEquals(defaultTouchIntensity > Vibrator.VIBRATION_INTENSITY_LOW,
+ 0.5 > ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(1)).getScale());
- // Alarm vibration is always VIBRATION_INTENSITY_HIGH.
- PrebakedSegment expected = new PrebakedSegment(
- VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_STRONG);
- assertEquals(expected, fakeVibrator.getEffectSegments().get(3));
+ // Alarm vibration will be scaled with SCALE_NONE.
+ assertEquals(1f,
+ ((PrimitiveSegment) fakeVibrator.getEffectSegments().get(2)).getScale(), 1e-5);
// Ring vibrations have intensity OFF and are not played.
}
@@ -1100,7 +1118,7 @@ public class VibratorManagerServiceTest {
int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
mExternalVibratorService.onExternalVibrationStop(externalVibration);
- assertEquals(IExternalVibratorService.SCALE_NONE, scale);
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
assertEquals(Arrays.asList(false, true, false),
mVibratorProviders.get(1).getExternalControlStates());
}
@@ -1127,8 +1145,8 @@ public class VibratorManagerServiceTest {
ringtoneAudioAttrs, secondController);
int secondScale = mExternalVibratorService.onExternalVibrationStart(secondVibration);
- assertEquals(IExternalVibratorService.SCALE_NONE, firstScale);
- assertEquals(IExternalVibratorService.SCALE_NONE, secondScale);
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, firstScale);
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, secondScale);
verify(firstController).mute();
verify(secondController, never()).mute();
// Set external control called only once.
@@ -1151,7 +1169,7 @@ public class VibratorManagerServiceTest {
ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ATTRS,
mock(IExternalVibrationController.class));
int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
- assertEquals(IExternalVibratorService.SCALE_NONE, scale);
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
// Vibration is cancelled.
assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
@@ -1163,7 +1181,6 @@ public class VibratorManagerServiceTest {
public void onExternalVibration_withRingtone_usesRingerModeSettings() {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
- mVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
AudioAttributes audioAttrs = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.build();
@@ -1181,13 +1198,13 @@ public class VibratorManagerServiceTest {
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1);
createSystemReadyService();
scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
- assertEquals(IExternalVibratorService.SCALE_NONE, scale);
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
createSystemReadyService();
scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
- assertEquals(IExternalVibratorService.SCALE_NONE, scale);
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
}
private VibrationEffectSegment expectedPrebaked(int effectId) {
@@ -1235,10 +1252,6 @@ public class VibratorManagerServiceTest {
mContextSpy.getContentResolver(), settingName, value, UserHandle.USER_CURRENT);
}
- private void setGlobalSetting(String settingName, int value) {
- Settings.Global.putInt(mContextSpy.getContentResolver(), settingName, value);
- }
-
private void vibrate(VibratorManagerService service, VibrationEffect effect,
VibrationAttributes attrs) {
vibrate(service, CombinedVibration.createParallel(effect), attrs);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
index 182848b4f628..bd7186e74354 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
@@ -108,7 +108,7 @@ public class NotificationHistoryDatabaseTest extends UiServiceTestCase {
@Test
public void testDeletionReceiver() {
- verify(mContext, times(1)).registerReceiver(any(), any());
+ verify(mContext, times(1)).registerReceiver(any(), any(), anyInt());
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 5fcb8029af31..d83190353a87 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -182,7 +182,6 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
-import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
@@ -205,6 +204,7 @@ import com.android.server.lights.LogicalLight;
import com.android.server.notification.NotificationManagerService.NotificationAssistants;
import com.android.server.notification.NotificationManagerService.NotificationListeners;
import com.android.server.pm.PackageManagerService;
+import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.utils.quota.MultiRateLimiter;
@@ -235,6 +235,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
@@ -243,6 +244,8 @@ import java.util.function.Consumer;
@RunWithLooper
public class NotificationManagerServiceTest extends UiServiceTestCase {
private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
+ private static final String PKG_NO_CHANNELS = "com.example.no.channels";
+ private static final int TEST_TASK_ID = 1;
private static final int UID_HEADLESS = 1000000;
private final int mUid = Binder.getCallingUid();
@@ -257,6 +260,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Mock
private PackageManagerInternal mPackageManagerInternal;
@Mock
+ private PermissionPolicyInternal mPermissionPolicyInternal;
+ @Mock
private WindowManagerInternal mWindowManagerInternal;
@Mock
private PermissionHelper mPermissionHelper;
@@ -385,6 +390,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
LocalServices.addService(ActivityManagerInternal.class, mAmi);
LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
+ LocalServices.removeServiceForTest(PermissionPolicyInternal.class);
+ LocalServices.addService(PermissionPolicyInternal.class, mPermissionPolicyInternal);
mContext.addMockSystemService(Context.ALARM_SERVICE, mAlarmManager);
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
@@ -415,8 +422,18 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
+ when(mPermissionPolicyInternal.canShowPermissionPromptForTask(
+ any(ActivityManager.RecentTaskInfo.class))).thenReturn(false);
mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
+ ActivityManager.AppTask task = mock(ActivityManager.AppTask.class);
+ List<ActivityManager.AppTask> taskList = new ArrayList<>();
+ ActivityManager.RecentTaskInfo taskInfo = new ActivityManager.RecentTaskInfo();
+ taskInfo.taskId = TEST_TASK_ID;
+ when(task.getTaskInfo()).thenReturn(taskInfo);
+ taskList.add(task);
+ when(mAtm.getAppTasks(anyString(), anyInt())).thenReturn(taskList);
+
// write to a test file; the system file isn't readable from tests
mFile = new File(mContext.getCacheDir(), "test.xml");
mFile.createNewFile();
@@ -941,6 +958,51 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testCreateNotificationChannels_FirstChannelWithFgndTaskStartsPermDialog()
+ throws Exception {
+ when(mPermissionPolicyInternal.canShowPermissionPromptForTask(any(
+ ActivityManager.RecentTaskInfo.class))).thenReturn(true);
+ final NotificationChannel channel =
+ new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
+ mBinderService.createNotificationChannels(PKG_NO_CHANNELS,
+ new ParceledListSlice(Arrays.asList(channel)));
+ verify(mWorkerHandler).post(eq(new NotificationManagerService
+ .ShowNotificationPermissionPromptRunnable(PKG_NO_CHANNELS,
+ UserHandle.getUserId(mUid), TEST_TASK_ID, mPermissionPolicyInternal)));
+ }
+
+ @Test
+ public void testCreateNotificationChannels_SecondChannelWithFgndTaskDoesntStartPermDialog()
+ throws Exception {
+ when(mPermissionPolicyInternal.canShowPermissionPromptForTask(any(
+ ActivityManager.RecentTaskInfo.class))).thenReturn(true);
+ assertTrue(mBinderService.getNumNotificationChannelsForPackage(PKG, mUid, true) > 0);
+
+ final NotificationChannel channel =
+ new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
+ mBinderService.createNotificationChannels(PKG,
+ new ParceledListSlice(Arrays.asList(channel)));
+ verify(mWorkerHandler, never()).post(any(
+ NotificationManagerService.ShowNotificationPermissionPromptRunnable.class));
+ }
+
+ @Test
+ public void testCreateNotificationChannels_FirstChannelWithBgndTaskDoesntStartPermDialog()
+ throws Exception {
+ reset(mPermissionPolicyInternal);
+ when(mPermissionPolicyInternal.canShowPermissionPromptForTask(any(
+ ActivityManager.RecentTaskInfo.class))).thenReturn(false);
+
+ final NotificationChannel channel =
+ new NotificationChannel("id", "name", IMPORTANCE_DEFAULT);
+ mBinderService.createNotificationChannels(PKG,
+ new ParceledListSlice(Arrays.asList(channel)));
+
+ verify(mWorkerHandler, never()).post(any(
+ NotificationManagerService.ShowNotificationPermissionPromptRunnable.class));
+ }
+
+ @Test
public void testCreateNotificationChannels_TwoChannels() throws Exception {
final NotificationChannel channel1 =
new NotificationChannel("id1", "name", IMPORTANCE_DEFAULT);
@@ -2892,7 +2954,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.thenReturn(singletonList(mock(AssociationInfo.class)));
NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
mService.setPreferencesHelper(mPreferencesHelper);
- when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
+ when(mPreferencesHelper.getNotificationChannelGroupWithChannels(
+ eq(PKG), anyInt(), eq(ncg.getId()), anyBoolean()))
.thenReturn(ncg);
reset(mListeners);
mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
@@ -2902,6 +2965,54 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testDeleteChannelGroupChecksForFgses() throws Exception {
+ when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
+ .thenReturn(singletonList(mock(AssociationInfo.class)));
+ CountDownLatch latch = new CountDownLatch(2);
+ mService.createNotificationChannelGroup(
+ PKG, mUid, new NotificationChannelGroup("group", "group"), true, false);
+ new Thread(() -> {
+ NotificationChannel notificationChannel = new NotificationChannel("id", "id",
+ NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.setGroup("group");
+ ParceledListSlice<NotificationChannel> pls =
+ new ParceledListSlice(ImmutableList.of(notificationChannel));
+ try {
+ mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ latch.countDown();
+ }).start();
+ new Thread(() -> {
+ try {
+ synchronized (this) {
+ wait(5000);
+ }
+ mService.createNotificationChannelGroup(PKG, mUid,
+ new NotificationChannelGroup("new", "new group"), true, false);
+ NotificationChannel notificationChannel =
+ new NotificationChannel("id", "id", NotificationManager.IMPORTANCE_HIGH);
+ notificationChannel.setGroup("new");
+ ParceledListSlice<NotificationChannel> pls =
+ new ParceledListSlice(ImmutableList.of(notificationChannel));
+ try {
+ mBinderService.createNotificationChannelsForPackage(PKG, mUid, pls);
+ mBinderService.deleteNotificationChannelGroup(PKG, "group");
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ latch.countDown();
+ }).start();
+
+ latch.await();
+ verify(mAmi).hasForegroundServiceNotification(anyString(), anyInt(), anyString());
+ }
+
+ @Test
public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
mService.setPreferencesHelper(mPreferencesHelper);
when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
@@ -7062,6 +7173,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testAreNotificationsEnabledForPackage_viaInternalService() throws Exception {
+ assertEquals(mInternalService.areNotificationsEnabledForPackage(
+ mContext.getPackageName(), mUid),
+ mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(), mUid));
+ verify(mPermissionHelper, never()).hasPermission(anyInt());
+ }
+
+ @Test
public void testAreBubblesAllowedForPackage_crossUser() throws Exception {
try {
mBinderService.getBubblePreferenceForPackage(mContext.getPackageName(),
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
index 0c8fe35484f7..1362628bde5e 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
@@ -536,6 +536,12 @@ public class NotificationPermissionMigrationTest extends UiServiceTestCase {
}
@Test
+ public void testAreNotificationsEnabledForPackage_viaInternalService() {
+ mInternalService.areNotificationsEnabledForPackage(mContext.getPackageName(), mUid);
+ verify(mPermissionHelper).hasPermission(mUid);
+ }
+
+ @Test
public void testGetPackageImportance() throws Exception {
when(mPermissionHelper.hasPermission(mUid)).thenReturn(true);
assertThat(mBinderService.getPackageImportance(mContext.getPackageName()))
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
index bd3ba0404c03..fa294dd61ea3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
@@ -224,7 +225,30 @@ public class PermissionHelperTest extends UiServiceTestCase {
verify(mPermManager).grantRuntimePermission(
"pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
- FLAG_PERMISSION_USER_SET, FLAG_PERMISSION_USER_SET, true, 10);
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_REVIEW_REQUIRED,
+ FLAG_PERMISSION_USER_SET, true, 10);
+ }
+
+ @Test
+ public void testSetNotificationPermission_grantReviewRequired() throws Exception {
+ mPermissionHelper.setNotificationPermission("pkg", 10, true, false, true);
+
+ verify(mPermManager).grantRuntimePermission(
+ "pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
+ verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
+ FLAG_PERMISSION_REVIEW_REQUIRED, FLAG_PERMISSION_REVIEW_REQUIRED, true, 10);
+ }
+
+ @Test
+ public void testSetNotificationPermission_pkgPerm_grantReviewRequired() throws Exception {
+ PermissionHelper.PackagePermission pkgPerm = new PermissionHelper.PackagePermission(
+ "pkg", 10, true, false);
+ mPermissionHelper.setNotificationPermission(pkgPerm);
+
+ verify(mPermManager).grantRuntimePermission(
+ "pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
+ verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
+ FLAG_PERMISSION_REVIEW_REQUIRED, FLAG_PERMISSION_REVIEW_REQUIRED, true, 10);
}
@Test
@@ -234,7 +258,8 @@ public class PermissionHelperTest extends UiServiceTestCase {
verify(mPermManager).revokeRuntimePermission(
eq("pkg"), eq(Manifest.permission.POST_NOTIFICATIONS), eq(10), anyString());
verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
- FLAG_PERMISSION_USER_SET, FLAG_PERMISSION_USER_SET, true, 10);
+ FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_REVIEW_REQUIRED,
+ FLAG_PERMISSION_USER_SET, true, 10);
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index d49cf670f471..76bd4ebfb228 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -3174,6 +3174,19 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
@Test
+ public void testIsGroupBlocked_appCannotCreateAsBlocked() throws Exception {
+ NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
+ group.setBlocked(true);
+ mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
+ assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+
+ NotificationChannelGroup group3 = group.clone();
+ group3.setBlocked(false);
+ mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true);
+ assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+ }
+
+ @Test
public void testIsGroup_appCannotResetBlock() throws Exception {
NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
@@ -4706,7 +4719,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testGetConversations_noDisabledGroups() {
NotificationChannelGroup group = new NotificationChannelGroup("a", "a");
group.setBlocked(true);
- mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true);
+ mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, false);
NotificationChannel parent = new NotificationChannel("parent", "p", 1);
mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
index 525888df7c78..cb9eb52bfc00 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
@@ -30,7 +30,6 @@ import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER
import static android.window.DisplayAreaOrganizer.FEATURE_FULLSCREEN_MAGNIFICATION;
import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER;
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED;
-import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_LAST;
@@ -197,25 +196,6 @@ public class DisplayAreaPolicyBuilderTest {
}
@Test
- public void testBuilder_defaultPolicy_hasOneHandedBackgroundFeature() {
- final DisplayAreaPolicy.Provider defaultProvider = DisplayAreaPolicy.Provider.fromResources(
- resourcesWithProvider(""));
- final DisplayAreaPolicyBuilder.Result defaultPolicy =
- (DisplayAreaPolicyBuilder.Result) defaultProvider.instantiate(mWms, mDisplayContent,
- mRoot, mImeContainer);
- if (mDisplayContent.isDefaultDisplay) {
- final List<Feature> features = defaultPolicy.getFeatures();
- boolean hasOneHandedBackgroundFeature = false;
- for (Feature feature : features) {
- hasOneHandedBackgroundFeature |=
- feature.getId() == FEATURE_ONE_HANDED_BACKGROUND_PANEL;
- }
-
- assertThat(hasOneHandedBackgroundFeature).isTrue();
- }
- }
-
- @Test
public void testBuilder_defaultPolicy_hasWindowedMagnificationFeature() {
final DisplayAreaPolicy.Provider defaultProvider = DisplayAreaPolicy.Provider.fromResources(
resourcesWithProvider(""));
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 2ef59f6ac5c9..2f78b588f305 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1718,6 +1718,7 @@ public class DisplayContentTests extends WindowTestsBase {
@Test
public void testShellTransitRotation() {
DisplayContent dc = createNewDisplay();
+ dc.setLastHasContent();
final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
final DisplayRotation dr = dc.getDisplayRotation();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index ed3888c7aedd..141588a87585 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -488,6 +488,7 @@ public class TransitionTests extends WindowTestsBase {
final TestTransitionPlayer player = registerTestTransitionPlayer();
mDisplayContent.getDisplayRotation().setRotation(mDisplayContent.getRotation() + 1);
+ mDisplayContent.setLastHasContent();
mDisplayContent.requestChangeTransitionIfNeeded(1 /* any changes */,
null /* displayChange */);
final FadeRotationAnimationController fadeController =
@@ -536,6 +537,7 @@ public class TransitionTests extends WindowTestsBase {
null /* remoteTransition */, null /* displayChange */);
mDisplayContent.getDisplayRotation().setRotation(mDisplayContent.getRotation() + 1);
final int anyChanges = 1;
+ mDisplayContent.setLastHasContent();
mDisplayContent.requestChangeTransitionIfNeeded(anyChanges, null /* displayChange */);
transition.setKnownConfigChanges(mDisplayContent, anyChanges);
final FadeRotationAnimationController fadeController =
@@ -550,9 +552,11 @@ public class TransitionTests extends WindowTestsBase {
assertTrue(app.getTask().inTransition());
final SurfaceControl.Transaction startTransaction = mock(SurfaceControl.Transaction.class);
+ final SurfaceControl leash = statusBar.mToken.getAnimationLeash();
+ doReturn(true).when(leash).isValid();
player.onTransactionReady(startTransaction);
// The leash should be unrotated.
- verify(startTransaction).setMatrix(eq(statusBar.mToken.getAnimationLeash()), any(), any());
+ verify(startTransaction).setMatrix(eq(leash), any(), any());
// The redrawn window will be faded in when the transition finishes. And because this test
// only use one non-activity window, the fade rotation controller should also be cleared.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 049966c7310d..4dffe7e8345b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -428,6 +428,25 @@ public class ZOrderingTests extends WindowTestsBase {
assertWindowHigher(mImeWindow, imeAppTarget);
}
+ @Test
+ public void testAssignWindowLayers_ForImeOnPopupImeLayeringTarget() {
+ final WindowState imeAppTarget = createWindow(null, TYPE_APPLICATION,
+ mAppWindow.mActivityRecord, "imeAppTarget");
+ mDisplayContent.setImeInputTarget(imeAppTarget);
+ mDisplayContent.setImeLayeringTarget(imeAppTarget);
+ mDisplayContent.setImeControlTarget(imeAppTarget);
+
+ // Set a popup IME layering target and keeps the original IME control target behinds it.
+ final WindowState popupImeTargetWin = createWindow(imeAppTarget,
+ TYPE_APPLICATION_SUB_PANEL, mAppWindow.mActivityRecord, "popupImeTargetWin");
+ mDisplayContent.setImeLayeringTarget(popupImeTargetWin);
+ mDisplayContent.updateImeParent();
+
+ // Ime should on top of the popup IME layering target window.
+ mDisplayContent.assignChildLayers(mTransaction);
+ assertWindowHigher(mImeWindow, popupImeTargetWin);
+ }
+
@Test
public void testAssignWindowLayers_ForNegativelyZOrderedSubtype() {
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index d94fafc6a5bf..ce9530c196ef 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -701,8 +701,15 @@ public final class Call {
*/
public static final int PROPERTY_CROSS_SIM = 0x00004000;
+ /**
+ * Connection is a tethered external call.
+ * Indicates that the {@link Connection} is fixed on this device but the audio streams are
+ * re-routed to another device.
+ */
+ public static final int PROPERTY_TETHERED_CALL = 0x00008000;
+
//******************************************************************************************
- // Next PROPERTY value: 0x00004000
+ // Next PROPERTY value: 0x00010000
//******************************************************************************************
private final @CallState int mState;
@@ -899,6 +906,9 @@ public final class Call {
if (hasProperty(properties, PROPERTY_CROSS_SIM)) {
builder.append(" PROPERTY_CROSS_SIM");
}
+ if (hasProperty(properties, PROPERTY_TETHERED_CALL)) {
+ builder.append(" PROPERTY_TETHERED_CALL");
+ }
builder.append("]");
return builder.toString();
}
diff --git a/telecomm/java/android/telecom/CallAudioState.java b/telecomm/java/android/telecom/CallAudioState.java
index fccdf76372dd..55957bd85eaa 100644
--- a/telecomm/java/android/telecom/CallAudioState.java
+++ b/telecomm/java/android/telecom/CallAudioState.java
@@ -27,7 +27,6 @@ import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -42,7 +41,8 @@ import java.util.stream.Collectors;
public final class CallAudioState implements Parcelable {
/** @hide */
@Retention(RetentionPolicy.SOURCE)
- @IntDef(value={ROUTE_EARPIECE, ROUTE_BLUETOOTH, ROUTE_WIRED_HEADSET, ROUTE_SPEAKER},
+ @IntDef(value = {ROUTE_EARPIECE, ROUTE_BLUETOOTH, ROUTE_WIRED_HEADSET, ROUTE_SPEAKER,
+ ROUTE_EXTERNAL},
flag=true)
public @interface CallAudioRoute {}
@@ -58,6 +58,9 @@ public final class CallAudioState implements Parcelable {
/** Direct the audio stream through the device's speakerphone. */
public static final int ROUTE_SPEAKER = 0x00000008;
+ /** Direct the audio stream through another device. */
+ public static final int ROUTE_EXTERNAL = 0x00000010;
+
/**
* Direct the audio stream through the device's earpiece or wired headset if one is
* connected.
@@ -70,7 +73,7 @@ public final class CallAudioState implements Parcelable {
* @hide
**/
public static final int ROUTE_ALL = ROUTE_EARPIECE | ROUTE_BLUETOOTH | ROUTE_WIRED_HEADSET |
- ROUTE_SPEAKER;
+ ROUTE_SPEAKER | ROUTE_EXTERNAL;
private final boolean isMuted;
private final int route;
@@ -189,7 +192,11 @@ public final class CallAudioState implements Parcelable {
*/
@CallAudioRoute
public int getSupportedRouteMask() {
- return supportedRouteMask;
+ if (route == ROUTE_EXTERNAL) {
+ return ROUTE_EXTERNAL;
+ } else {
+ return supportedRouteMask;
+ }
}
/**
@@ -233,6 +240,10 @@ public final class CallAudioState implements Parcelable {
listAppend(buffer, "SPEAKER");
}
+ if ((route & ROUTE_EXTERNAL) == ROUTE_EXTERNAL) {
+ listAppend(buffer, "EXTERNAL");
+ }
+
return buffer.toString();
}
@@ -248,10 +259,10 @@ public final class CallAudioState implements Parcelable {
int route = source.readInt();
int supportedRouteMask = source.readInt();
BluetoothDevice activeBluetoothDevice = source.readParcelable(
- ClassLoader.getSystemClassLoader(), android.bluetooth.BluetoothDevice.class);
+ ClassLoader.getSystemClassLoader());
List<BluetoothDevice> supportedBluetoothDevices = new ArrayList<>();
source.readParcelableList(supportedBluetoothDevices,
- ClassLoader.getSystemClassLoader(), android.bluetooth.BluetoothDevice.class);
+ ClassLoader.getSystemClassLoader());
return new CallAudioState(isMuted, route,
supportedRouteMask, activeBluetoothDevice, supportedBluetoothDevices);
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 21a180459978..d63cdc004a3d 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -561,6 +561,15 @@ public abstract class Connection extends Conferenceable {
*/
public static final int PROPERTY_CROSS_SIM = 1 << 13;
+ /**
+ * Connection is a tethered external call.
+ * <p>
+ * Indicates that the {@link Connection} is fixed on this device but the audio streams are
+ * re-routed to another device.
+ * <p>
+ */
+ public static final int PROPERTY_TETHERED_CALL = 1 << 14;
+
//**********************************************************************************************
// Next PROPERTY value: 1<<14
//**********************************************************************************************
@@ -3537,9 +3546,9 @@ public abstract class Connection extends Conferenceable {
mIsBlocked = in.readByte() != 0;
mIsInContacts = in.readByte() != 0;
CallScreeningService.ParcelableCallResponse response
- = in.readParcelable(CallScreeningService.class.getClassLoader(), android.telecom.CallScreeningService.ParcelableCallResponse.class);
+ = in.readParcelable(CallScreeningService.class.getClassLoader());
mCallResponse = response == null ? null : response.toCallResponse();
- mCallScreeningComponent = in.readParcelable(ComponentName.class.getClassLoader(), android.content.ComponentName.class);
+ mCallScreeningComponent = in.readParcelable(ComponentName.class.getClassLoader());
}
@NonNull
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 1172e1392ef8..be5fae488d5e 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -272,17 +272,17 @@ public final class ConnectionRequest implements Parcelable {
}
private ConnectionRequest(Parcel in) {
- mAccountHandle = in.readParcelable(getClass().getClassLoader(), android.telecom.PhoneAccountHandle.class);
- mAddress = in.readParcelable(getClass().getClassLoader(), android.net.Uri.class);
- mExtras = in.readParcelable(getClass().getClassLoader(), android.os.Bundle.class);
+ mAccountHandle = in.readParcelable(getClass().getClassLoader());
+ mAddress = in.readParcelable(getClass().getClassLoader());
+ mExtras = in.readParcelable(getClass().getClassLoader());
mVideoState = in.readInt();
mTelecomCallId = in.readString();
mShouldShowIncomingCallUi = in.readInt() == 1;
- mRttPipeFromInCall = in.readParcelable(getClass().getClassLoader(), android.os.ParcelFileDescriptor.class);
- mRttPipeToInCall = in.readParcelable(getClass().getClassLoader(), android.os.ParcelFileDescriptor.class);
+ mRttPipeFromInCall = in.readParcelable(getClass().getClassLoader());
+ mRttPipeToInCall = in.readParcelable(getClass().getClassLoader());
mParticipants = new ArrayList<Uri>();
- in.readList(mParticipants, getClass().getClassLoader(), android.net.Uri.class);
+ in.readList(mParticipants, getClass().getClassLoader());
mIsAdhocConference = in.readInt() == 1;
}
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 0f034ad6a45e..ed7b79f62753 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -287,7 +287,7 @@ public final class DisconnectCause implements Parcelable {
int tone = source.readInt();
int telephonyDisconnectCause = source.readInt();
int telephonyPreciseDisconnectCause = source.readInt();
- ImsReasonInfo imsReasonInfo = source.readParcelable(null, android.telephony.ims.ImsReasonInfo.class);
+ ImsReasonInfo imsReasonInfo = source.readParcelable(null);
return new DisconnectCause(code, label, description, reason, tone,
telephonyDisconnectCause, telephonyPreciseDisconnectCause, imsReasonInfo);
}
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index f412a1825e2a..320308c9e926 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -623,9 +623,9 @@ public final class ParcelableCall implements Parcelable {
ClassLoader classLoader = ParcelableCall.class.getClassLoader();
String id = source.readString();
int state = source.readInt();
- DisconnectCause disconnectCause = source.readParcelable(classLoader, android.telecom.DisconnectCause.class);
+ DisconnectCause disconnectCause = source.readParcelable(classLoader);
List<String> cannedSmsResponses = new ArrayList<>();
- source.readList(cannedSmsResponses, classLoader, java.lang.String.class);
+ source.readList(cannedSmsResponses, classLoader);
int capabilities = source.readInt();
int properties = source.readInt();
long connectTimeMillis = source.readLong();
@@ -633,23 +633,23 @@ public final class ParcelableCall implements Parcelable {
int handlePresentation = source.readInt();
String callerDisplayName = source.readString();
int callerDisplayNamePresentation = source.readInt();
- GatewayInfo gatewayInfo = source.readParcelable(classLoader, android.telecom.GatewayInfo.class);
- PhoneAccountHandle accountHandle = source.readParcelable(classLoader, android.telecom.PhoneAccountHandle.class);
+ GatewayInfo gatewayInfo = source.readParcelable(classLoader);
+ PhoneAccountHandle accountHandle = source.readParcelable(classLoader);
boolean isVideoCallProviderChanged = source.readByte() == 1;
IVideoProvider videoCallProvider =
IVideoProvider.Stub.asInterface(source.readStrongBinder());
String parentCallId = source.readString();
List<String> childCallIds = new ArrayList<>();
- source.readList(childCallIds, classLoader, java.lang.String.class);
- StatusHints statusHints = source.readParcelable(classLoader, android.telecom.StatusHints.class);
+ source.readList(childCallIds, classLoader);
+ StatusHints statusHints = source.readParcelable(classLoader);
int videoState = source.readInt();
List<String> conferenceableCallIds = new ArrayList<>();
- source.readList(conferenceableCallIds, classLoader, java.lang.String.class);
+ source.readList(conferenceableCallIds, classLoader);
Bundle intentExtras = source.readBundle(classLoader);
Bundle extras = source.readBundle(classLoader);
int supportedAudioRoutes = source.readInt();
boolean isRttCallChanged = source.readByte() == 1;
- ParcelableRttCall rttCall = source.readParcelable(classLoader, android.telecom.ParcelableRttCall.class);
+ ParcelableRttCall rttCall = source.readParcelable(classLoader);
long creationTimeMillis = source.readLong();
int callDirection = source.readInt();
int callerNumberVerificationStatus = source.readInt();
diff --git a/telecomm/java/android/telecom/ParcelableConference.java b/telecomm/java/android/telecom/ParcelableConference.java
index e57c833e930e..1f8aafbca476 100644
--- a/telecomm/java/android/telecom/ParcelableConference.java
+++ b/telecomm/java/android/telecom/ParcelableConference.java
@@ -292,24 +292,24 @@ public final class ParcelableConference implements Parcelable {
@Override
public ParcelableConference createFromParcel(Parcel source) {
ClassLoader classLoader = ParcelableConference.class.getClassLoader();
- PhoneAccountHandle phoneAccount = source.readParcelable(classLoader, android.telecom.PhoneAccountHandle.class);
+ PhoneAccountHandle phoneAccount = source.readParcelable(classLoader);
int state = source.readInt();
int capabilities = source.readInt();
List<String> connectionIds = new ArrayList<>(2);
- source.readList(connectionIds, classLoader, java.lang.String.class);
+ source.readList(connectionIds, classLoader);
long connectTimeMillis = source.readLong();
IVideoProvider videoCallProvider =
IVideoProvider.Stub.asInterface(source.readStrongBinder());
int videoState = source.readInt();
- StatusHints statusHints = source.readParcelable(classLoader, android.telecom.StatusHints.class);
+ StatusHints statusHints = source.readParcelable(classLoader);
Bundle extras = source.readBundle(classLoader);
int properties = source.readInt();
long connectElapsedTimeMillis = source.readLong();
- Uri address = source.readParcelable(classLoader, android.net.Uri.class);
+ Uri address = source.readParcelable(classLoader);
int addressPresentation = source.readInt();
String callerDisplayName = source.readString();
int callerDisplayNamePresentation = source.readInt();
- DisconnectCause disconnectCause = source.readParcelable(classLoader, android.telecom.DisconnectCause.class);
+ DisconnectCause disconnectCause = source.readParcelable(classLoader);
boolean isRingbackRequested = source.readInt() == 1;
int callDirection = source.readInt();
diff --git a/telecomm/java/android/telecom/ParcelableConnection.java b/telecomm/java/android/telecom/ParcelableConnection.java
index 7b8333870eaf..2b9ce9b46ad7 100644
--- a/telecomm/java/android/telecom/ParcelableConnection.java
+++ b/telecomm/java/android/telecom/ParcelableConnection.java
@@ -261,10 +261,10 @@ public final class ParcelableConnection implements Parcelable {
public ParcelableConnection createFromParcel(Parcel source) {
ClassLoader classLoader = ParcelableConnection.class.getClassLoader();
- PhoneAccountHandle phoneAccount = source.readParcelable(classLoader, android.telecom.PhoneAccountHandle.class);
+ PhoneAccountHandle phoneAccount = source.readParcelable(classLoader);
int state = source.readInt();
int capabilities = source.readInt();
- Uri address = source.readParcelable(classLoader, android.net.Uri.class);
+ Uri address = source.readParcelable(classLoader);
int addressPresentation = source.readInt();
String callerDisplayName = source.readString();
int callerDisplayNamePresentation = source.readInt();
@@ -274,8 +274,8 @@ public final class ParcelableConnection implements Parcelable {
boolean ringbackRequested = source.readByte() == 1;
boolean audioModeIsVoip = source.readByte() == 1;
long connectTimeMillis = source.readLong();
- StatusHints statusHints = source.readParcelable(classLoader, android.telecom.StatusHints.class);
- DisconnectCause disconnectCause = source.readParcelable(classLoader, android.telecom.DisconnectCause.class);
+ StatusHints statusHints = source.readParcelable(classLoader);
+ DisconnectCause disconnectCause = source.readParcelable(classLoader);
List<String> conferenceableConnectionIds = new ArrayList<>();
source.readStringList(conferenceableConnectionIds);
Bundle extras = Bundle.setDefusable(source.readBundle(classLoader), true);
diff --git a/telecomm/java/android/telecom/ParcelableRttCall.java b/telecomm/java/android/telecom/ParcelableRttCall.java
index b88473a8a63b..fbcf486151f9 100644
--- a/telecomm/java/android/telecom/ParcelableRttCall.java
+++ b/telecomm/java/android/telecom/ParcelableRttCall.java
@@ -46,8 +46,8 @@ public class ParcelableRttCall implements Parcelable {
protected ParcelableRttCall(Parcel in) {
mRttMode = in.readInt();
- mTransmitStream = in.readParcelable(ParcelFileDescriptor.class.getClassLoader(), android.os.ParcelFileDescriptor.class);
- mReceiveStream = in.readParcelable(ParcelFileDescriptor.class.getClassLoader(), android.os.ParcelFileDescriptor.class);
+ mTransmitStream = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
+ mReceiveStream = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
}
public static final @android.annotation.NonNull Creator<ParcelableRttCall> CREATOR = new Creator<ParcelableRttCall>() {
diff --git a/telecomm/java/android/telecom/PhoneAccountSuggestion.java b/telecomm/java/android/telecom/PhoneAccountSuggestion.java
index d9f89d544f40..2589d9504f6d 100644
--- a/telecomm/java/android/telecom/PhoneAccountSuggestion.java
+++ b/telecomm/java/android/telecom/PhoneAccountSuggestion.java
@@ -84,7 +84,7 @@ public final class PhoneAccountSuggestion implements Parcelable {
}
private PhoneAccountSuggestion(Parcel in) {
- mHandle = in.readParcelable(PhoneAccountHandle.class.getClassLoader(), android.telecom.PhoneAccountHandle.class);
+ mHandle = in.readParcelable(PhoneAccountHandle.class.getClassLoader());
mReason = in.readInt();
mShouldAutoSelect = in.readByte() != 0;
}
diff --git a/telecomm/java/android/telecom/StatusHints.java b/telecomm/java/android/telecom/StatusHints.java
index 2faecc2e3468..762c93a49022 100644
--- a/telecomm/java/android/telecom/StatusHints.java
+++ b/telecomm/java/android/telecom/StatusHints.java
@@ -132,8 +132,8 @@ public final class StatusHints implements Parcelable {
private StatusHints(Parcel in) {
mLabel = in.readCharSequence();
- mIcon = in.readParcelable(getClass().getClassLoader(), android.graphics.drawable.Icon.class);
- mExtras = in.readParcelable(getClass().getClassLoader(), android.os.Bundle.class);
+ mIcon = in.readParcelable(getClass().getClassLoader());
+ mExtras = in.readParcelable(getClass().getClassLoader());
}
@Override
diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java
index 6d673fbc7305..2b355ae216e3 100644
--- a/telephony/java/android/telephony/AvailableNetworkInfo.java
+++ b/telephony/java/android/telephony/AvailableNetworkInfo.java
@@ -185,9 +185,9 @@ public final class AvailableNetworkInfo implements Parcelable {
mMccMncs = new ArrayList<>();
in.readStringList(mMccMncs);
mBands = new ArrayList<>();
- in.readList(mBands, Integer.class.getClassLoader(), java.lang.Integer.class);
+ in.readList(mBands, Integer.class.getClassLoader());
mRadioAccessSpecifiers = new ArrayList<>();
- in.readList(mRadioAccessSpecifiers, RadioAccessSpecifier.class.getClassLoader(), android.telephony.RadioAccessSpecifier.class);
+ in.readList(mRadioAccessSpecifiers, RadioAccessSpecifier.class.getClassLoader());
}
public AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs,
diff --git a/telephony/java/android/telephony/BarringInfo.java b/telephony/java/android/telephony/BarringInfo.java
index 29152f19d17d..0aa4b5805cd6 100644
--- a/telephony/java/android/telephony/BarringInfo.java
+++ b/telephony/java/android/telephony/BarringInfo.java
@@ -294,8 +294,8 @@ public final class BarringInfo implements Parcelable {
/** @hide */
public BarringInfo(Parcel p) {
- mCellIdentity = p.readParcelable(CellIdentity.class.getClassLoader(), android.telephony.CellIdentity.class);
- mBarringServiceInfos = p.readSparseArray(BarringServiceInfo.class.getClassLoader(), android.telephony.BarringInfo.BarringServiceInfo.class);
+ mCellIdentity = p.readParcelable(CellIdentity.class.getClassLoader());
+ mBarringServiceInfos = p.readSparseArray(BarringServiceInfo.class.getClassLoader());
}
@Override
diff --git a/telephony/java/android/telephony/CallAttributes.java b/telephony/java/android/telephony/CallAttributes.java
index b7bef39aa275..0c258f4b6435 100644
--- a/telephony/java/android/telephony/CallAttributes.java
+++ b/telephony/java/android/telephony/CallAttributes.java
@@ -53,9 +53,9 @@ public final class CallAttributes implements Parcelable {
}
private CallAttributes(Parcel in) {
- this.mPreciseCallState = in.readParcelable(PreciseCallState.class.getClassLoader(), android.telephony.PreciseCallState.class);
+ this.mPreciseCallState = in.readParcelable(PreciseCallState.class.getClassLoader());
this.mNetworkType = in.readInt();
- this.mCallQuality = in.readParcelable(CallQuality.class.getClassLoader(), android.telephony.CallQuality.class);
+ this.mCallQuality = in.readParcelable(CallQuality.class.getClassLoader());
}
// getters
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index d604dc1d2c92..808df50466a3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -37,6 +37,8 @@ import android.os.PersistableBundle;
import android.os.RemoteException;
import android.service.carrier.CarrierService;
import android.telecom.TelecomManager;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.gba.TlsParams;
import android.telephony.gba.UaSecurityProtocolIdentifier;
@@ -4532,7 +4534,7 @@ public class CarrierConfigManager {
"carrier_auto_cancel_cs_notification";
/**
- * Passing this value as {@link KEY_SUBSCRIPTION_GROUP_UUID_STRING} will remove the
+ * Passing this value as {@link #KEY_SUBSCRIPTION_GROUP_UUID_STRING} will remove the
* subscription from a group instead of adding it to a group.
*
* TODO: Expose in a future release.
@@ -4790,6 +4792,396 @@ public class CarrierConfigManager {
public static final String KEY_RCS_REQUEST_RETRY_INTERVAL_MILLIS_LONG =
KEY_PREFIX + "rcs_request_retry_interval_millis_long";
+ /** SIP timer T1 as per 3GPP TS 24.229 Table 7.7.1 */
+ public static final String KEY_SIP_TIMER_T1_MILLIS_INT =
+ KEY_PREFIX + "sip_timer_t1_millis_int";
+
+ /** SIP timer T2 as per 3GPP TS 24.229 Table 7.7.1 */
+ public static final String KEY_SIP_TIMER_T2_MILLIS_INT =
+ KEY_PREFIX + "sip_timer_t2_millis_int";
+
+ /** SIP timer T4 as per 3GPP TS 24.229 Table 7.7.1 */
+ public static final String KEY_SIP_TIMER_T4_MILLIS_INT =
+ KEY_PREFIX + "sip_timer_t4_millis_int";
+
+ /** SIP timer B as per 3GPP TS 24.229 Table 7.7.1 */
+ public static final String KEY_SIP_TIMER_B_MILLIS_INT =
+ KEY_PREFIX + "sip_timer_b_millis_int";
+
+ /** SIP timer C as per 3GPP TS 24.229 Table 7.7.1 */
+ public static final String KEY_SIP_TIMER_C_MILLIS_INT =
+ KEY_PREFIX + "sip_timer_c_millis_int";
+
+ /** SIP timer D as per 3GPP TS 24.229 Table 7.7.1 */
+ public static final String KEY_SIP_TIMER_D_MILLIS_INT =
+ KEY_PREFIX + "sip_timer_d_millis_int";
+
+ /** SIP timer F as per 3GPP TS 24.229 Table 7.7.1 */
+ public static final String KEY_SIP_TIMER_F_MILLIS_INT =
+ KEY_PREFIX + "sip_timer_f_millis_int";
+
+ /** SIP timer H as per 3GPP TS 24.229 Table 7.7.1 */
+ public static final String KEY_SIP_TIMER_H_MILLIS_INT =
+ KEY_PREFIX + "sip_timer_h_millis_int";
+
+ /** SIP timer J as per 3GPP TS 24.229 Table 7.7.1 */
+ public static final String KEY_SIP_TIMER_J_MILLIS_INT =
+ KEY_PREFIX + "sip_timer_j_millis_int";
+
+ /** Specifies the SIP Server default port. */
+ public static final String KEY_SIP_SERVER_PORT_NUMBER_INT =
+ KEY_PREFIX + "sip_server_port_number_int";
+
+ /**
+ * Specify the “phone-context” parameter as defined in
+ * section 7.2A.10 in 3GPP TS 24.229.
+ */
+ public static final String KEY_PHONE_CONTEXT_DOMAIN_NAME_STRING =
+ KEY_PREFIX + "phone_context_domain_name_string";
+
+ /** @hide */
+ @IntDef({REQUEST_URI_FORMAT_TEL, REQUEST_URI_FORMAT_SIP})
+
+ public @interface RequestUriFormatType {}
+
+ /**
+ * Request URI is of type TEL URI.
+ */
+ public static final int REQUEST_URI_FORMAT_TEL = 0;
+
+ /**
+ * Request URI is of type SIP URI.
+ */
+ public static final int REQUEST_URI_FORMAT_SIP = 1;
+
+ /**
+ * Specify whether the request URI is SIP URI
+ * {@link #REQUEST_URI_FORMAT_SIP} or
+ * TEL URI {@link #REQUEST_URI_FORMAT_TEL}.
+ */
+ public static final String KEY_REQUEST_URI_TYPE_INT =
+ KEY_PREFIX + "request_uri_type_int";
+
+ /**
+ * Flag indicating whether Globally Routable User agent (GRUU)
+ * in supported HEADER is included or not.
+ *
+ * <p> Reference: RFC 5627.
+ */
+ public static final String KEY_GRUU_ENABLED_BOOL =
+ KEY_PREFIX + "gruu_enabled_bool";
+
+ /**
+ * Flag indicating whether to keep/release IMS PDN in case of
+ * moving to non VOPS area.
+ *
+ * <p>if {@code True}, keep IMS PDN in case of moving to non VOPS area.
+ * if {@code false}, otherwise.
+ */
+ public static final String KEY_KEEP_PDN_UP_IN_NO_VOPS_BOOL =
+ KEY_PREFIX + "keep_pdn_up_in_no_vops_bool";
+
+ /** @hide */
+ @IntDef({
+ PREFERRED_TRANSPORT_UDP,
+ PREFERRED_TRANSPORT_TCP,
+ PREFERRED_TRANSPORT_DYNAMIC_UDP_TCP,
+ PREFERRED_TRANSPORT_TLS
+ })
+
+ public @interface PreferredTransportType {}
+
+ /** Preferred Transport is always UDP. */
+ public static final int PREFERRED_TRANSPORT_UDP = 0;
+
+ /** Preferred Transport is always TCP. */
+ public static final int PREFERRED_TRANSPORT_TCP = 1;
+
+ /**
+ * Preferred Transport is both UDP and TCP and selected based
+ * on MTU size specified in {@link #KEY_IPV4_SIP_MTU_SIZE_CELLULAR_INT}
+ * and {@link #KEY_IPV6_SIP_MTU_SIZE_CELLULAR_INT}.
+ *
+ * <p>Default transport is UDP. If message size is larger
+ * than MTU, then TCP shall be used.
+ */
+ public static final int PREFERRED_TRANSPORT_DYNAMIC_UDP_TCP = 2;
+
+ /** Preferred Transport is TLS. */
+ public static final int PREFERRED_TRANSPORT_TLS = 3;
+
+ /**
+ * Specify the preferred transport protocol for SIP messages.
+ *
+ * <p>Possible values are,
+ * {@link #PREFERRED_TRANSPORT_UDP},
+ * {@link #PREFERRED_TRANSPORT_TCP},
+ * {@link #PREFERRED_TRANSPORT_DYNAMIC_UDP_TCP}
+ */
+ public static final String KEY_SIP_PREFERRED_TRANSPORT_INT =
+ KEY_PREFIX + "sip_preferred_transport_int";
+
+ /**
+ * Specify the maximum IPV4 MTU size of SIP message on Cellular.
+ *
+ * <p>If {@link #KEY_SIP_PREFERRED_TRANSPORT_INT} is
+ * {@link #PREFERRED_TRANSPORT_DYNAMIC_UDP_TCP} and SIP message MTU size
+ * is more than this value, then SIP transport will be TCP, else the
+ * SIP transport is UDP.
+ */
+ public static final String KEY_IPV4_SIP_MTU_SIZE_CELLULAR_INT =
+ KEY_PREFIX + "ipv4_sip_mtu_size_cellular_int";
+
+ /**
+ * Specify the maximum IPV6 MTU size of SIP message on Cellular.
+ *
+ * <p>If {@link #KEY_SIP_PREFERRED_TRANSPORT_INT} is
+ * {@link #PREFERRED_TRANSPORT_DYNAMIC_UDP_TCP} and SIP message MTU size
+ * is more than this value, then SIP transport will be TCP, else the
+ * SIP transport is UDP.
+ */
+ public static final String KEY_IPV6_SIP_MTU_SIZE_CELLULAR_INT =
+ KEY_PREFIX + "ipv6_sip_mtu_size_cellular_int";
+
+ /**
+ * This config determines whether IMS PDN needs to be enabled
+ * when VOPS support is not available in both home and roaming scenarios.
+ *
+ * <p>This is applicable before IMS PDN is up, to decide whether
+ * IMS PDN needs to be enabled based on VOPS support in home/roaming.
+ *
+ * <p>Possible values are,
+ * {@link #NETWORK_TYPE_HOME},
+ * {@link #NETWORK_TYPE_ROAMING}
+ * An empty array indicates IMS PDN depends on VOPS on both home
+ * and roaming scenarios.
+ */
+ public static final String KEY_IMS_PDN_ENABLED_IN_NO_VOPS_SUPPORT_INT_ARRAY =
+ KEY_PREFIX + "ims_pdn_enabled_in_no_vops_support_int_array";
+
+ /**
+ * Flag indicating whether IPSec enabled for SIP messages.
+ *
+ * <p> Reference: 3GPP TS 33.203 and RFC 3329.
+ */
+ public static final String KEY_SIP_OVER_IPSEC_ENABLED_BOOL =
+ KEY_PREFIX + "sip_over_ipsec_enabled_bool";
+
+ /** @hide */
+ @IntDef({IPSEC_AUTHENTICATION_ALGORITHM_HMAC_MD5, IPSEC_AUTHENTICATION_ALGORITHM_HMAC_SHA1})
+
+ public @interface IpsecAuthenticationAlgorithmType {}
+
+ /** IPSec Authentication algorithm is HMAC-MD5. see Annex H of TS 33.203 */
+ public static final int IPSEC_AUTHENTICATION_ALGORITHM_HMAC_MD5 = 0;
+
+ /** IPSec Authentication algorithm is HMAC-SHA1. see Annex H of TS 33.203 */
+ public static final int IPSEC_AUTHENTICATION_ALGORITHM_HMAC_SHA1 = 1;
+
+ /**
+ * List of supported IPSEC Authentication algorithms.
+ *
+ * <p>Possible values are,
+ * {@link #IPSEC_AUTHENTICATION_ALGORITHM_HMAC_MD5},
+ * {@link #IPSEC_AUTHENTICATION_ALGORITHM_HMAC_SHA1}
+ */
+ public static final String KEY_IPSEC_AUTHENTICATION_ALGORITHMS_INT_ARRAY =
+ KEY_PREFIX + "ipsec_authentication_algorithms_int_array";
+
+ /** @hide */
+ @IntDef({
+ IPSEC_ENCRYPTION_ALGORITHM_NULL,
+ IPSEC_ENCRYPTION_ALGORITHM_DES_EDE3_CBC,
+ IPSEC_ENCRYPTION_ALGORITHM_AES_CBC
+ })
+
+ public @interface IpsecEncryptionAlgorithmType {}
+
+ /** IPSec Encryption algorithm is NULL. see Annex H of TS 33.203 */
+ public static final int IPSEC_ENCRYPTION_ALGORITHM_NULL = 0;
+
+ /** IPSec Encryption algorithm is DES_EDE3_CBC. see Annex H of TS 33.203 */
+ public static final int IPSEC_ENCRYPTION_ALGORITHM_DES_EDE3_CBC = 1;
+
+ /** IPSec Encryption algorithm is AES_CBC. see Annex H of TS 33.203 */
+ public static final int IPSEC_ENCRYPTION_ALGORITHM_AES_CBC = 2;
+
+ /**
+ * List of supported IPSEC encryption algorithms.
+ *
+ * <p>Possible values are,
+ * {@link #IPSEC_ENCRYPTION_ALGORITHM_NULL},
+ * {@link #IPSEC_ENCRYPTION_ALGORITHM_DES_EDE3_CBC},
+ * {@link #IPSEC_ENCRYPTION_ALGORITHM_AES_CBC}
+ */
+ public static final String KEY_IPSEC_ENCRYPTION_ALGORITHMS_INT_ARRAY =
+ KEY_PREFIX + "ipsec_encryption_algorithms_int_array";
+
+ /**
+ * Expiry timer for IMS Registration in seconds.
+ * <p>Reference: RFC 3261 Section 20.19.
+ */
+ public static final String KEY_REGISTRATION_EXPIRY_TIMER_SEC_INT =
+ KEY_PREFIX + "registration_expiry_timer_sec_int";
+
+ /** Registration Retry Base-time as per RFC 5626 Section 4.5. */
+ public static final String KEY_REGISTRATION_RETRY_BASE_TIMER_MILLIS_INT =
+ KEY_PREFIX + "registration_retry_base_timer_millis_int";
+
+ /** Registration Retry max-time as per RFC 5626 Section 4.5. */
+ public static final String KEY_REGISTRATION_RETRY_MAX_TIMER_MILLIS_INT =
+ KEY_PREFIX + "registration_retry_max_timer_millis_int";
+
+ /**
+ * Flag indicating whether subscription to registration event package
+ * is supported or not.
+ */
+ public static final String KEY_REGISTRATION_EVENT_PACKAGE_SUPPORTED_BOOL =
+ KEY_PREFIX + "registration_event_package_supported_bool";
+
+ /**
+ * Expiry timer for SUBSCRIBE in seconds.
+ * <p>Reference: RFC 3261 Section 20.19.
+ */
+ public static final String KEY_REGISTRATION_SUBSCRIBE_EXPIRY_TIMER_SEC_INT =
+ KEY_PREFIX + "registration_subscribe_expiry_timer_sec_int";
+
+ /** @hide */
+ @IntDef({
+ GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_WIFI,
+ GEOLOCATION_PIDF_FOR_EMERGENCY_ON_WIFI,
+ GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_CELLULAR,
+ GEOLOCATION_PIDF_FOR_EMERGENCY_ON_CELLULAR
+ })
+
+ public @interface GeolocationPidfAllowedType {}
+
+ /**
+ * Indicates geolocation PIDF XML needs to be included for
+ * normal/non-emergency call scenario on WiFi
+ *
+ * <p>Geolocation for normal/non-emergency call should only include
+ * country code.
+ */
+ public static final int GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_WIFI = 1;
+
+ /**
+ * Indicates geolocation PIDF XML needs to be included for emergency
+ * call scenario on WiFi
+ */
+ public static final int GEOLOCATION_PIDF_FOR_EMERGENCY_ON_WIFI = 2;
+
+ /**
+ * Indicates geolocation PIDF XML needs to be included for normal/non-emergency
+ * call scenario on Cellular
+ *
+ * <p>Geolocation for normal/non-emergency call should only include
+ * country code.
+ */
+ public static final int GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_CELLULAR = 3;
+
+ /**
+ * Indicates geolocation PIDF XML needs to be included for emergency
+ * call scenario on Cellular
+ */
+ public static final int GEOLOCATION_PIDF_FOR_EMERGENCY_ON_CELLULAR = 4;
+
+ /**
+ * List of cases where geolocation PIDF XML needs to be included in the
+ * SIP REGISTER over WiFi and Cellular.
+ *
+ * <p>Possible values are,
+ * {@link #GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_WIFI},
+ * {@link #GEOLOCATION_PIDF_FOR_EMERGENCY_ON_WIFI},
+ * {@link #GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_CELLULAR},
+ * {@link #GEOLOCATION_PIDF_FOR_EMERGENCY_ON_CELLULAR}
+ *
+ * <p>An empty array indicates geolocation PIDF XML should not be included in
+ * the SIP REGISTER over WiFi and Cellular.
+ */
+ public static final String KEY_GEOLOCATION_PIDF_IN_SIP_REGISTER_SUPPORT_INT_ARRAY =
+ KEY_PREFIX + "geolocation_pidf_in_sip_register_support_int_array";
+
+ /**
+ * List of cases where geolocation PIDF XML needs to be included in the
+ * SIP INVITE over WiFi and Cellular.
+ *
+ * <p>Possible values are,
+ * {@link #GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_WIFI},
+ * {@link #GEOLOCATION_PIDF_FOR_EMERGENCY_ON_WIFI},
+ * {@link #GEOLOCATION_PIDF_FOR_NON_EMERGENCY_ON_CELLULAR},
+ * {@link #GEOLOCATION_PIDF_FOR_EMERGENCY_ON_CELLULAR}
+ *
+ * <p>An empty array indicates geolocation PIDF XML should not be included
+ * in the SIP INVITE over WiFi and Cellular.
+ */
+ public static final String KEY_GEOLOCATION_PIDF_IN_SIP_INVITE_SUPPORT_INT_ARRAY =
+ KEY_PREFIX + "geolocation_pidf_in_sip_invite_support_int_array";
+
+ /**
+ * Specifies the IMS User Agent in template format.
+ *
+ * <p>Example: #MANUFACTURER#_#MODEL#_Android#AV#_#BUILD#".
+ * IMS Stack should internally substitute the tokens with the
+ * values from the respective android properties.
+ *
+ * <p>List of allowed tokens and the corresponding android properties are,
+ * <UL>
+ * <LI>MANUFACTURER : ro.product.manufacturer</LI>
+ * <LI>MODEL : ro.product.model</LI>
+ * <LI>AV : ro.build.version.release"</LI>
+ * <LI>BUILD : ro.build.id</LI>
+ * </UL>
+ * <p> Vendor IMS Stack should strip any whitespace characters present
+ * in the android properties values before replacing the token.
+ *
+ * <p> An empty string is invalid as per IR92 section 2.6. This key is
+ * considered invalid if the format is violated. If the key is invalid or
+ * not configured, IMS stack should use internal default values.
+ */
+ public static final String KEY_IMS_USER_AGENT_STRING =
+ KEY_PREFIX + "ims_user_agent_string";
+
+ /** @hide */
+ @IntDef({
+ NETWORK_TYPE_HOME,
+ NETWORK_TYPE_ROAMING
+ })
+
+ public @interface NetworkType {}
+
+ /** Indicates HOME Network. */
+ public static final int NETWORK_TYPE_HOME = 0;
+
+ /** Indicates Roaming Network. */
+ public static final int NETWORK_TYPE_ROAMING = 1;
+
+ /** @hide */
+ @IntDef({
+ RTCP_INACTIVITY_ON_HOLD,
+ RTCP_INACTIVITY_ON_CONNECTED,
+ RTP_INACTIVITY_ON_CONNECTED,
+ E911_RTCP_INACTIVITY_ON_CONNECTED,
+ E911_RTP_INACTIVITY_ON_CONNECTED
+ })
+
+ public @interface MediaInactivityReason {}
+
+ /** RTCP inactivity occurred when call is on HOLD. */
+ public static final int RTCP_INACTIVITY_ON_HOLD = 0;
+
+ /** RTCP inactivity occurred when call is connected. */
+ public static final int RTCP_INACTIVITY_ON_CONNECTED = 1;
+
+ /** RTP inactivity occurred when call is connected. */
+ public static final int RTP_INACTIVITY_ON_CONNECTED = 2;
+
+ /** E911 RTCP inactivity occurred when call is connected. */
+ public static final int E911_RTCP_INACTIVITY_ON_CONNECTED = 3;
+
+ /** E911 RTP inactivity occurred when call is connected. */
+ public static final int E911_RTP_INACTIVITY_ON_CONNECTED = 4;
+
private Ims() {}
private static PersistableBundle getDefaults() {
@@ -4826,6 +5218,2159 @@ public class CarrierConfigManager {
"+g.gsma.rcs.botversion=\"#=1,#=2\"",
"+g.gsma.rcs.cpimext"});
+ defaults.putBoolean(KEY_GRUU_ENABLED_BOOL, true);
+ defaults.putBoolean(KEY_SIP_OVER_IPSEC_ENABLED_BOOL, true);
+ defaults.putBoolean(KEY_KEEP_PDN_UP_IN_NO_VOPS_BOOL, false);
+ defaults.putBoolean(KEY_REGISTRATION_EVENT_PACKAGE_SUPPORTED_BOOL, true);
+
+ defaults.putInt(KEY_SIP_TIMER_T1_MILLIS_INT, 2000);
+ defaults.putInt(KEY_SIP_TIMER_T2_MILLIS_INT, 16000);
+ defaults.putInt(KEY_SIP_TIMER_T4_MILLIS_INT, 17000);
+ defaults.putInt(KEY_SIP_TIMER_B_MILLIS_INT, 128000);
+ defaults.putInt(KEY_SIP_TIMER_C_MILLIS_INT, 210000);
+ defaults.putInt(KEY_SIP_TIMER_D_MILLIS_INT, 130000);
+ defaults.putInt(KEY_SIP_TIMER_F_MILLIS_INT, 128000);
+ defaults.putInt(KEY_SIP_TIMER_H_MILLIS_INT, 128000);
+ defaults.putInt(KEY_SIP_TIMER_J_MILLIS_INT, 128000);
+ defaults.putInt(KEY_SIP_SERVER_PORT_NUMBER_INT, 5060);
+ defaults.putInt(KEY_REQUEST_URI_TYPE_INT, REQUEST_URI_FORMAT_SIP);
+ defaults.putInt(KEY_SIP_PREFERRED_TRANSPORT_INT, PREFERRED_TRANSPORT_DYNAMIC_UDP_TCP);
+ defaults.putInt(KEY_IPV4_SIP_MTU_SIZE_CELLULAR_INT, 1500);
+ defaults.putInt(KEY_IPV6_SIP_MTU_SIZE_CELLULAR_INT, 1500);
+ defaults.putInt(KEY_REGISTRATION_EXPIRY_TIMER_SEC_INT, 600000);
+ defaults.putInt(KEY_REGISTRATION_RETRY_BASE_TIMER_MILLIS_INT, 30000);
+ defaults.putInt(KEY_REGISTRATION_RETRY_MAX_TIMER_MILLIS_INT, 1800000);
+ defaults.putInt(KEY_REGISTRATION_SUBSCRIBE_EXPIRY_TIMER_SEC_INT, 600000);
+
+ defaults.putIntArray(
+ KEY_IPSEC_AUTHENTICATION_ALGORITHMS_INT_ARRAY,
+ new int[] {
+ IPSEC_AUTHENTICATION_ALGORITHM_HMAC_MD5,
+ IPSEC_AUTHENTICATION_ALGORITHM_HMAC_SHA1
+ });
+ defaults.putIntArray(
+ KEY_IPSEC_ENCRYPTION_ALGORITHMS_INT_ARRAY,
+ new int[] {
+ IPSEC_ENCRYPTION_ALGORITHM_NULL,
+ IPSEC_ENCRYPTION_ALGORITHM_DES_EDE3_CBC,
+ IPSEC_ENCRYPTION_ALGORITHM_AES_CBC
+ });
+ defaults.putIntArray(
+ KEY_IMS_PDN_ENABLED_IN_NO_VOPS_SUPPORT_INT_ARRAY,
+ new int[] {
+ });
+ defaults.putIntArray(
+ KEY_GEOLOCATION_PIDF_IN_SIP_REGISTER_SUPPORT_INT_ARRAY,
+ new int[] {
+ GEOLOCATION_PIDF_FOR_EMERGENCY_ON_WIFI
+ });
+ defaults.putIntArray(
+ KEY_GEOLOCATION_PIDF_IN_SIP_INVITE_SUPPORT_INT_ARRAY,
+ new int[] {
+ GEOLOCATION_PIDF_FOR_EMERGENCY_ON_WIFI
+ });
+
+ defaults.putString(KEY_PHONE_CONTEXT_DOMAIN_NAME_STRING, "");
+ defaults.putString(KEY_IMS_USER_AGENT_STRING,
+ "#MANUFACTURER#_#MODEL#_Android#AV#_#BUILD#");
+
+ return defaults;
+ }
+ }
+
+ /**
+ * IMS Voice configs. This groups the configs required for IMS Voice - VoNR/VoLTE
+ *
+ * <p>Reference: IR.92
+ */
+ public static final class ImsVoice {
+ private ImsVoice() {}
+
+ /** Prefix of all imsvoice.KEY_* constants. */
+ public static final String KEY_PREFIX = "imsvoice.";
+
+ /**
+ * Flag specifying whether VoLTE should be available when on
+ * roaming network.
+ *
+ * <p>If {@code false}: hard disabled.
+ * If {@code true}: then depends on availability, etc.
+ */
+ public static final String KEY_CARRIER_VOLTE_ROAMING_AVAILABLE_BOOL =
+ KEY_PREFIX + "carrier_volte_roaming_available_bool";
+
+ /**
+ * Flag specifying whether to send vertical caller id service codes
+ * (*67 and *82) in the dialed string in the SIP:INVITE.
+ *
+ * <p>If {@code true}, vertical caller id service codes *67 and *82
+ * will be sent in the dialed string in the SIP:INVITE.
+ * If {@code false}, *67 and *82 will be removed.
+ */
+ public static final String KEY_INCLUDE_CALLER_ID_SERVICE_CODES_IN_SIP_INVITE_BOOL =
+ KEY_PREFIX + "include_caller_id_service_codes_in_sip_invite_bool";
+
+ /**
+ * Flag indicating whether Multi-end point setting is enabled or not.
+ */
+ public static final String KEY_MULTIENDPOINT_SUPPORTED_BOOL =
+ KEY_PREFIX + "multiendpoint_supported_bool";
+
+ /**
+ * Flag indicating whether Supported header field with the option tag
+ * 'timer' is enabled or not.
+ *
+ * <p>If {@code true}, session timer support is available.{@code false} otherwise.
+ *
+ * Reference: RFC 4028 Section 3
+ */
+ public static final String KEY_SESSION_TIMER_SUPPORTED_BOOL =
+ KEY_PREFIX + "session_timer_supported_bool";
+
+ /**
+ * Session-expires header field expressed in seconds as per
+ * RFC 4028 Section 3.
+ *
+ * <p>This establishes the upper bound for the session refresh interval.
+ */
+ public static final String KEY_SESSION_EXPIRES_TIMER_SEC_INT =
+ KEY_PREFIX + "session_expires_timer_sec_int";
+
+ /**
+ * Indicates the minimum value for the session interval in seconds.
+ * Represented as min-SE header field as per RFC 4028 Section 3.
+ *
+ * <p>This establishes the lower bound for the session refresh interval.
+ */
+ public static final String KEY_MINIMUM_SESSION_EXPIRES_TIMER_SEC_INT =
+ KEY_PREFIX + "minimum_session_expires_timer_sec_int";
+
+ /** @hide */
+ @IntDef({
+ SESSION_REFRESHER_TYPE_UNKNOWN,
+ SESSION_REFRESHER_TYPE_UAC,
+ SESSION_REFRESHER_TYPE_UAS
+ })
+
+ public @interface SessionRefresherType {}
+
+ /**
+ * Session Refresher entity is unknown. This means UE does not include the
+ * "refresher" parameter in the Session-Expires header field of
+ * the SIP INVITE request.
+ */
+ public static final int SESSION_REFRESHER_TYPE_UNKNOWN = 0;
+
+ /**
+ * Session Refresher entity is User Agent Client (UAC).
+ *
+ * <p>Type of "refresher" parameter in the Session-Expires header field
+ * of the SIP INVITE request is UAC.
+ */
+ public static final int SESSION_REFRESHER_TYPE_UAC = 1;
+
+ /**
+ * Session Refresher entity is User Agent Server (UAS).
+ *
+ * <p>Type of "refresher" parameter in the Session-Expires header field
+ * of the SIP INVITE request is UAS.
+ */
+ public static final int SESSION_REFRESHER_TYPE_UAS = 2;
+
+ /**
+ * Session Refresher entity as per RFC 4028 and IR.92 Section 2.2.8.
+ *
+ * <p>This determines,
+ * a) whether to include the "refresher" parameter
+ * b) Type of refresher" parameter
+ * in the Session-Expires header field of the SIP INVITE request.
+ *
+ * <p>Possible values are,
+ * {@link #SESSION_REFRESHER_TYPE_UNKNOWN},
+ * {@link #SESSION_REFRESHER_TYPE_UAC},
+ * {@link #SESSION_REFRESHER_TYPE_UAS}
+ */
+ public static final String KEY_SESSION_REFRESHER_TYPE_INT =
+ KEY_PREFIX + "session_refresher_type_int";
+
+ /**
+ * Flag indicating whether PRACK must be enabled for all 18x messages.
+ *
+ * <p>If {@code false}, only 18x responses with SDP are sent reliably.
+ * If {@code true}, SIP 18x responses (other than SIP 183 response)
+ * are sent reliably.
+ */
+ public static final String KEY_PRACK_SUPPORTED_FOR_18X_BOOL =
+ KEY_PREFIX + "prack_supported_for_18x_bool";
+
+ /** @hide */
+ @IntDef({
+ CONFERENCE_SUBSCRIBE_TYPE_IN_DIALOG,
+ CONFERENCE_SUBSCRIBE_TYPE_OUT_OF_DIALOG
+ })
+
+ public @interface ConferenceSubscribeType {}
+
+ /**
+ * The SIP SUBSCRIBE to conference state events is sent in the
+ * SIP INVITE dialog between the UE and the conference server.
+ *
+ * <p>Reference: IR.92 Section 2.3.3.
+ */
+ public static final int CONFERENCE_SUBSCRIBE_TYPE_IN_DIALOG = 0;
+
+ /**
+ * The SIP SUBSCRIBE to conference state events is sent out of
+ * the SIP INVITE dialog between the UE and the conference server.
+ *
+ * <p>Reference: IR.92 Section 2.3.3.
+ */
+ public static final int CONFERENCE_SUBSCRIBE_TYPE_OUT_OF_DIALOG = 1;
+
+ /**
+ * This is used to specify whether the SIP SUBSCRIBE to conference state events,
+ * is sent in or out of the SIP INVITE dialog between the UE and the
+ * conference server.
+ *
+ * <p>Reference: IR.92 Section 2.3.3.
+ *
+ * <p>Possible values are,
+ * {@link #CONFERENCE_SUBSCRIBE_TYPE_IN_DIALOG},
+ * {@link #CONFERENCE_SUBSCRIBE_TYPE_OUT_OF_DIALOG}
+ *
+ * An empty array indicates SUBSCRIBE to conference event package
+ * is not required.
+ */
+ public static final String KEY_CONFERENCE_SUBSCRIBE_TYPE_INT =
+ KEY_PREFIX + "conference_subscribe_type_int";
+
+ /**
+ * Flag specifying whether QoS preconditions are supported during call setup.
+ *
+ * <p>If {@code true}: QoS Preconditions are supported during call setup and
+ * 'precondition' tag is included in the SIP INVITE header and precondition
+ * parameters are sent in SDP as required.
+ * <p>If {@code false}: QoS Preconditions are not supported during call setup.
+ *
+ * <p>Reference: 3GPP TS 24.229
+ */
+ public static final String KEY_VOICE_QOS_PRECONDITION_SUPPORTED_BOOL =
+ KEY_PREFIX + "voice_qos_precondition_supported_bool";
+
+ /**
+ * Flag specifying whether voice is allowed on default bearer.
+ *
+ * <p>If {@code true}: voice packets can be sent on default bearer. {@code false} otherwise.
+ */
+ public static final String KEY_VOICE_ON_DEFAULT_BEARER_SUPPORTED_BOOL =
+ KEY_PREFIX + "voice_on_default_bearer_supported_bool";
+
+ /**
+ * Specifies the dedicated bearer wait time during call establishment.
+ *
+ * <p>If dedicated bearer is not established within this time and if
+ * {@link #KEY_VOICE_ON_DEFAULT_BEARER_SUPPORTED_BOOL} is false, then call setup would fail.
+ * <p>If dedicated bearer is not established within this time and if
+ * {@link #KEY_VOICE_ON_DEFAULT_BEARER_SUPPORTED_BOOL} is true, then the media is allowed
+ * on default bearer.
+ */
+ public static final String KEY_DEDICATED_BEARER_WAIT_TIMER_MILLIS_INT =
+ KEY_PREFIX + "dedicated_bearer_wait_timer_millis_int";
+
+ /** @hide */
+ @IntDef({
+ BASIC_SRVCC_SUPPORT,
+ ALERTING_SRVCC_SUPPORT,
+ PREALERTING_SRVCC_SUPPORT,
+ MIDCALL_SRVCC_SUPPORT
+ })
+
+ public @interface SrvccType {}
+
+ /**
+ * Indicates support for basic SRVCC, typically 1 active call
+ * as detailed in IR.92 Section A.3.
+ */
+ public static final int BASIC_SRVCC_SUPPORT = 0;
+
+ /**
+ * SRVCC access transfer for calls in alerting phase as per 3GPP 24.237
+ * and IR.64 Section 4.4.
+ * Media feature tag used: g.3gpp.srvcc-alerting.
+ */
+ public static final int ALERTING_SRVCC_SUPPORT = 1;
+
+ /**
+ * SRVCC access transfer for calls in pre-alerting phase as per 3GPP 24.237.
+ * Media feature tag used: g.3gpp.ps2cs-srvcc-orig-pre-alerting.
+ */
+ public static final int PREALERTING_SRVCC_SUPPORT = 2;
+
+ /**
+ * SRVCC access transfer for calls in mid-call phase as per 3GPP 24.237.
+ * and IR.64 Section 4.4.
+ * <p>This means UE supports the MSC server assisted mid-call feature.
+ * Media feature tag used: g.3gpp.mid-call.
+ */
+ public static final int MIDCALL_SRVCC_SUPPORT = 3;
+
+ /**
+ * List of different SRVCC types supported as defined in 3GPP 24.237.
+ *
+ * <p> Possible values are,
+ * {@link #BASIC_SRVCC_SUPPORT},
+ * {@link #ALERTING_SRVCC_SUPPORT},
+ * {@link #PREALERTING_SRVCC_SUPPORT},
+ * {@link #MIDCALL_SRVCC_SUPPORT}
+ *
+ * <p> Reference: IR.64, 3GPP 24.237, 3GPP 23.216
+ */
+ public static final String KEY_SRVCC_TYPE_INT_ARRAY =
+ KEY_PREFIX + "srvcc_type_int_array";
+
+ /**
+ * Specifies the ringing timer for Mobile terminated calls.
+ *
+ * <p>Ringing timer starts when the device sends SIP 180 Ringing in
+ * response to a received SIP INVITE. If Ringing timer expires,
+ * the device sends SIP 486 response.
+ */
+ public static final String KEY_RINGING_TIMER_MILLIS_INT =
+ KEY_PREFIX + "ringing_timer_millis_int";
+
+ /**
+ * Specifies the ringback timer for Mobile originated calls.
+ *
+ * <p>Ringback timer starts when the device receives SIP 180 Ringing
+ * in response to its SIP INVITE. If Ringback timer expires,
+ * the device sends SIP CANCEL.
+ */
+ public static final String KEY_RINGBACK_TIMER_MILLIS_INT =
+ KEY_PREFIX + "ringback_timer_millis_int";
+
+ /**
+ * Specifies the timeout value for RTP inactivity for audio media.
+ * <p>On timer expiry, call will end.
+ * See {@link #KEY_AUDIO_INACTIVITY_CALL_END_REASONS_INT_ARRAY} for more
+ * details.
+ * <p> Value of 0 means this timer is not enabled.
+ */
+ public static final String KEY_AUDIO_RTP_INACTIVITY_TIMER_MILLIS_INT =
+ KEY_PREFIX + "audio_rtp_inactivity_timer_millis_int";
+
+ /**
+ * Specifies the timeout value for RTCP inactivity for audio media.
+ * <p>On timer expiry, call will end.
+ * See {@link #KEY_AUDIO_INACTIVITY_CALL_END_REASONS_INT_ARRAY} for more
+ * details.
+ * <p> Value of 0 means this timer is not enabled.
+ */
+ public static final String KEY_AUDIO_RTCP_INACTIVITY_TIMER_MILLIS_INT =
+ KEY_PREFIX + "audio_rtcp_inactivity_timer_millis_int";
+
+ /**
+ * Used to specify the conference factory URI.
+ *
+ * <p>If this is empty, then conference URI is generated from MCC/MNC as
+ * specified in clause 13.10 of 3GPP 23.003.
+ */
+ public static final String KEY_CONFERENCE_FACTORY_URI_STRING =
+ KEY_PREFIX + "conference_factory_uri_string";
+
+ /** @hide */
+ @IntDef({
+ SESSION_REFRESH_METHOD_INVITE,
+ SESSION_REFRESH_METHOD_UPDATE_PREFERRED
+ })
+
+ public @interface SessionRefreshMethod {}
+
+ /**
+ * SIP INVITE is used for Session Refresh
+ */
+ public static final int SESSION_REFRESH_METHOD_INVITE = 0;
+
+ /**
+ * Both SIP INVITE and UPDATE are used for session refresh.
+ *
+ * <p>SIP UPDATE will be used if UPDATE is in 'Allow' header.
+ * If UPDATE is not in 'Allow' header, then INVITE will be used.
+ */
+ public static final int SESSION_REFRESH_METHOD_UPDATE_PREFERRED = 1;
+
+ /**
+ * This is used to specify the method used for session refresh.
+ *
+ * <p>Possible values are,
+ * {@link #SESSION_REFRESH_METHOD_INVITE},
+ * {@link #SESSION_REFRESH_METHOD_UPDATE_PREFERRED}
+ */
+ public static final String KEY_SESSION_REFRESH_METHOD_INT =
+ KEY_PREFIX + "session_refresh_method_int";
+
+ /**
+ * Flag specifying whether the 'From' header field is used for determination of
+ * the originating party identity in Originating Identification Presentation(OIP)
+ * service.
+ *
+ * <p>If {@code true}: Indicates that the 'From' header field is used for
+ * determination of the originating party identity in OIP.
+ * {@code false} otherwise.
+ */
+ public static final String KEY_OIP_SOURCE_FROM_HEADER_BOOL =
+ KEY_PREFIX + "oip_source_from_header_bool";
+
+ /**
+ * Specifies the timer value for INVITE to the first 1xx response
+ * (including 100 trying). If no response is received at timer expiry,
+ * call is redialed over CS.
+ *
+ * <p> Reference: 24.173 Table L.1
+ */
+ public static final String KEY_MO_CALL_REQUEST_TIMEOUT_MILLIS_INT =
+ KEY_PREFIX + "mo_call_request_timeout_millis_int";
+
+ /**
+ * List of various reasons of media inactivity for which
+ * voice/emergency call will end.
+ *
+ * <p>Possible values are,
+ * {@link Ims#RTCP_INACTIVITY_ON_HOLD},
+ * {@link Ims#RTCP_INACTIVITY_ON_CONNECTED},
+ * {@link Ims#RTP_INACTIVITY_ON_CONNECTED}
+ * {@link Ims#E911_RTCP_INACTIVITY_ON_CONNECTED},
+ * {@link Ims#E911_RTP_INACTIVITY_ON_CONNECTED}
+ */
+ public static final String KEY_AUDIO_INACTIVITY_CALL_END_REASONS_INT_ARRAY =
+ KEY_PREFIX + "audio_inactivity_call_end_reasons_int_array";
+
+ /**
+ * Specifies the AS (Application Specific) SDP modifier for audio media.
+ *
+ * <p>This value is expressed in kilobits per second.
+ * Reference: RFC 3556 Section 2.
+ */
+ public static final String KEY_AUDIO_AS_BANDWIDTH_KBPS_INT =
+ KEY_PREFIX + "audio_as_bandwidth_kbps_int";
+
+ /**
+ * Specifies the RS SDP modifier for audio media. This indicates the RTCP
+ * bandwidth allocated to active data senders for audio media.
+ *
+ * <p>This value is expressed in bits per second.
+ * Reference: RFC 3556 Section 2.
+ */
+ public static final String KEY_AUDIO_RS_BANDWIDTH_BPS_INT =
+ KEY_PREFIX + "audio_rs_bandwidth_bps_int";
+
+ /**
+ * Specifies the RR SDP modifier for audio media. This indicates the RTCP
+ * bandwidth allocated to receivers for audio media.
+ *
+ * <p>This value is expressed in bits per second.
+ * Reference: RFC 3556 Section 2.
+ */
+ public static final String KEY_AUDIO_RR_BANDWIDTH_BPS_INT =
+ KEY_PREFIX + "audio_rr_bandwidth_bps_int";
+
+ /**
+ * Specifies the Audio Codec capability. This contains a list of payload types
+ * representing different audio codec instances.
+ *
+ * <p> The priority of the codecs is EVS, AMRWB, AMRNB, DTMF WB, DTMF NB
+ * from highest to lowest. In each individual codec, the priority is determined
+ * by the order of the payload types from highest to lowest.
+ *
+ * <p>Possible keys in this bundle are,
+ * <UL>
+ * <LI>{@link #KEY_EVS_PAYLOAD_TYPE_INT_ARRAY}</LI>
+ * <LI>{@link #KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY}</LI>
+ * <LI>{@link #KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY}</LI>
+ * <LI>{@link #KEY_DTMFWB_PAYLOAD_TYPE_INT_ARRAY}</LI>
+ * <LI>{@link #KEY_DTMFNB_PAYLOAD_TYPE_INT_ARRAY}</LI>
+ * </UL>
+ * <p>To specify payload descriptions for each of the audio payload types, see
+ * <UL>
+ * <LI>{@link #KEY_EVS_PAYLOAD_DESCRIPTION_BUNDLE}</LI>
+ * <LI>{@link #KEY_AMRNB_PAYLOAD_DESCRIPTION_BUNDLE}</LI>
+ * <LI>{@link #KEY_AMRWB_PAYLOAD_DESCRIPTION_BUNDLE}</LI>
+ * </UL>
+ */
+ public static final String KEY_AUDIO_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE =
+ KEY_PREFIX + "audio_codec_capability_payload_types_bundle";
+
+ /**
+ * A list of integers representing the different payload types
+ * in EVS codec in priority order from highest to lowest.
+ * <p>Payload type is an integer in dynamic payload type range 96-127
+ * as per RFC RFC 3551 Section 6.
+ */
+ public static final String KEY_EVS_PAYLOAD_TYPE_INT_ARRAY =
+ KEY_PREFIX + "evs_payload_type_int_array";
+
+ /**
+ * A list of integers representing the different payload types
+ * in AMR-WB codec in priority order from highest to lowest.
+ * <p>Payload type is an integer in dynamic payload type range 96-127
+ * as per RFC RFC 3551 Section 6.
+ */
+ public static final String KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY =
+ KEY_PREFIX + "amrwb_payload_type_int_array";
+
+ /**
+ * A list of integers representing the different payload types
+ * in AMR-NB codec in priority order from highest to lowest.
+ * <p>Payload type is an integer in dynamic payload type range 96-127
+ * as per RFC RFC 3551 Section 6.
+ */
+ public static final String KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY =
+ KEY_PREFIX + "amrnb_payload_type_int_array";
+
+ /**
+ * A list of integers representing the different payload types
+ * in DTMF WB codec in priority order from highest to lowest.
+ * <p>Payload type is an integer in dynamic payload type range 96-127
+ * as per RFC RFC 3551 Section 6.
+ */
+ public static final String KEY_DTMFWB_PAYLOAD_TYPE_INT_ARRAY =
+ KEY_PREFIX + "dtmfwb_payload_type_int_array";
+
+ /**
+ * A list of integers representing the different payload types
+ * in DTMF NB codec in priority order from highest to lowest.
+ * <p>Payload type is an integer in dynamic payload type range 96-127
+ * as per RFC RFC 3551 Section 6.
+ */
+ public static final String KEY_DTMFNB_PAYLOAD_TYPE_INT_ARRAY =
+ KEY_PREFIX + "dtmfnb_payload_type_int_array";
+
+ /** @hide */
+ @IntDef({
+ BANDWIDTH_EFFICIENT,
+ OCTET_ALIGNED
+ })
+
+ public @interface AmrPayloadFormat {}
+
+ /** AMR NB/WB Payload format is bandwidth-efficient. */
+ public static final int BANDWIDTH_EFFICIENT = 0;
+
+ /** AMR NB/WB Payload format is octet-aligned. */
+ public static final int OCTET_ALIGNED = 1;
+
+ /**
+ * Specifies the payload format of the AMR-NB/AMR-WB codec.
+ *
+ * <p>Possible values are,
+ * {@link #BANDWIDTH_EFFICIENT},
+ * {@link #OCTET_ALIGNED}
+
+ * <p>If value is not specified, payload format is
+ * {@link #BANDWIDTH_EFFICIENT}.
+ *
+ * <p>Reference: RFC 4867 Section 8.1.
+ */
+ public static final String KEY_AMR_CODEC_ATTRIBUTE_PAYLOAD_FORMAT_INT =
+ KEY_PREFIX + "amr_codec_attribute_payload_format_int";
+
+ /**
+ * Restricts the active mode set to a subset of all modes in the codec.
+ *
+ * <p>This attribute is optional. If value is set, then session mode
+ * set is restricted to the modes specified in this list. If this value
+ * is not specified, then all available modes in the codec are allowed.
+ * This attribute is applicable for AMR-WB, AMR-NB,
+ * and EVS codec (operating in AMR-WB IO Mode).
+ *
+ * <p>Possible values are subset of,
+ * [0,1,2,3,4,5,6,7,8] - AMRWB with the modes representing nine speech codec modes
+ * with bit rates of 6.6, 8.85, 12.65, 14.25, 15.85, 18.25, 19.85, 23.05, 23.85 kbps.
+ * [0,1,2,3,4,5,6,7] - AMRNB with the modes representing eight speech codec modes
+ * with bit rates of 4.75, 5.15, 5.90, 6.70, 7.40, 7.95, 10.2, 12.2 kbps.
+ *
+ * <p>If value is not specified, then it means device supports all
+ * modes in the codec but not included in SDP.
+ *
+ * <p>Reference: RFC 4867 Section 8.1, 3GPP 26.445 A.3.1
+ */
+ public static final String KEY_AMR_CODEC_ATTRIBUTE_MODESET_INT_ARRAY =
+ KEY_PREFIX + "amr_codec_attribute_modeset_int_array";
+
+ /**
+ * Specifies the codec attributes of different payload types in
+ * the AMR NarrowBand (AMR-NB) codec.
+ *
+ * <p> The keys in this bundle are payload types specified
+ * in {@link #KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY}.
+ *
+ * <p>Codec attributes allowed as part of AMR-NB codec bundle are,
+ * <UL>
+ * <LI>{@link #KEY_AMR_CODEC_ATTRIBUTE_PAYLOAD_FORMAT_INT}</LI>
+ * <LI>{@link #KEY_AMR_CODEC_ATTRIBUTE_MODESET_INT_ARRAY}</LI>
+ * </UL>
+ *
+ * <p> If this bundle is not configured and AMRNB payload type is added
+ * in {@link #KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY}, then default
+ * values as in the individual codec attribute to be used
+ * for that payload type.
+ */
+ public static final String KEY_AMRNB_PAYLOAD_DESCRIPTION_BUNDLE =
+ KEY_PREFIX + "amrnb_payload_description_bundle";
+
+ /**
+ * Specifies the codec attributes of different payload types in
+ * the AMR WideBand (AMR-WB) codec.
+ *
+ * <p> The keys in this bundle are payload types specified
+ * in {@link #KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY}.
+ *
+ * <p>Codec attributes allowed as part of AMR-NB codec bundle are,
+ * <UL>
+ * <LI>{@link #KEY_AMR_CODEC_ATTRIBUTE_PAYLOAD_FORMAT_INT}</LI>
+ * <LI>{@link #KEY_AMR_CODEC_ATTRIBUTE_MODESET_INT_ARRAY}</LI>
+ * </UL>
+ *
+ * <p> If this bundle is not configured and AMRWB payload type is added
+ * in {@link #KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY}, then default
+ * values as in the individual codec attribute to be used
+ * for that payload type.
+ */
+ public static final String KEY_AMRWB_PAYLOAD_DESCRIPTION_BUNDLE =
+ KEY_PREFIX + "amrwb_payload_description_bundle";
+
+ /** @hide */
+ @IntDef({
+ EVS_OPERATIONAL_MODE_PRIMARY,
+ EVS_OPERATIONAL_MODE_AMRWB_IO
+ })
+
+ public @interface EvsOperationalMode {}
+
+ /** Indicates the EVS primary mode. 3GPP 26.445 Section 3.1 */
+ public static final int EVS_OPERATIONAL_MODE_PRIMARY = 0;
+
+ /** Indicates the EVS AMR-WB IO mode. 3GPP 26.445 Section 3.1 */
+ public static final int EVS_OPERATIONAL_MODE_AMRWB_IO = 1;
+
+ /**
+ * Specifies if the EVS mode used is EVS primary mode
+ * or EVS AMR-WB IO mode.
+ *
+ * <p>Possible values are,
+ * {@link #EVS_OPERATIONAL_MODE_PRIMARY},
+ * {@link #EVS_OPERATIONAL_MODE_AMRWB_IO}
+ *
+ * <p>If this is not present, then {@link #EVS_OPERATIONAL_MODE_PRIMARY} is used.
+ * <p>Reference: 3GPP 26.445 Section 3.1.
+ */
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_MODE_SWITCH_INT =
+ KEY_PREFIX + "evs_codec_attribute_mode_switch_int";
+
+ /** @hide */
+ @IntDef({
+ EVS_ENCODED_BW_TYPE_NB,
+ EVS_ENCODED_BW_TYPE_WB,
+ EVS_ENCODED_BW_TYPE_SWB,
+ EVS_ENCODED_BW_TYPE_FB,
+ EVS_ENCODED_BW_TYPE_NB_WB,
+ EVS_ENCODED_BW_TYPE_NB_WB_SWB,
+ EVS_ENCODED_BW_TYPE_NB_WB_SWB_FB,
+ EVS_ENCODED_BW_TYPE_WB_SWB,
+ EVS_ENCODED_BW_TYPE_WB_SWB_FB
+ })
+
+ public @interface EvsEncodedBwType {}
+
+ /**
+ * EVS encoded Bandwidth is Narrow Band (NB).
+ * Reference: 3GPP 26.441 Table 1.
+ */
+ public static final int EVS_ENCODED_BW_TYPE_NB = 0;
+
+ /**
+ * EVS encoded Bandwidth is Wide Band (WB).
+ * Reference: 3GPP 26.441 Table 1.
+ */
+ public static final int EVS_ENCODED_BW_TYPE_WB = 1;
+
+ /**
+ * EVS encoded Bandwidth is Super WideBand (SWB).
+ * Reference: 3GPP 26.441 Table 1.
+ */
+ public static final int EVS_ENCODED_BW_TYPE_SWB = 2;
+
+ /**
+ * EVS encoded Bandwidth is Full Band (FB).
+ * Reference: 3GPP 26.441 Table 1.
+ */
+ public static final int EVS_ENCODED_BW_TYPE_FB = 3;
+
+ /**
+ * EVS encoded Bandwidth is in the range NB,WB.
+ * Reference: 3GPP 26.441 Table 1.
+ */
+ public static final int EVS_ENCODED_BW_TYPE_NB_WB = 4;
+
+ /**
+ * EVS encoded Bandwidth is in the range NB,WB,SWB.
+ * Reference: 3GPP 26.441 Table 1.
+ */
+ public static final int EVS_ENCODED_BW_TYPE_NB_WB_SWB = 5;
+
+ /**
+ * EVS encoded Bandwidth is in the range NB,WB,SWB,FB.
+ * Reference: 3GPP 26.441 Table 1.
+ */
+ public static final int EVS_ENCODED_BW_TYPE_NB_WB_SWB_FB = 6;
+
+ /**
+ * EVS encoded Bandwidth is in the range WB,SWB.
+ * Reference: 3GPP 26.441 Table 1.
+ */
+ public static final int EVS_ENCODED_BW_TYPE_WB_SWB = 7;
+
+ /**
+ * EVS encoded Bandwidth is in the range WB,SWB,FB.
+ * Reference: 3GPP 26.441 Table 1.
+ */
+ public static final int EVS_ENCODED_BW_TYPE_WB_SWB_FB = 8;
+
+ /**
+ * Specifies the EVS codec encoding bandwidth options.
+ *
+ * Possible values are,
+ * {@link #EVS_ENCODED_BW_TYPE_NB},
+ * {@link #EVS_ENCODED_BW_TYPE_WB},
+ * {@link #EVS_ENCODED_BW_TYPE_SWB},
+ * {@link #EVS_ENCODED_BW_TYPE_FB},
+ * {@link #EVS_ENCODED_BW_TYPE_NB_WB},
+ * {@link #EVS_ENCODED_BW_TYPE_NB_WB_SWB},
+ * {@link #EVS_ENCODED_BW_TYPE_NB_WB_SWB_FB},
+ * {@link #EVS_ENCODED_BW_TYPE_WB_SWB},
+ * {@link #EVS_ENCODED_BW_TYPE_WB_SWB_FB}
+ *
+ * If this key is not specified, then the behavior is same as
+ * value {@link #EVS_ENCODED_BW_TYPE_NB_WB_SWB}
+ *
+ * <p>Reference: 3GPP 26.441 Table 1.
+ */
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_BANDWIDTH_INT =
+ KEY_PREFIX + "evs_codec_attribute_bandwidth_int";
+
+ /** @hide */
+ @IntDef({
+ EVS_PRIMARY_MODE_BITRATE_5_9_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_7_2_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_8_0_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_9_6_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_13_2_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_16_4_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_24_4_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_32_0_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_48_0_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_64_0_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_96_0_KBPS,
+ EVS_PRIMARY_MODE_BITRATE_128_0_KBPS
+ })
+
+ public @interface EvsPrimaryModeBitRate {}
+
+ /** EVS primary mode with bitrate 5.9 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_5_9_KBPS = 0;
+
+ /** EVS primary mode with bitrate 7.2 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_7_2_KBPS = 1;
+
+ /** EVS primary mode with bitrate 8.0 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_8_0_KBPS = 2;
+
+ /** EVS primary mode with bitrate 9.6 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_9_6_KBPS = 3;
+
+ /** EVS primary mode with bitrate 13.2 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_13_2_KBPS = 4;
+
+ /** EVS primary mode with bitrate 16.4 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_16_4_KBPS = 5;
+
+ /** EVS primary mode with bitrate 24.4 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_24_4_KBPS = 6;
+
+ /** EVS primary mode with bitrate 32.0 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_32_0_KBPS = 7;
+
+ /** EVS primary mode with bitrate 48.0 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_48_0_KBPS = 8;
+
+ /** EVS primary mode with bitrate 64.0 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_64_0_KBPS = 9;
+
+ /** EVS primary mode with bitrate 96.0 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_96_0_KBPS = 10;
+
+ /** EVS primary mode with bitrate 128.0 kbps */
+ public static final int EVS_PRIMARY_MODE_BITRATE_128_0_KBPS = 11;
+
+ /**
+ * Specifies the range of source codec bit-rate for EVS Primary mode
+ * in the session. This is expressed in kilobits per second and
+ * applicable for both the send and the receive directions.
+ *
+ * <p>The range is specified as integer aray of size 2,
+ * represented as [low, high], where low <= high
+ *
+ * <p>Possible values for low and high are,
+ * {@link #EVS_PRIMARY_MODE_BITRATE_5_9_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_7_2_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_8_0_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_9_6_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_13_2_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_16_4_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_24_4_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_32_0_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_48_0_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_64_0_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_96_0_KBPS},
+ * {@link #EVS_PRIMARY_MODE_BITRATE_128_0_KBPS}
+ *
+ * If this key is not specified, then the behavior is same as
+ * value {@link #EVS_PRIMARY_MODE_BITRATE_24_4_KBPS}
+ *
+ * <p>Reference: 3GPP 26.445 Section A.3.1
+ */
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_BITRATE_INT_ARRAY =
+ KEY_PREFIX + "evs_codec_attribute_bitrate_int_array";
+
+ /**
+ * Specifies the Channel aware mode (ch-aw-recv) for the receive direction.
+ * This is applicable for EVS codec.
+ *
+ * <p>Permissible values are -1, 0, 2, 3, 5, and 7.
+ * If this key is not specified, then the behavior is same as value 0
+ * (channel aware mode disabled).
+ * <p> If this key is configured, then device is expected to send
+ * this parameter in the SDP offer.
+ *
+ * <p>Reference: 3GPP TS 26.445 section 4.4.5, 3GPP 26.445 Section A.3.1
+ */
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_CH_AW_RECV_INT =
+ KEY_PREFIX + "evs_codec_attribute_ch_aw_recv_int";
+
+ /**
+ * Specifies whether to limit the session to header-full format.
+ * This applies to both directions in the session. This attribute
+ * is applicable for EVS codec.
+ *
+ * <p>Permissible values are 0, 1
+ * If hf-only is 1, only Header-Full format is used and hf-only is
+ * included in the SDP.
+ * <p>If hf-only is 0, both Compact and Header-Full formats are used
+ * and hf-only is included in the SDP.
+ * <p>If this key is not present, then both Compact
+ * and Header-Full formats are used and hf-only is not included in
+ * the SDP.
+ * <p> If this key is configured, then device is expected to send
+ * this parameter in the SDP offer if operator required it.
+ *
+ * <p>Reference: 3GPP 26.445 Section A.3.1.
+ */
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_HF_ONLY_INT =
+ KEY_PREFIX + "evs_codec_attribute_hf_only_int";
+
+ /**
+ * Specifies whether DTX (Discontinuous transmission) is enabled
+ * or not. This applies to both directions in the session.
+ * This attribute is applicable for EVS codec and can be used
+ * in both EVS Primary mode and EVS AMR-WB IO mode.
+ *
+ * <p>If {@code true}: Indicates DTX is enabled.
+ * If {@code false}: Indicates DTX is disabled.
+ *
+ * <p>If this is not present, then default value of {@code true}
+ * will apply.
+ * <p>Reference: 3GPP TS 26.445 Section A.3.1.
+ */
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_DTX_BOOL =
+ KEY_PREFIX + "evs_codec_attribute_dtx_bool";
+
+ /**
+ * This is used if further restriction is required on DTX in the
+ * receive direction. This attribute is applicable for EVS codec
+ * and can be used in both EVS Primary mode and EVS AMR-WB IO mode.
+ *
+ * <p> If this value is true or not present, then DTX setting is
+ * dependent on {@link #KEY_EVS_CODEC_ATTRIBUTE_DTX_BOOL}.
+ *
+ * <p> If this is not present, then default value of {@code true}
+ * will apply.
+ *
+ * <p>Reference: 3GPP TS 26.445 Section A.3.1.
+ */
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_DTX_RECV_BOOL =
+ KEY_PREFIX + "evs_codec_attribute_dtx_recv_bool";
+
+ /**
+ * Specifies the number of audio channels.
+ * If this is not present, then default value of 1 will apply.
+ *
+ * <p>Reference: RFC 3551
+ */
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_CHANNELS_INT =
+ KEY_PREFIX + "evs_codec_attribute_channels_int";
+
+ /**
+ * Indicates whether the Codec Mode Request (CMR) is supported
+ * for the session.
+ * This attribute is applicable for EVS codec in Primary Mode only.
+ *
+ * <p>Possible values are -1, 0, 1. If this key is not present,
+ * then behavior as per value 0 is applicable.
+ *
+ * <p>Reference: 3GPP 26.445 Section A.3.1, 3GPP 26.114 Table 6.2a
+ */
+ public static final String KEY_EVS_CODEC_ATTRIBUTE_CMR_INT =
+ KEY_PREFIX + "codec_attribute_cmr_int";
+
+ /**
+ * Specifies the number of frame-blocks. This indicates the frame-block period
+ * at which codec mode changes are allowed for the sender. This attribute is
+ * applicable for EVS codec in AMR-WB IO mode and AMR-WB.
+ *
+ * <p>Possible values are 1, 2.
+ * If the key is not present, behavior as per value 1 is applicable and this
+ * parameter is not included in SDP.
+ *
+ * <p>Reference: RFC 4867 Section 8.1.
+ */
+ public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_PERIOD_INT =
+ KEY_PREFIX + "codec_attribute_mode_change_period_int";
+
+ /**
+ * Specifies if the client is capable to transmit with a restricted mode
+ * change period. This attribute is applicable for EVS codec in
+ * AMR-WB IO mode and AMR-WB.
+ *
+ * <p>Possible values are 1, 2. If this key is not present,
+ * then behavior as per value 1 is applicable and this
+ * parameter is not included in SDP.
+ *
+ * <p>Reference: RFC 4867 Section 8.1.
+ */
+ public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_CAPABILITY_INT =
+ KEY_PREFIX + "codec_attribute_mode_change_capability_int";
+
+ /**
+ * Specifies the allowed mode changes for the sender in the active mode set.
+ * This attribute is applicable for EVS codec in AMR-WB IO mode
+ * and AMR-WB.
+ *
+ * <p>Possible values are 0, 1. If value is 1, then the sender should only
+ * perform mode changes to the neighboring modes in the active codec mode set.
+ * If value is 0, then mode changes between any two modes
+ * in the active codec mode set is allowed.
+ * If the key is not present, behavior as per value 0 is applicable and this
+ * parameter is not included in SDP.
+ *
+ * <p>Reference: RFC 4867 Section 8.1.
+ */
+ public static final String KEY_CODEC_ATTRIBUTE_MODE_CHANGE_NEIGHBOR_INT =
+ KEY_PREFIX + "codec_attribute_mode_change_neighbor_int";
+
+ /**
+ * Specifies the codec attributes of different payload types in
+ * the EVS codec.
+ *
+ * <p> The keys in this bundle are payload types specified
+ * in {@link #KEY_EVS_PAYLOAD_TYPE_INT_ARRAY}.
+ *
+ * <p>Codec attributes allowed as part of EVS codec are,
+ * <UL>
+ * <LI>{@link #KEY_EVS_CODEC_ATTRIBUTE_BANDWIDTH_INT}</LI>
+ * <LI>{@link #KEY_EVS_CODEC_ATTRIBUTE_BITRATE_INT_ARRAY}</LI>
+ * <LI>{@link #KEY_EVS_CODEC_ATTRIBUTE_CH_AW_RECV_INT}</LI>
+ * <LI>{@link #KEY_EVS_CODEC_ATTRIBUTE_HF_ONLY_INT}</LI>
+ * <LI>{@link #KEY_EVS_CODEC_ATTRIBUTE_DTX_BOOL}</LI>
+ * <LI>{@link #KEY_EVS_CODEC_ATTRIBUTE_DTX_RECV_BOOL}</LI>
+ * <LI>{@link #KEY_EVS_CODEC_ATTRIBUTE_MODE_SWITCH_INT}</LI>
+ * <LI>{@link #KEY_EVS_CODEC_ATTRIBUTE_CMR_INT}</LI>
+ * <LI>{@link #KEY_EVS_CODEC_ATTRIBUTE_CHANNELS_INT}</LI>
+ * <LI>{@link #KEY_CODEC_ATTRIBUTE_MODE_CHANGE_PERIOD_INT}</LI>
+ * <LI>{@link #KEY_CODEC_ATTRIBUTE_MODE_CHANGE_CAPABILITY_INT}</LI>
+ * <LI>{@link #KEY_CODEC_ATTRIBUTE_MODE_CHANGE_NEIGHBOR_INT}</LI>
+ * </UL>
+ */
+ public static final String KEY_EVS_PAYLOAD_DESCRIPTION_BUNDLE =
+ KEY_PREFIX + "evs_payload_description_bundle";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putBoolean(KEY_CARRIER_VOLTE_ROAMING_AVAILABLE_BOOL, true);
+ defaults.putBoolean(KEY_INCLUDE_CALLER_ID_SERVICE_CODES_IN_SIP_INVITE_BOOL, false);
+ defaults.putBoolean(KEY_MULTIENDPOINT_SUPPORTED_BOOL, false);
+ defaults.putBoolean(KEY_SESSION_TIMER_SUPPORTED_BOOL, true);
+ defaults.putBoolean(KEY_OIP_SOURCE_FROM_HEADER_BOOL, false);
+ defaults.putBoolean(KEY_PRACK_SUPPORTED_FOR_18X_BOOL, true);
+ defaults.putBoolean(KEY_VOICE_QOS_PRECONDITION_SUPPORTED_BOOL, true);
+ defaults.putBoolean(KEY_VOICE_ON_DEFAULT_BEARER_SUPPORTED_BOOL, false);
+
+ defaults.putInt(KEY_SESSION_REFRESHER_TYPE_INT, SESSION_REFRESHER_TYPE_UNKNOWN);
+ defaults.putInt(KEY_SESSION_REFRESH_METHOD_INT,
+ SESSION_REFRESH_METHOD_UPDATE_PREFERRED);
+ defaults.putInt(KEY_CONFERENCE_SUBSCRIBE_TYPE_INT,
+ CONFERENCE_SUBSCRIBE_TYPE_OUT_OF_DIALOG);
+ defaults.putInt(KEY_AUDIO_RTP_INACTIVITY_TIMER_MILLIS_INT, 20000);
+ defaults.putInt(KEY_AUDIO_RTCP_INACTIVITY_TIMER_MILLIS_INT, 20000);
+ defaults.putInt(KEY_DEDICATED_BEARER_WAIT_TIMER_MILLIS_INT, 8000);
+ defaults.putInt(KEY_RINGING_TIMER_MILLIS_INT, 90000);
+ defaults.putInt(KEY_RINGBACK_TIMER_MILLIS_INT, 90000);
+ defaults.putInt(KEY_MO_CALL_REQUEST_TIMEOUT_MILLIS_INT, 5000);
+ defaults.putInt(KEY_SESSION_EXPIRES_TIMER_SEC_INT, 1800);
+ defaults.putInt(KEY_MINIMUM_SESSION_EXPIRES_TIMER_SEC_INT, 90);
+ defaults.putInt(KEY_AUDIO_AS_BANDWIDTH_KBPS_INT, 41);
+ defaults.putInt(KEY_AUDIO_RS_BANDWIDTH_BPS_INT, 600);
+ defaults.putInt(KEY_AUDIO_RR_BANDWIDTH_BPS_INT, 2000);
+
+ defaults.putIntArray(
+ KEY_AUDIO_INACTIVITY_CALL_END_REASONS_INT_ARRAY,
+ new int[] {
+ Ims.RTCP_INACTIVITY_ON_CONNECTED,
+ Ims.RTP_INACTIVITY_ON_CONNECTED
+ });
+
+ defaults.putIntArray(
+ KEY_SRVCC_TYPE_INT_ARRAY,
+ new int[] {
+ BASIC_SRVCC_SUPPORT,
+ ALERTING_SRVCC_SUPPORT,
+ PREALERTING_SRVCC_SUPPORT,
+ MIDCALL_SRVCC_SUPPORT
+ });
+
+ defaults.putString(KEY_CONFERENCE_FACTORY_URI_STRING, "");
+
+ PersistableBundle audio_codec_capability_payload_types = new PersistableBundle();
+
+ audio_codec_capability_payload_types.putIntArray(
+ KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY,
+ new int[] { 97, 98 });
+
+ audio_codec_capability_payload_types.putIntArray(
+ KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY,
+ new int[] { 99, 100 });
+
+ audio_codec_capability_payload_types.putIntArray(
+ KEY_DTMFWB_PAYLOAD_TYPE_INT_ARRAY,
+ new int[] { 101 });
+
+ audio_codec_capability_payload_types.putIntArray(
+ KEY_DTMFNB_PAYLOAD_TYPE_INT_ARRAY,
+ new int[] { 102 });
+
+ defaults.putPersistableBundle(
+ KEY_AUDIO_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE,
+ audio_codec_capability_payload_types);
+
+ /* Setting defaults for AMRWB */
+ PersistableBundle all_amrwb_payload_bundles = new PersistableBundle();
+ PersistableBundle amrwb_bundle_instance1 = new PersistableBundle();
+
+ all_amrwb_payload_bundles.putPersistableBundle(
+ "97", /* Same value of payload type as in KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY */
+ amrwb_bundle_instance1);
+
+ PersistableBundle amrwb_bundle_instance2 = new PersistableBundle();
+
+ amrwb_bundle_instance2.putInt(KEY_AMR_CODEC_ATTRIBUTE_PAYLOAD_FORMAT_INT,
+ OCTET_ALIGNED);
+
+ all_amrwb_payload_bundles.putPersistableBundle(
+ "98", /* Same value of payload type as in KEY_AMRWB_PAYLOAD_TYPE_INT_ARRAY */
+ amrwb_bundle_instance2);
+
+ defaults.putPersistableBundle(
+ KEY_AMRWB_PAYLOAD_DESCRIPTION_BUNDLE,
+ all_amrwb_payload_bundles);
+
+ /* Setting defaults for AMRNB */
+ PersistableBundle all_amrnb_payload_bundles = new PersistableBundle();
+ PersistableBundle amrnb_bundle_instance1 = new PersistableBundle();
+
+ all_amrnb_payload_bundles.putPersistableBundle(
+ "99", /* Same value of payload type as in KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY */
+ amrnb_bundle_instance1);
+
+ PersistableBundle amrnb_bundle_instance2 = new PersistableBundle();
+
+ amrnb_bundle_instance2.putInt(KEY_AMR_CODEC_ATTRIBUTE_PAYLOAD_FORMAT_INT,
+ OCTET_ALIGNED);
+
+ all_amrnb_payload_bundles.putPersistableBundle(
+ "100", /* Same value of payload type as in KEY_AMRNB_PAYLOAD_TYPE_INT_ARRAY */
+ amrnb_bundle_instance2);
+
+ defaults.putPersistableBundle(
+ KEY_AMRNB_PAYLOAD_DESCRIPTION_BUNDLE,
+ all_amrnb_payload_bundles);
+
+ return defaults;
+ }
+ }
+
+ /**
+ * IMS SMS configs. This groups the configs specific for SMS over IMS
+ */
+ public static final class ImsSms {
+ private ImsSms() {}
+
+ /** Prefix of all imssms.KEY_* constants. */
+ public static final String KEY_PREFIX = "imssms.";
+
+ /**
+ * Flag specifying if SMS over IMS support is available or not.
+ *
+ * <p>If {@code true}: SMS over IMS support available.
+ * {@code false}: otherwise.
+ */
+ public static final String KEY_SMS_OVER_IMS_SUPPORTED_BOOL =
+ KEY_PREFIX + "sms_over_ims_supported_bool";
+
+ /**
+ * Flag specifying whether to allow SMS CSFB in case of
+ * SMS over PS failure.
+ *
+ * <p>If {@code true}: allow SMS CSFB in case of SMS over PS failure.
+ * {@code false} otherwise.
+ */
+ public static final String KEY_SMS_CSFB_RETRY_ON_FAILURE_BOOL =
+ KEY_PREFIX + "sms_csfb_retry_on_failure_bool";
+
+ /** @hide */
+ @IntDef({
+ SMS_FORMAT_3GPP,
+ SMS_FORMAT_3GPP2
+ })
+
+ public @interface SmsFormat {}
+
+ /** SMS format is 3GPP. */
+ public static final int SMS_FORMAT_3GPP = 0;
+
+ /** SMS format is 3GPP2. */
+ public static final int SMS_FORMAT_3GPP2 = 1;
+
+ /**
+ * Specifies the SMS over IMS format.
+ *
+ * <p>Possible values are,
+ * {@link #SMS_FORMAT_3GPP},
+ * {@link #SMS_FORMAT_3GPP2}
+ */
+ public static final String KEY_SMS_OVER_IMS_FORMAT_INT =
+ KEY_PREFIX + "sms_over_ims_format_int";
+
+ /**
+ * List of different RAT technologies on which SMS over IMS
+ * is supported.
+ *
+ * <p>Possible values are,
+ * {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#IWLAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#UTRAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#GERAN}
+ */
+ public static final String KEY_SMS_OVER_IMS_SUPPORTED_RATS_INT_ARRAY =
+ KEY_PREFIX + "sms_over_ims_supported_rats_int_array";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putBoolean(KEY_SMS_OVER_IMS_SUPPORTED_BOOL, true);
+ defaults.putBoolean(KEY_SMS_CSFB_RETRY_ON_FAILURE_BOOL, true);
+
+ defaults.putInt(KEY_SMS_OVER_IMS_FORMAT_INT, SMS_FORMAT_3GPP);
+
+ defaults.putIntArray(
+ KEY_SMS_OVER_IMS_SUPPORTED_RATS_INT_ARRAY,
+ new int[] {
+ AccessNetworkType.EUTRAN,
+ AccessNetworkType.IWLAN
+ });
+
+ return defaults;
+ }
+ }
+
+ /**
+ * IMS RTT configs. This groups the configs specific for text media,
+ * RTT (Real Time Text).
+ */
+ public static final class ImsRtt {
+ private ImsRtt() {}
+
+ /** Prefix of all imsrtt.KEY_* constants. */
+ public static final String KEY_PREFIX = "imsrtt.";
+
+ /**
+ * Flag specifying whether text media is allowed on default bearer.
+ *
+ * <p>If {@code true}: text media can be sent on default bearer.
+ * {@code false} otherwise.
+ */
+ public static final String KEY_TEXT_ON_DEFAULT_BEARER_SUPPORTED_BOOL =
+ KEY_PREFIX + "text_on_default_bearer_supported_bool";
+
+ /**
+ * Flag specifying whether QoS preconditions are supported for text.
+ *
+ * <p>If {@code true}: QoS Preconditions are supported.
+ * {@code false} otherwise.
+ * <p>Reference: 3GPP TS 24.229
+ */
+ public static final String KEY_TEXT_QOS_PRECONDITION_SUPPORTED_BOOL =
+ KEY_PREFIX + "text_qos_precondition_supported_bool";
+
+ /**
+ * Specifies the AS (Application Specific) SDP modifier for text media.
+ *
+ * <p>Expressed in kilobits per second as per RFC 3556 Section 2.
+ */
+ public static final String KEY_TEXT_AS_BANDWIDTH_KBPS_INT =
+ KEY_PREFIX + "text_as_bandwidth_kbps_int";
+
+ /**
+ * Specifies the RS (RTCP bandwidth-Sender) SDP modifier for text media.
+ *
+ * <p>This indicates the RTCP bandwidth allocated to active data senders
+ * for text media.
+ *
+ * <p>Expressed in bits per second as per RFC 3556 Section 2.
+ */
+ public static final String KEY_TEXT_RS_BANDWIDTH_BPS_INT =
+ KEY_PREFIX + "text_rs_bandwidth_bps_int";
+
+ /**
+ * Specifies the RR (RTCP bandwidth-Receiver) SDP modifier for
+ * text media.
+ *
+ * <p>This indicates the RTCP bandwidth allocated to receivers
+ * for text media.
+ *
+ * <p>Expressed in bits per second as per RFC 3556 Section 2.
+ */
+ public static final String KEY_TEXT_RR_BANDWIDTH_BPS_INT =
+ KEY_PREFIX + "text_rr_bandwidth_bps_int";
+
+ /**
+ * List of various reasons for RTT call to end due to
+ * media inactivity.
+ *
+ * <p>Possible values are,
+ * <UL>
+ * <LI>{@link Ims#RTCP_INACTIVITY_ON_HOLD}</LI>
+ * <LI>{@link Ims#RTCP_INACTIVITY_ON_CONNECTED}</LI>
+ * <LI>{@link Ims#RTP_INACTIVITY_ON_CONNECTED}</LI>
+ * <LI>{@link Ims#E911_RTCP_INACTIVITY_ON_CONNECTED}</LI>
+ * <LI>{@link Ims#E911_RTP_INACTIVITY_ON_CONNECTED}</LI>
+ * </UL>
+ */
+ public static final String KEY_TEXT_INACTIVITY_CALL_END_REASONS_INT_ARRAY =
+ KEY_PREFIX + "text_inactivity_call_end_reasons_int_array";
+
+ /**
+ * Specifies the Text Codec capability.
+ *
+ * <p>Possible keys in this bundle are,
+ * <UL>
+ * <LI>{@link #KEY_T140_PAYLOAD_TYPE_INT}</LI>
+ * <LI>{@link #KEY_RED_PAYLOAD_TYPE_INT}</LI>
+ * </UL>
+ */
+ public static final String KEY_TEXT_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE =
+ KEY_PREFIX + "text_codec_capability_payload_types_bundle";
+
+ /** Integer representing payload type for T140 codec.
+ * <p>Payload type is an integer in dynamic payload type range 96-127
+ * as per RFC RFC 3551 Section 6.
+ */
+ public static final String KEY_T140_PAYLOAD_TYPE_INT =
+ KEY_PREFIX + "t140_payload_type_int";
+
+ /** Integer representing payload type for RED/redundancy codec.
+ * <p>Payload type is an integer in dynamic payload type range 96-127
+ * as per RFC RFC 3551 Section 6.
+ */
+ public static final String KEY_RED_PAYLOAD_TYPE_INT =
+ KEY_PREFIX + "red_payload_type_int";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putBoolean(KEY_TEXT_ON_DEFAULT_BEARER_SUPPORTED_BOOL, false);
+ defaults.putBoolean(KEY_TEXT_QOS_PRECONDITION_SUPPORTED_BOOL, true);
+
+ defaults.putInt(KEY_TEXT_AS_BANDWIDTH_KBPS_INT, 4);
+ defaults.putInt(KEY_TEXT_RS_BANDWIDTH_BPS_INT, 100);
+ defaults.putInt(KEY_TEXT_RR_BANDWIDTH_BPS_INT, 300);
+
+ defaults.putIntArray(
+ KEY_TEXT_INACTIVITY_CALL_END_REASONS_INT_ARRAY,
+ new int[] {
+ Ims.RTCP_INACTIVITY_ON_CONNECTED,
+ Ims.RTP_INACTIVITY_ON_CONNECTED
+ });
+
+ PersistableBundle text_codec_capability_payload_types = new PersistableBundle();
+
+ text_codec_capability_payload_types.putInt(
+ KEY_RED_PAYLOAD_TYPE_INT,
+ 112);
+
+ text_codec_capability_payload_types.putInt(
+ KEY_T140_PAYLOAD_TYPE_INT,
+ 111);
+
+ defaults.putPersistableBundle(
+ KEY_TEXT_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE,
+ text_codec_capability_payload_types);
+
+ return defaults;
+ }
+ }
+
+ /**
+ * Emergency Call/E911. This groups the configs specific for emergency call
+ * over IMS.
+ *
+ * <p> Reference: 3GPP 24.229, 3GPP 23.167 Annex H, 3GPP 24.301.
+ */
+ public static final class ImsEmergency {
+ private ImsEmergency() {}
+
+ /** Prefix of all imsemergency.KEY_* constants. */
+ public static final String KEY_PREFIX = "imsemergency.";
+
+ /**
+ * Flag specifying whether UE would retry E911 call on
+ * IMS PDN if emergency PDN setup failed.
+ *
+ * <p>If {@code true}: Allow UE to retry emergency call on
+ * IMS PDN if emergency PDN setup failed.{@code false} otherwise.
+ */
+ public static final String KEY_RETRY_EMERGENCY_ON_IMS_PDN_BOOL =
+ KEY_PREFIX + "retry_emergency_on_ims_pdn_bool";
+
+ /**
+ * Flag specifying whether UE should enter Emergency CallBack Mode(ECBM)
+ * after E911 call is ended.
+ *
+ * <p>If {@code true}: Enter ECBM mode after E911 call is ended.
+ * {@code false} otherwise.
+ */
+ public static final String KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL =
+ KEY_PREFIX + "emergency_callback_mode_supported_bool";
+
+ /**
+ * Flag specifying whether QoS preconditions are supported for emergency
+ * call setup.
+ *
+ * <p>If {@code true}: QoS Preconditions are supported.
+ * {@code false} otherwise.
+ *
+ * <p>Reference: 3GPP TS 24.229
+ */
+ public static final String KEY_EMERGENCY_QOS_PRECONDITION_SUPPORTED_BOOL =
+ KEY_PREFIX + "emergency_qos_precondition_supported_bool";
+
+ /**
+ * List of different RAT technologies on which emergency call using IMS
+ * is supported.
+ *
+ * <p>Possible values are,
+ * {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#IWLAN}
+ */
+ public static final String KEY_EMERGENCY_OVER_IMS_SUPPORTED_RATS_INT_ARRAY =
+ KEY_PREFIX + "emergency_over_ims_supported_rats_int_array";
+
+ /**
+ * Specifies the maximum time from deciding that an emergency service is to
+ * be established until completion of the emergency registration procedure.
+ * Upon timer expiry, the UE considers the emergency REGISTER request or
+ * the emergency call attempt as failed.
+ */
+ public static final String KEY_EMERGENCY_REGISTRATION_TIMER_MILLIS_INT =
+ KEY_PREFIX + "emergency_registration_timer_millis_int";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putBoolean(KEY_RETRY_EMERGENCY_ON_IMS_PDN_BOOL, false);
+ defaults.putBoolean(KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL, false);
+ defaults.putBoolean(KEY_EMERGENCY_QOS_PRECONDITION_SUPPORTED_BOOL, true);
+
+ defaults.putIntArray(
+ KEY_EMERGENCY_OVER_IMS_SUPPORTED_RATS_INT_ARRAY,
+ new int[] {
+ AccessNetworkType.EUTRAN,
+ AccessNetworkType.IWLAN
+ });
+
+ defaults.putInt(KEY_EMERGENCY_REGISTRATION_TIMER_MILLIS_INT, 20000);
+
+ return defaults;
+ }
+ }
+
+ /**
+ * IMS Video Telephony configs. This groups the configs that are specific for video call.
+ */
+ public static final class ImsVt {
+ private ImsVt() {}
+
+ /** Prefix of all imsvt.KEY_* constants. */
+ public static final String KEY_PREFIX = "imsvt.";
+
+ /**
+ * Flag specifying whether video media is allowed on default bearer.
+ *
+ * <p>If {@code true}: video media can be sent on default bearer.
+ * {@code false} otherwise.
+ */
+ public static final String KEY_VIDEO_ON_DEFAULT_BEARER_SUPPORTED_BOOL =
+ KEY_PREFIX + "video_on_default_bearer_supported_bool";
+
+ /**
+ * Specifies the timeout value for no video RTP packets received.
+ * <p>On timer expiry, VT call can downgrade to voice call or end
+ * or continue depending on the operator requirement.
+ */
+ public static final String KEY_VIDEO_RTP_INACTIVITY_TIMER_MILLIS_INT =
+ KEY_PREFIX + "video_rtp_inactivity_timer_millis_int";
+
+ /**
+ * Specifies the timeout value for no video RTCP packets received.
+ * <p>On timer expiry, VT call can downgrade to voice call or end
+ * or continue depending on the operator requirement.
+ */
+ public static final String KEY_VIDEO_RTCP_INACTIVITY_TIMER_MILLIS_INT =
+ KEY_PREFIX + "video_rtcp_inactivity_timer_millis_int";
+
+ /**
+ * Specifies the AS (Application Specific) SDP modifier for video media.
+ *
+ * <p>Expressed in kilobits per second as per RFC 3556 Section 2.
+ */
+ public static final String KEY_VIDEO_AS_BANDWIDTH_KBPS_INT =
+ KEY_PREFIX + "video_as_bandwidth_kbps_int";
+
+ /**
+ * Specifies the RS (RTCP bandwidth-Sender) SDP modifier for video media.
+ *
+ * <p>This indicates the RTCP bandwidth allocated to active data senders
+ * for video media.
+ *
+ * <p>Expressed in bits per second as per RFC 3556 Section 2.
+ */
+ public static final String KEY_VIDEO_RS_BANDWIDTH_BPS_INT =
+ KEY_PREFIX + "video_rs_bandwidth_bps_int";
+
+ /**
+ * Specifies the RR (RTCP bandwidth-Receiver) SDP modifier
+ * for video media.
+ *
+ * <p>This indicates the RTCP bandwidth allocated to receivers
+ * for video media.
+ *
+ * <p>Expressed in bits per second as per RFC 3556 Section 2.
+ */
+ public static final String KEY_VIDEO_RR_BANDWIDTH_BPS_INT =
+ KEY_PREFIX + "video_rr_bandwidth_bps_int";
+
+ /**
+ * Specifies the differentiated services code point (DSCP) value
+ * for Video RTP.
+ *
+ * <p>Reference: RFC 4594 Section 1.4.4
+ */
+ public static final String KEY_VIDEO_RTP_DSCP_INT =
+ KEY_PREFIX + "video_rtp_dscp_int";
+
+ /**
+ * Flag specifying whether QoS preconditions are supported for Video.
+ *
+ * <p>If {@code true}: QoS Preconditions are supported.
+ * {@code false} otherwise.
+ * <p>Reference: 3GPP TS 24.229
+ */
+ public static final String KEY_VIDEO_QOS_PRECONDITION_SUPPORTED_BOOL =
+ KEY_PREFIX + "video_qos_precondition_supported_bool";
+
+ /**
+ * Specifies the Video Codec capability. This contains a list of
+ * payload types representing different Video codec instances.
+
+ * <p>Possible key(s) in this bundle are,
+ * <UL>
+ * <LI>{@link #KEY_H264_PAYLOAD_TYPE_INT_ARRAY}</LI>
+ * </UL>
+ * <p>To specify payload descriptions for each of the payload types, see
+ * <UL>
+ * <LI>{@link #KEY_H264_PAYLOAD_DESCRIPTION_BUNDLE}</LI>
+ * </UL>
+ */
+ public static final String KEY_VIDEO_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE =
+ KEY_PREFIX + "video_codec_capability_payload_types_bundle";
+
+ /**
+ * A list of integers representing the different payload types
+ * in H264 video codec in priority order from highest to lowest.
+ * <p>Payload type is an integer in dynamic payload type range 96-127
+ * as per RFC RFC 3551 Section 6.
+ */
+ public static final String KEY_H264_PAYLOAD_TYPE_INT_ARRAY =
+ KEY_PREFIX + "h264_payload_type_int_array";
+
+ /**
+ * Specifies the codec attributes of different payload types
+ * representing H264 video codec instances.
+ *
+ * <p> The allowed payload types of the video codecs are specified in,
+ * {@link #KEY_H264_PAYLOAD_TYPE_INT_ARRAY}.
+ *
+ * <p>Codec attributes allowed as part of H264 codec bundle are,
+ * <UL>
+ * <LI>{@link #KEY_H264_VIDEO_CODEC_ATTRIBUTE_PROFILE_LEVEL_ID_STRING}</LI>
+ * <LI>{@link #KEY_VIDEO_CODEC_ATTRIBUTE_PACKETIZATION_MODE_INT}</LI>
+ * <LI>{@link #KEY_VIDEO_CODEC_ATTRIBUTE_FRAME_RATE_INT}</LI>
+ * <LI>{@link #KEY_VIDEO_CODEC_ATTRIBUTE_RESOLUTION_INT_ARRAY}</LI>
+ * </UL>
+ *
+ * <p>If this bundle is not configured and
+ * {@link #KEY_H264_PAYLOAD_TYPE_INT_ARRAY} is not empty,
+ * then default values as in the individual codec attributes to
+ * be used for that payload type.
+ * <p>If the codec attributes in a particular codec instance bundle
+ * is not valid together, then that codec instance should not be used.
+ */
+ public static final String KEY_H264_PAYLOAD_DESCRIPTION_BUNDLE =
+ KEY_PREFIX + "h264_payload_description_bundle";
+
+ /**
+ * Specifies the packetization mode of the video codec.
+ *
+ * <p>Permissible values are 0 (Single NAL unit mode),
+ * 1(Non-interleaved mode).
+ *
+ * <p>If this key is not specified or invalid, then the following
+ * default value to be used.
+ * <UL>
+ * <LI>For H264: 1(Non-interleaved mode)</LI>
+ * <UL>
+ *
+ * <p>Reference: RFC 6184 Section 5.4
+ */
+ public static final String KEY_VIDEO_CODEC_ATTRIBUTE_PACKETIZATION_MODE_INT =
+ KEY_PREFIX + "video_codec_attribute_packetization_mode_int";
+
+ /**
+ * Specifies the maximum frame rate the offerer wishes to receive.
+ * This gives the maximum video frame rate in frames/sec.
+ *
+ * <p>If this key is not specified or invalid, then the following
+ * default value to be used.
+ * <UL>
+ * <LI>For H264: 15 </LI>
+ * <UL>
+ * <p>Reference: RFC 4566 Section 6, 3GPP 26.114 Section 6.2.3.2
+ */
+ public static final String KEY_VIDEO_CODEC_ATTRIBUTE_FRAME_RATE_INT =
+ KEY_PREFIX + "video_codec_attribute_frame_rate_int";
+
+ /**
+ * Specifies the maximum resolution allowed for the video codec
+ * instance.
+ *
+ * <p>This is specified as an array of two integers, with
+ * index 0 : Width,
+ * index 1 : Height
+ *
+ * <p>If this key is not specified or invalid as per the video codec,
+ * then the following default value to be used.
+ * <UL>
+ * <LI>For H264: 240 (WIDTH) x 320 (HEIGHT) </LI>
+ * <UL>
+ * <p>Reference: RFC 4566 Section 6, 3GPP 26.114 Section 6.2.3.2
+ *
+ */
+ public static final String KEY_VIDEO_CODEC_ATTRIBUTE_RESOLUTION_INT_ARRAY =
+ KEY_PREFIX + "video_codec_attribute_resolution_int_array";
+
+ /**
+ * Specifies the profile level id of the H264 video codec.
+ * This value is represented as "profile-level-id" in the SDP offer
+ * as per RFC 6184 Section 8.1.
+ *
+ * <p>If this key is not specified or invalid as per the video codec,
+ * then default value of 42C00C to be used.
+ *
+ * <p>Reference: RFC 6184 Section 8.1, ITU-T Recommendation H.264
+ */
+ public static final String KEY_H264_VIDEO_CODEC_ATTRIBUTE_PROFILE_LEVEL_ID_STRING =
+ KEY_PREFIX + "h264_video_codec_attribute_profile_level_id_string";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putBoolean(KEY_VIDEO_ON_DEFAULT_BEARER_SUPPORTED_BOOL, false);
+ defaults.putBoolean(KEY_VIDEO_QOS_PRECONDITION_SUPPORTED_BOOL, true);
+
+ defaults.putInt(KEY_VIDEO_RTP_INACTIVITY_TIMER_MILLIS_INT, 0);
+ defaults.putInt(KEY_VIDEO_RTCP_INACTIVITY_TIMER_MILLIS_INT, 0);
+
+ defaults.putInt(KEY_VIDEO_AS_BANDWIDTH_KBPS_INT, 960);
+ defaults.putInt(KEY_VIDEO_RS_BANDWIDTH_BPS_INT, 8000);
+ defaults.putInt(KEY_VIDEO_RR_BANDWIDTH_BPS_INT, 6000);
+ defaults.putInt(KEY_VIDEO_RTP_DSCP_INT, 40);
+
+ PersistableBundle video_codec_capability_payload_types = new PersistableBundle();
+
+ video_codec_capability_payload_types.putIntArray(
+ KEY_H264_PAYLOAD_TYPE_INT_ARRAY,
+ new int[] { 99, 100 });
+
+ defaults.putPersistableBundle(
+ KEY_VIDEO_CODEC_CAPABILITY_PAYLOAD_TYPES_BUNDLE,
+ video_codec_capability_payload_types);
+
+ PersistableBundle all_h264_payload_bundles = new PersistableBundle();
+
+ /* Setting default codec attributes for individual H264 profiles*/
+
+ /* For H264 profile-level-id: 42C00C, frame rate:15, Resolution: 240x320 */
+ PersistableBundle h264_bundle_instance1 = new PersistableBundle();
+ all_h264_payload_bundles.putPersistableBundle(
+ "99", /* Same value of payload type as in KEY_H264_PAYLOAD_TYPE_INT_ARRAY */
+ h264_bundle_instance1);
+
+ /* For H264 profile-level-id: 42C00C, packetisation mode:0, frame rate:15,
+ * Resolution: 240x320 */
+ PersistableBundle h264_bundle_instance2 = new PersistableBundle();
+ h264_bundle_instance2.putInt(
+ KEY_VIDEO_CODEC_ATTRIBUTE_PACKETIZATION_MODE_INT,
+ 0);
+
+ all_h264_payload_bundles.putPersistableBundle(
+ "100", /* Same value of payload type as in KEY_H264_PAYLOAD_TYPE_INT_ARRAY */
+ h264_bundle_instance2);
+
+ defaults.putPersistableBundle(
+ KEY_H264_PAYLOAD_DESCRIPTION_BUNDLE,
+ all_h264_payload_bundles);
+
+ return defaults;
+ }
+ }
+
+ /**
+ * WiFi Calling. This groups the configs specific for Voice over WiFi/WFC call.
+ */
+ public static final class ImsWfc {
+ private ImsWfc() {}
+
+ /** Prefix of all imswfc.KEY_* constants. */
+ public static final String KEY_PREFIX = "imswfc.";
+
+ /**
+ * List of MDNs for which Geo-location PIDF XML with country info
+ * needs to included for normal calls involving short code.
+ */
+ public static final String KEY_PIDF_SHORT_CODE_STRING_ARRAY =
+ KEY_PREFIX + "pidf_short_code_string_array";
+
+ /**
+ * Flag specifying whether emergency call over VoWiFi is requested over
+ * emergency PDN or IMS PDN.
+ *
+ * <p>If {@code false}: E911 call uses IMS PDN for E911 call over VoWiFi.
+ * If {@code true}: E911 call uses Emergency PDN for E911 call over VoWiFi.
+ */
+ public static final String KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL =
+ KEY_PREFIX + "emergency_call_over_emergency_pdn_bool";
+
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+
+ defaults.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, false);
+ defaults.putStringArray(KEY_PIDF_SHORT_CODE_STRING_ARRAY, new String[] {});
+
+ return defaults;
+ }
+ }
+
+ /**
+ * IMS supplementary services configs. This groups the configs required for
+ * supplementary services (SS) like XCAP over UT,
+ * Unstructured Supplementary Service Data(USSD).
+ */
+ public static final class ImsSs {
+ private ImsSs() {}
+
+ /** Prefix of all imsss.KEY_* constants. */
+ public static final String KEY_PREFIX = "imsss.";
+
+ /**
+ * Flag that controls whether XCAP over UT status need to be
+ * dependent on IMS registration.
+ *
+ * <p>If {@code true}: XCAP over UT status need to be
+ * dependent on IMS registration.
+ * {@code false} otherwise.
+ */
+ public static final String KEY_UT_REQUIRES_IMS_REGISTRATION_BOOL =
+ KEY_PREFIX + "ut_requires_ims_registration_bool";
+
+ /**
+ * Flag that controls whether Circuit Switched Fallback (CSFB)
+ * option is available when XCAP over UT fails.
+ *
+ * <p>If {@code false}: XCAP over UT only with no CSFB option.
+ * If XCAP over UT fails, return error.
+ * if {@code true}, Use CSFB if XCAP over UT fails.
+ */
+ public static final String KEY_USE_CSFB_ON_XCAP_OVER_UT_FAILURE_BOOL =
+ KEY_PREFIX + "use_csfb_on_xcap_over_ut_failure_bool";
+
+ /**
+ * Flag that controls whether XCAP over UT is enabled or not
+ * when PS data is turned off.
+ *
+ * <p>If {@code true}: XCAP over UT is enabled when PS data is off.
+ * {@code false}: Otherwise.
+ *
+ * Reference: IR.92 Section 5.5.1
+ */
+ public static final String KEY_UT_SUPPORTED_WHEN_PS_DATA_OFF_BOOL =
+ KEY_PREFIX + "ut_supported_when_ps_data_off_bool";
+
+ /**
+ * Flag that controls whether network initiated USSD over IMS is
+ * supported by the UE.
+ *
+ * <p>If {@code true}: Support Available.{@code false}: Otherwise.
+ * Reference: 3GPP 24.390.
+ */
+ public static final String KEY_NETWORK_INITIATED_USSD_OVER_IMS_SUPPORTED_BOOL =
+ KEY_PREFIX + "network_initiated_ussd_over_ims_supported_bool";
+
+ /**
+ * Specifies the 'XCAP over UT' IP Type when device is
+ * on Home Network.
+ *
+ * <p>Possible values are,
+ * {@link ApnSetting#PROTOCOL_IPV4V6},
+ * {@link ApnSetting#PROTOCOL_IP},
+ * {@link ApnSetting#PROTOCOL_IPV6}
+ *
+ * If key is invalid or not configured, the default value
+ * {@link ApnSetting#PROTOCOL_IPV4V6} will apply.
+ */
+ public static final String KEY_UT_IPTYPE_HOME_INT =
+ KEY_PREFIX + "ut_iptype_home_int";
+
+ /**
+ * Specifies the 'XCAP over UT' IP Type when device is roaming.
+ *
+ * <p>Possible values are,
+ * {@link ApnSetting#PROTOCOL_IPV4V6},
+ * {@link ApnSetting#PROTOCOL_IP},
+ * {@link ApnSetting#PROTOCOL_IPV6}
+
+ * If key is invalid or not configured, the default value
+ * {@link ApnSetting#PROTOCOL_IPV4V6} will apply.
+ */
+ public static final String KEY_UT_IPTYPE_ROAMING_INT =
+ KEY_PREFIX + "ut_iptype_roaming_int";
+
+ /**
+ * Specifies the XCAP Application Server fully qualified domain name (FQDN).
+ * <p> Reference: 24.623 Section 5.2.3.
+ */
+ public static final String KEY_UT_AS_SERVER_FQDN_STRING =
+ KEY_PREFIX + "ut_as_server_fqdn_string";
+
+ /**
+ * Specifies the XCAP Application Server Remote port.
+ * As XCAP is a usage of HTTP, the default value is same as HTTP, i.e. 80.
+ */
+ public static final String KEY_UT_AS_SERVER_PORT_INT =
+ KEY_PREFIX + "ut_as_server_port_int";
+
+ /**
+ * Specifies the preferred transport to be used for XCAP over UT.
+ *
+ * <p>Possible values are,
+ * {@link Ims#PREFERRED_TRANSPORT_TCP},
+ * {@link Ims#PREFERRED_TRANSPORT_TLS}
+ *
+ * <p>If key is invalid or not configured, the default value
+ * {@link Ims#PREFERRED_TRANSPORT_TCP} will apply.
+ */
+ public static final String KEY_UT_TRANSPORT_TYPE_INT =
+ KEY_PREFIX + "ut_transport_type_int";
+
+ /** @hide */
+ @IntDef({
+ SUPPLEMENTARY_SERVICE_CW,
+ SUPPLEMENTARY_SERVICE_CF_ALL,
+ SUPPLEMENTARY_SERVICE_CF_CFU,
+ SUPPLEMENTARY_SERVICE_CF_ALL_CONDITONAL_FORWARDING,
+ SUPPLEMENTARY_SERVICE_CF_CFB,
+ SUPPLEMENTARY_SERVICE_CF_CFNRY,
+ SUPPLEMENTARY_SERVICE_CF_CFNRC,
+ SUPPLEMENTARY_SERVICE_CF_CFNL,
+ SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIP,
+ SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIP,
+ SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIR,
+ SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIR,
+ SUPPLEMENTARY_SERVICE_CB_ALL,
+ SUPPLEMENTARY_SERVICE_CB_OBS,
+ SUPPLEMENTARY_SERVICE_CB_BAOC,
+ SUPPLEMENTARY_SERVICE_CB_BOIC,
+ SUPPLEMENTARY_SERVICE_CB_BOIC_EXHC,
+ SUPPLEMENTARY_SERVICE_CB_IBS,
+ SUPPLEMENTARY_SERVICE_CB_BAIC,
+ SUPPLEMENTARY_SERVICE_CB_BIC_ROAM,
+ SUPPLEMENTARY_SERVICE_CB_ACR,
+ SUPPLEMENTARY_SERVICE_CB_BIL
+ })
+
+ public @interface SsType {}
+
+ /** Communication Waiting (CW) support as per 3GPP 24.615. */
+ public static final int SUPPLEMENTARY_SERVICE_CW = 0;
+
+ /**
+ * Call Diversion - All call forwarding support as per 3GPP 24.604.
+ *
+ * <p>This value is associated with MMI support service code 002
+ * as indicated in TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CF_ALL = 1;
+
+ /**
+ * Call Diversion - All Unconditional call forwarding support (CFU) as
+ * per 3GPP 24.604.
+ *
+ * <p>This value is associated with MMI support service code 21
+ * as indicated in TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CF_CFU = 2;
+
+ /**
+ * Call Diversion - All conditional call forwarding support as
+ * per 3GPP 24.604.
+ *
+ * <p>This value is associated with MMI support service code 004
+ * as indicated in TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CF_ALL_CONDITONAL_FORWARDING = 3;
+
+ /**
+ * Call Diversion - Call forwarding on mobile subscriber busy (CFB)
+ * support as per 3GPP 24.604.
+ *
+ * <p>This value is associated with MMI support service code 67
+ * as indicated in TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CF_CFB = 4;
+
+ /**
+ * Call Diversion - Call forwarding on no reply (CFNRY)
+ * support as per 3GPP 24.604.
+ *
+ * <p>This value is associated with MMI support service code 61
+ * as indicated in TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CF_CFNRY = 5;
+
+ /**
+ * Call Diversion - Call forwarding on mobile subscriber not reachable
+ * (CFNRC) support as per 3GPP 24.604.
+ *
+ * <p>This value is associated with MMI support service code 62
+ * as indicated in TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CF_CFNRC = 6;
+
+ /**
+ * Communication Forwarding on Not Logged-in (CFNL).
+ * support as per 3GPP 24.604 Section 4.2.1.7
+ *
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CF_CFNL = 7;
+
+ /**
+ * Originating Identification Presentation (OIP) support
+ * as per 3GPP 24.607.
+ *
+ */
+ public static final int SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIP = 8;
+
+ /**
+ * Terminating Identification Presentation (TIP) support
+ * as per 3GPP 24.608.
+ */
+ public static final int SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIP = 9;
+
+ /**
+ * Originating Identification Restriction (OIR) support
+ * as per 3GPP 24.607.
+ */
+ public static final int SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIR = 10;
+
+ /**
+ * Terminating Identification Restriction (TIR) support
+ * as per 3GPP 24.608.
+ */
+ public static final int SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIR = 11;
+
+ /**
+ * Call Barring - All barring services,
+ * This value is associated with MMI support service code 330
+ * as indicated TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_ALL = 12;
+
+ /**
+ * Call Barring - Outgoing barring services,
+ * This value is associated with MMI support service code 333
+ * as indicated TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_OBS = 13;
+
+ /**
+ * Call Barring - Barring of all outgoing calls (BAOC)
+ * support as per 3GPP TS 24.611.
+ *
+ * <p>This value is associated with MMI support service code 33
+ * as indicated TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_BAOC = 14;
+
+ /**
+ * Call Barring - Barring of outgoing international calls
+ * (BOIC) support as per 3GPP TS 24.611.
+ *
+ * <p>This value is associated with MMI support service code 331
+ * as indicated TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_BOIC = 15;
+
+ /**
+ * Call Barring - Barring of outgoing international calls
+ * except those directed to the home PLMN country (BOIC-EXHC) support
+ * as per 3GPP TS 24.611.
+ *
+ * <p>This value is associated with MMI support service code 332
+ * as indicated TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_BOIC_EXHC = 16;
+
+ /**
+ * Call Barring - Incoming barring services,
+ * This value is associated with MMI support service code 353
+ * as indicated TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_IBS = 17;
+
+ /**
+ * Call Barring - Barring of all incoming calls (BAIC)
+ * support as per 3GPP TS 24.611.
+ *
+ * <p>This value is associated with MMI support service code 35
+ * as indicated TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_BAIC = 18;
+
+ /**
+ * Call Barring - Barring of incoming calls when roaming outside
+ * the home PLMN country (BIC-ROAM) support as per 3GPP TS 24.611.
+ *
+ * <p>This value is associated with MMI support service code 351
+ * as indicated TS 22.030 Table B.1
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_BIC_ROAM = 19;
+
+ /**
+ * Call Barring - Anonymous Call Rejection/Barring of all anonymous
+ * incoming number support as per 3GPP TS 24.611.
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_ACR = 20;
+
+ /**
+ * Call Barring - Barring list of incoming numbers support.
+ */
+ public static final int SUPPLEMENTARY_SERVICE_CB_BIL = 21;
+
+ /**
+ * List of UT services that are Server based.
+ *
+ * <p>Possible values are,
+ * <UL>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CW}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CF_ALL}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CF_CFU}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CF_ALL_CONDITONAL_FORWARDING}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CF_CFB}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CF_CFNRY}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CF_CFNRC}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CF_CFNL}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIP}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIP}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIR}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIR}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_ALL}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_OBS}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_IBS}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_BAOC}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_BOIC}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_BOIC_EXHC}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_BAIC}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_BIC_ROAM}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_ACR}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CB_BIL}</LI>
+ * </UL>
+ */
+ public static final String KEY_UT_SERVER_BASED_SERVICES_INT_ARRAY =
+ KEY_PREFIX + "ut_server_based_services_int_array";
+
+ /**
+ * List of UT services that are terminal based.
+ *
+ * By default, all services are server based and defined in
+ * {@link #KEY_UT_SERVER_BASED_SERVICES_INT_ARRAY}.
+ * Adding here will override that service setting to terminal based.
+ *
+ * <p>Possible values are,
+ * <UL>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_CW}</LI>
+ * <LI>{@link #SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIR}</LI>
+ * </UL>
+ */
+ public static final String KEY_UT_TERMINAL_BASED_SERVICES_INT_ARRAY =
+ KEY_PREFIX + "ut_terminal_based_services_int_array";
+
+ /**
+ * List of different RAT technologies on which XCAP over UT
+ * is supported.
+ *
+ * <p>Possible values are,
+ * {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#IWLAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#UTRAN}
+ * {@link AccessNetworkConstants.AccessNetworkType#GERAN}
+ */
+ public static final String KEY_XCAP_OVER_UT_SUPPORTED_RATS_INT_ARRAY =
+ KEY_PREFIX + "xcap_over_ut_supported_rats_int_array";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putBoolean(KEY_UT_REQUIRES_IMS_REGISTRATION_BOOL, true);
+ defaults.putBoolean(KEY_USE_CSFB_ON_XCAP_OVER_UT_FAILURE_BOOL, true);
+ defaults.putBoolean(KEY_UT_SUPPORTED_WHEN_PS_DATA_OFF_BOOL, true);
+ defaults.putBoolean(KEY_NETWORK_INITIATED_USSD_OVER_IMS_SUPPORTED_BOOL, true);
+
+ defaults.putInt(KEY_UT_IPTYPE_HOME_INT, ApnSetting.PROTOCOL_IPV4V6);
+ defaults.putInt(KEY_UT_IPTYPE_ROAMING_INT, ApnSetting.PROTOCOL_IPV4V6);
+ defaults.putInt(KEY_UT_AS_SERVER_PORT_INT, 80);
+ defaults.putInt(KEY_UT_TRANSPORT_TYPE_INT, Ims.PREFERRED_TRANSPORT_TCP);
+
+ defaults.putIntArray(
+ KEY_UT_SERVER_BASED_SERVICES_INT_ARRAY,
+ new int[] {
+ SUPPLEMENTARY_SERVICE_CW,
+ SUPPLEMENTARY_SERVICE_CF_ALL,
+ SUPPLEMENTARY_SERVICE_CF_CFU,
+ SUPPLEMENTARY_SERVICE_CF_CFNRC,
+ SUPPLEMENTARY_SERVICE_CF_ALL_CONDITONAL_FORWARDING,
+ SUPPLEMENTARY_SERVICE_CF_CFB,
+ SUPPLEMENTARY_SERVICE_CF_CFNRY,
+ SUPPLEMENTARY_SERVICE_CF_CFNL,
+ SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIP,
+ SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIP,
+ SUPPLEMENTARY_SERVICE_IDENTIFICATION_OIR,
+ SUPPLEMENTARY_SERVICE_IDENTIFICATION_TIR,
+ SUPPLEMENTARY_SERVICE_CB_ALL,
+ SUPPLEMENTARY_SERVICE_CB_OBS,
+ SUPPLEMENTARY_SERVICE_CB_IBS,
+ SUPPLEMENTARY_SERVICE_CB_BAOC,
+ SUPPLEMENTARY_SERVICE_CB_BOIC,
+ SUPPLEMENTARY_SERVICE_CB_BOIC_EXHC,
+ SUPPLEMENTARY_SERVICE_CB_BAIC,
+ SUPPLEMENTARY_SERVICE_CB_BIC_ROAM,
+ SUPPLEMENTARY_SERVICE_CB_ACR,
+ SUPPLEMENTARY_SERVICE_CB_BIL
+ });
+ defaults.putIntArray(
+ KEY_UT_TERMINAL_BASED_SERVICES_INT_ARRAY,
+ new int[] {});
+
+ defaults.putIntArray(
+ KEY_XCAP_OVER_UT_SUPPORTED_RATS_INT_ARRAY,
+ new int[] {
+ AccessNetworkType.EUTRAN,
+ AccessNetworkType.IWLAN
+ });
+ defaults.putString(KEY_UT_AS_SERVER_FQDN_STRING, "");
+
+ return defaults;
+ }
+ }
+
+ /**
+ * This groups the BSF (BootStrapping Function) related configs.
+ * Reference: 3GPP TS 24.109.
+ */
+ public static final class Bsf {
+ private Bsf() {}
+
+ /** Prefix of all bsf.KEY_* constants. */
+ public static final String KEY_PREFIX = "bsf.";
+
+ /** Specifies the fully qualified domain name (FQDN) of BSF Server
+ * as per 3GPP 24.109.
+ */
+ public static final String KEY_BSF_SERVER_FQDN_STRING =
+ KEY_PREFIX + "bsf_server_fqdn_string";
+
+ /**
+ * Specifies the port number of the BSF server as per 3GPP 24.109.
+ * This is usually default port number of HTTP, i.e. 80.
+ */
+ public static final String KEY_BSF_SERVER_PORT_INT =
+ KEY_PREFIX + "bsf_server_port_int";
+
+ /**
+ * Specifies the transport type used in communication with
+ * BSF server.
+ *
+ * <p>Possible values are,
+ * {@link Ims#PREFERRED_TRANSPORT_TCP},
+ * {@link Ims#PREFERRED_TRANSPORT_TLS}
+ *
+ * <p>If key is invalid or not configured, the default value
+ * {@link Ims#PREFERRED_TRANSPORT_TCP} will apply.
+ */
+ public static final String KEY_BSF_TRANSPORT_TYPE_INT =
+ KEY_PREFIX + "bsf_transport type_int";
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+
+ defaults.putInt(KEY_BSF_SERVER_PORT_INT, 80);
+ defaults.putInt(KEY_BSF_TRANSPORT_TYPE_INT, Ims.PREFERRED_TRANSPORT_TCP);
+ defaults.putString(KEY_BSF_SERVER_FQDN_STRING, "");
+
return defaults;
}
}
@@ -6162,6 +8707,14 @@ public class CarrierConfigManager {
});
sDefaults.putBoolean(KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
sDefaults.putAll(Ims.getDefaults());
+ sDefaults.putAll(ImsVoice.getDefaults());
+ sDefaults.putAll(ImsSms.getDefaults());
+ sDefaults.putAll(ImsRtt.getDefaults());
+ sDefaults.putAll(ImsEmergency.getDefaults());
+ sDefaults.putAll(ImsVt.getDefaults());
+ sDefaults.putAll(ImsWfc.getDefaults());
+ sDefaults.putAll(ImsSs.getDefaults());
+ sDefaults.putAll(Bsf.getDefaults());
sDefaults.putAll(Iwlan.getDefaults());
sDefaults.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, new String[0]);
sDefaults.putBoolean(KEY_FORMAT_INCOMING_NUMBER_TO_NATIONAL_FOR_JP_BOOL, false);
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index b4b8aee31b54..4db00cf258e5 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -379,7 +379,7 @@ public final class CellIdentityLte extends CellIdentity {
mBands = in.createIntArray();
mBandwidth = in.readInt();
mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null);
- mCsgInfo = in.readParcelable(null, android.telephony.ClosedSubscriberGroupInfo.class);
+ mCsgInfo = in.readParcelable(null);
updateGlobalCellId();
if (DBG) log(toString());
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 90e6295abda8..13d93737f751 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -297,7 +297,7 @@ public final class CellIdentityTdscdma extends CellIdentity {
mCpid = in.readInt();
mUarfcn = in.readInt();
mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null);
- mCsgInfo = in.readParcelable(null, android.telephony.ClosedSubscriberGroupInfo.class);
+ mCsgInfo = in.readParcelable(null);
updateGlobalCellId();
if (DBG) log(toString());
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 72282cdb344b..9b463da14f16 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -313,7 +313,7 @@ public final class CellIdentityWcdma extends CellIdentity {
mPsc = in.readInt();
mUarfcn = in.readInt();
mAdditionalPlmns = (ArraySet<String>) in.readArraySet(null);
- mCsgInfo = in.readParcelable(null, android.telephony.ClosedSubscriberGroupInfo.class);
+ mCsgInfo = in.readParcelable(null);
updateGlobalCellId();
if (DBG) log(toString());
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index f5ba3abf53a5..cd22abddd3a7 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -326,7 +326,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa
mCsiRsrq = in.readInt();
mCsiSinr = in.readInt();
mCsiCqiTableIndex = in.readInt();
- mCsiCqiReport = in.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class);
+ mCsiCqiReport = in.readArrayList(Integer.class.getClassLoader());
mSsRsrp = in.readInt();
mSsRsrq = in.readInt();
mSsSinr = in.readInt();
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
index 837124fe89de..957f683292f7 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
@@ -105,7 +105,7 @@ public final class DataSpecificRegistrationInfo implements Parcelable {
isDcNrRestricted = source.readBoolean();
isNrAvailable = source.readBoolean();
isEnDcAvailable = source.readBoolean();
- mVopsSupportInfo = source.readParcelable(VopsSupportInfo.class.getClassLoader(), android.telephony.VopsSupportInfo.class);
+ mVopsSupportInfo = source.readParcelable(VopsSupportInfo.class.getClassLoader());
}
@Override
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index c18443e81aff..6a807665a103 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -311,12 +311,12 @@ public final class NetworkRegistrationInfo implements Parcelable {
mRejectCause = source.readInt();
mEmergencyOnly = source.readBoolean();
mAvailableServices = new ArrayList<>();
- source.readList(mAvailableServices, Integer.class.getClassLoader(), java.lang.Integer.class);
- mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader(), android.telephony.CellIdentity.class);
+ source.readList(mAvailableServices, Integer.class.getClassLoader());
+ mCellIdentity = source.readParcelable(CellIdentity.class.getClassLoader());
mVoiceSpecificInfo = source.readParcelable(
- VoiceSpecificRegistrationInfo.class.getClassLoader(), android.telephony.VoiceSpecificRegistrationInfo.class);
+ VoiceSpecificRegistrationInfo.class.getClassLoader());
mDataSpecificInfo = source.readParcelable(
- DataSpecificRegistrationInfo.class.getClassLoader(), android.telephony.DataSpecificRegistrationInfo.class);
+ DataSpecificRegistrationInfo.class.getClassLoader());
mNrState = source.readInt();
mRplmn = source.readString();
mIsUsingCarrierAggregation = source.readBoolean();
diff --git a/telephony/java/android/telephony/NetworkScanRequest.java b/telephony/java/android/telephony/NetworkScanRequest.java
index c8b8ffb9846b..326f4171de3b 100644
--- a/telephony/java/android/telephony/NetworkScanRequest.java
+++ b/telephony/java/android/telephony/NetworkScanRequest.java
@@ -221,7 +221,8 @@ public final class NetworkScanRequest implements Parcelable {
private NetworkScanRequest(Parcel in) {
mScanType = in.readInt();
- Parcelable[] tempSpecifiers = in.readParcelableArray(Object.class.getClassLoader());
+ Parcelable[] tempSpecifiers = in.readParcelableArray(Object.class.getClassLoader(),
+ RadioAccessSpecifier.class);
if (tempSpecifiers != null) {
mSpecifiers = new RadioAccessSpecifier[tempSpecifiers.length];
for (int i = 0; i < tempSpecifiers.length; i++) {
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index 63e3468ac19b..a3aaf61a6fec 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -150,7 +150,7 @@ public final class PhoneCapability implements Parcelable {
mMaxActiveDataSubscriptions = in.readInt();
mNetworkValidationBeforeSwitchSupported = in.readBoolean();
mLogicalModemList = new ArrayList<>();
- in.readList(mLogicalModemList, ModemInfo.class.getClassLoader(), android.telephony.ModemInfo.class);
+ in.readList(mLogicalModemList, ModemInfo.class.getClassLoader());
mDeviceNrCapabilities = in.createIntArray();
}
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 2670b03ca8ac..ce2f3f924554 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -125,9 +125,9 @@ public final class PreciseDataConnectionState implements Parcelable {
mId = in.readInt();
mState = in.readInt();
mNetworkType = in.readInt();
- mLinkProperties = in.readParcelable(LinkProperties.class.getClassLoader(), android.net.LinkProperties.class);
+ mLinkProperties = in.readParcelable(LinkProperties.class.getClassLoader());
mFailCause = in.readInt();
- mApnSetting = in.readParcelable(ApnSetting.class.getClassLoader(), android.telephony.data.ApnSetting.class);
+ mApnSetting = in.readParcelable(ApnSetting.class.getClassLoader());
}
/**
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 70da9b95410a..5affb62ae5cd 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -479,7 +479,7 @@ public class ServiceState implements Parcelable {
mIsEmergencyOnly = in.readInt() != 0;
mArfcnRsrpBoost = in.readInt();
synchronized (mNetworkRegistrationInfos) {
- in.readList(mNetworkRegistrationInfos, NetworkRegistrationInfo.class.getClassLoader(), android.telephony.NetworkRegistrationInfo.class);
+ in.readList(mNetworkRegistrationInfos, NetworkRegistrationInfo.class.getClassLoader());
}
mChannelNumber = in.readInt();
mCellBandwidths = in.createIntArray();
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index f74ef0fe764a..b7bc46736e18 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -275,12 +275,12 @@ public class SignalStrength implements Parcelable {
public SignalStrength(Parcel in) {
if (DBG) log("Size of signalstrength parcel:" + in.dataSize());
- mCdma = in.readParcelable(CellSignalStrengthCdma.class.getClassLoader(), android.telephony.CellSignalStrengthCdma.class);
- mGsm = in.readParcelable(CellSignalStrengthGsm.class.getClassLoader(), android.telephony.CellSignalStrengthGsm.class);
- mWcdma = in.readParcelable(CellSignalStrengthWcdma.class.getClassLoader(), android.telephony.CellSignalStrengthWcdma.class);
- mTdscdma = in.readParcelable(CellSignalStrengthTdscdma.class.getClassLoader(), android.telephony.CellSignalStrengthTdscdma.class);
- mLte = in.readParcelable(CellSignalStrengthLte.class.getClassLoader(), android.telephony.CellSignalStrengthLte.class);
- mNr = in.readParcelable(CellSignalStrengthLte.class.getClassLoader(), android.telephony.CellSignalStrengthNr.class);
+ mCdma = in.readParcelable(CellSignalStrengthCdma.class.getClassLoader());
+ mGsm = in.readParcelable(CellSignalStrengthGsm.class.getClassLoader());
+ mWcdma = in.readParcelable(CellSignalStrengthWcdma.class.getClassLoader());
+ mTdscdma = in.readParcelable(CellSignalStrengthTdscdma.class.getClassLoader());
+ mLte = in.readParcelable(CellSignalStrengthLte.class.getClassLoader());
+ mNr = in.readParcelable(CellSignalStrengthLte.class.getClassLoader());
mTimestampMillis = in.readLong();
}
diff --git a/telephony/java/android/telephony/ThermalMitigationRequest.java b/telephony/java/android/telephony/ThermalMitigationRequest.java
index a0676ea63711..91ad9c3e1f51 100644
--- a/telephony/java/android/telephony/ThermalMitigationRequest.java
+++ b/telephony/java/android/telephony/ThermalMitigationRequest.java
@@ -100,7 +100,7 @@ public final class ThermalMitigationRequest implements Parcelable {
private ThermalMitigationRequest(Parcel in) {
mThermalMitigationAction = in.readInt();
- mDataThrottlingRequest = in.readParcelable(DataThrottlingRequest.class.getClassLoader(), android.telephony.DataThrottlingRequest.class);
+ mDataThrottlingRequest = in.readParcelable(DataThrottlingRequest.class.getClassLoader());
}
/**
diff --git a/telephony/java/android/telephony/UiccCardInfo.java b/telephony/java/android/telephony/UiccCardInfo.java
index 74f9c876cc40..464389b84945 100644
--- a/telephony/java/android/telephony/UiccCardInfo.java
+++ b/telephony/java/android/telephony/UiccCardInfo.java
@@ -156,11 +156,9 @@ public final class UiccCardInfo implements Parcelable {
@Nullable
@Deprecated
public String getIccId() {
- // Temporarily bypassing exception
- // TODO: add exception once refactoring completed.
- //if (mIccIdAccessRestricted) {
- // throw new UnsupportedOperationException("getIccId from UiccPortInfo");
- //}
+ if (mIccIdAccessRestricted) {
+ throw new UnsupportedOperationException("getIccId from UiccPortInfo");
+ }
//always return ICCID from first port.
return getPorts().stream().findFirst().get().getIccId();
}
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index a8668e7d77d4..2b1c8c863eb6 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -159,11 +159,9 @@ public class UiccSlotInfo implements Parcelable {
*/
@Deprecated
public boolean getIsActive() {
- // Temporarily bypassing exception
- // TODO: add exception once refactoring completed.
- //if (mLogicalSlotAccessRestricted) {
- // throw new UnsupportedOperationException("get port status from UiccPortInfo");
- //}
+ if (mLogicalSlotAccessRestricted) {
+ throw new UnsupportedOperationException("get port status from UiccPortInfo");
+ }
//always return status from first port.
return getPorts().stream().findFirst().get().isActive();
}
@@ -198,11 +196,9 @@ public class UiccSlotInfo implements Parcelable {
*/
@Deprecated
public int getLogicalSlotIdx() {
- // Temporarily bypassing exception
- // TODO: add exception once refactoring completed.
- //if (mLogicalSlotAccessRestricted) {
- // throw new UnsupportedOperationException("get logical slot index from UiccPortInfo");
- //}
+ if (mLogicalSlotAccessRestricted) {
+ throw new UnsupportedOperationException("get logical slot index from UiccPortInfo");
+ }
//always return logical slot index from first port.
//portList always have at least one element.
return getPorts().stream().findFirst().get().getLogicalSlotIndex();
diff --git a/telephony/java/android/telephony/VisualVoicemailSms.java b/telephony/java/android/telephony/VisualVoicemailSms.java
index bec715e3b81a..085f8823b840 100644
--- a/telephony/java/android/telephony/VisualVoicemailSms.java
+++ b/telephony/java/android/telephony/VisualVoicemailSms.java
@@ -121,7 +121,7 @@ public final class VisualVoicemailSms implements Parcelable {
@Override
public VisualVoicemailSms createFromParcel(Parcel in) {
return new Builder()
- .setPhoneAccountHandle((PhoneAccountHandle) in.readParcelable(null, android.telecom.PhoneAccountHandle.class))
+ .setPhoneAccountHandle((PhoneAccountHandle) in.readParcelable(null))
.setPrefix(in.readString())
.setFields(in.readBundle())
.setMessageBody(in.readString())
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 4ff59b568657..977fe33988d6 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1629,7 +1629,7 @@ public class ApnSetting implements Parcelable {
.setApnName(in.readString())
.setProxyAddress(in.readString())
.setProxyPort(in.readInt())
- .setMmsc(in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class))
+ .setMmsc(in.readParcelable(Uri.class.getClassLoader()))
.setMmsProxyAddress(in.readString())
.setMmsProxyPort(in.readInt())
.setUser(in.readString())
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index ae0d4e7e3b4e..ef02589abaf8 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -241,24 +241,24 @@ public final class DataCallResponse implements Parcelable {
mProtocolType = source.readInt();
mInterfaceName = source.readString();
mAddresses = new ArrayList<>();
- source.readList(mAddresses, LinkAddress.class.getClassLoader(), android.net.LinkAddress.class);
+ source.readList(mAddresses, LinkAddress.class.getClassLoader());
mDnsAddresses = new ArrayList<>();
- source.readList(mDnsAddresses, InetAddress.class.getClassLoader(), java.net.InetAddress.class);
+ source.readList(mDnsAddresses, InetAddress.class.getClassLoader());
mGatewayAddresses = new ArrayList<>();
- source.readList(mGatewayAddresses, InetAddress.class.getClassLoader(), java.net.InetAddress.class);
+ source.readList(mGatewayAddresses, InetAddress.class.getClassLoader());
mPcscfAddresses = new ArrayList<>();
- source.readList(mPcscfAddresses, InetAddress.class.getClassLoader(), java.net.InetAddress.class);
+ source.readList(mPcscfAddresses, InetAddress.class.getClassLoader());
mMtu = source.readInt();
mMtuV4 = source.readInt();
mMtuV6 = source.readInt();
mHandoverFailureMode = source.readInt();
mPduSessionId = source.readInt();
- mDefaultQos = source.readParcelable(Qos.class.getClassLoader(), android.telephony.data.Qos.class);
+ mDefaultQos = source.readParcelable(Qos.class.getClassLoader());
mQosBearerSessions = new ArrayList<>();
- source.readList(mQosBearerSessions, QosBearerSession.class.getClassLoader(), android.telephony.data.QosBearerSession.class);
- mSliceInfo = source.readParcelable(NetworkSliceInfo.class.getClassLoader(), android.telephony.data.NetworkSliceInfo.class);
+ source.readList(mQosBearerSessions, QosBearerSession.class.getClassLoader());
+ mSliceInfo = source.readParcelable(NetworkSliceInfo.class.getClassLoader());
mTrafficDescriptors = new ArrayList<>();
- source.readList(mTrafficDescriptors, TrafficDescriptor.class.getClassLoader(), android.telephony.data.TrafficDescriptor.class);
+ source.readList(mTrafficDescriptors, TrafficDescriptor.class.getClassLoader());
}
/**
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index a166a5d6404c..ec04c1ae9522 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -107,8 +107,8 @@ public final class DataProfile implements Parcelable {
private DataProfile(Parcel source) {
mType = source.readInt();
- mApnSetting = source.readParcelable(ApnSetting.class.getClassLoader(), android.telephony.data.ApnSetting.class);
- mTrafficDescriptor = source.readParcelable(TrafficDescriptor.class.getClassLoader(), android.telephony.data.TrafficDescriptor.class);
+ mApnSetting = source.readParcelable(ApnSetting.class.getClassLoader());
+ mTrafficDescriptor = source.readParcelable(TrafficDescriptor.class.getClassLoader());
mPreferred = source.readBoolean();
mSetupTimestamp = source.readLong();
}
diff --git a/telephony/java/android/telephony/data/Qos.java b/telephony/java/android/telephony/data/Qos.java
index 9c2a3bb1e15c..8c437c83e196 100644
--- a/telephony/java/android/telephony/data/Qos.java
+++ b/telephony/java/android/telephony/data/Qos.java
@@ -136,8 +136,8 @@ public abstract class Qos {
protected Qos(@NonNull Parcel source) {
type = source.readInt();
- downlink = source.readParcelable(QosBandwidth.class.getClassLoader(), android.telephony.data.Qos.QosBandwidth.class);
- uplink = source.readParcelable(QosBandwidth.class.getClassLoader(), android.telephony.data.Qos.QosBandwidth.class);
+ downlink = source.readParcelable(QosBandwidth.class.getClassLoader());
+ uplink = source.readParcelable(QosBandwidth.class.getClassLoader());
}
/**
diff --git a/telephony/java/android/telephony/data/QosBearerFilter.java b/telephony/java/android/telephony/data/QosBearerFilter.java
index 5a7189f44552..d6f0cb02f0aa 100644
--- a/telephony/java/android/telephony/data/QosBearerFilter.java
+++ b/telephony/java/android/telephony/data/QosBearerFilter.java
@@ -18,6 +18,7 @@ package android.telephony.data;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.LinkAddress;
import android.os.Parcel;
import android.os.Parcelable;
@@ -35,11 +36,10 @@ import java.util.Objects;
* @hide
*/
public final class QosBearerFilter implements Parcelable {
-
- private List<LinkAddress> localAddresses;
- private List<LinkAddress> remoteAddresses;
- private PortRange localPort;
- private PortRange remotePort;
+ private @NonNull List<LinkAddress> localAddresses;
+ private @NonNull List<LinkAddress> remoteAddresses;
+ private @Nullable PortRange localPort;
+ private @Nullable PortRange remotePort;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -56,13 +56,12 @@ public final class QosBearerFilter implements Parcelable {
public static final int QOS_PROTOCOL_AH = android.hardware.radio.V1_6.QosProtocol.AH;
public static final int QOS_MIN_PORT = android.hardware.radio.V1_6.QosPortRange.MIN;
/**
- * Hardcoded inplace of android.hardware.radio.V1_6.QosPortRange.MAX as it
+ * Hardcoded in place of android.hardware.radio.V1_6.QosPortRange.MAX as it
* returns -1 due to uint16_t to int conversion in java. (TODO: Fix the HAL)
*/
public static final int QOS_MAX_PORT = 65535; // android.hardware.radio.V1_6.QosPortRange.MIN;
- @QosProtocol
- private int protocol;
+ private @QosProtocol int protocol;
private int typeOfServiceMask;
@@ -85,8 +84,7 @@ public final class QosBearerFilter implements Parcelable {
public static final int QOS_FILTER_DIRECTION_BIDIRECTIONAL =
android.hardware.radio.V1_6.QosFilterDirection.BIDIRECTIONAL;
- @QosBearerFilterDirection
- private int filterDirection;
+ private @QosBearerFilterDirection int filterDirection;
/**
* Specified the order in which the filter needs to be matched.
@@ -94,9 +92,10 @@ public final class QosBearerFilter implements Parcelable {
*/
private int precedence;
- public QosBearerFilter(List<LinkAddress> localAddresses, List<LinkAddress> remoteAddresses,
- PortRange localPort, PortRange remotePort, int protocol, int tos,
- long flowLabel, long spi, int direction, int precedence) {
+ public QosBearerFilter(@NonNull List<LinkAddress> localAddresses,
+ @NonNull List<LinkAddress> remoteAddresses, @Nullable PortRange localPort,
+ @Nullable PortRange remotePort, @QosProtocol int protocol, int tos, long flowLabel,
+ long spi, @QosBearerFilterDirection int direction, int precedence) {
this.localAddresses = new ArrayList<>();
this.localAddresses.addAll(localAddresses);
this.remoteAddresses = new ArrayList<>();
@@ -111,19 +110,19 @@ public final class QosBearerFilter implements Parcelable {
this.precedence = precedence;
}
- public List<LinkAddress> getLocalAddresses() {
+ public @NonNull List<LinkAddress> getLocalAddresses() {
return localAddresses;
}
- public List<LinkAddress> getRemoteAddresses() {
+ public @NonNull List<LinkAddress> getRemoteAddresses() {
return remoteAddresses;
}
- public PortRange getLocalPortRange() {
+ public @Nullable PortRange getLocalPortRange() {
return localPort;
}
- public PortRange getRemotePortRange() {
+ public @Nullable PortRange getRemotePortRange() {
return remotePort;
}
@@ -245,8 +244,8 @@ public final class QosBearerFilter implements Parcelable {
&& localAddresses.containsAll(other.localAddresses)
&& remoteAddresses.size() == other.remoteAddresses.size()
&& remoteAddresses.containsAll(other.remoteAddresses)
- && localPort.equals(other.localPort)
- && remotePort.equals(other.remotePort)
+ && Objects.equals(localPort, other.localPort)
+ && Objects.equals(remotePort, other.remotePort)
&& protocol == other.protocol
&& typeOfServiceMask == other.typeOfServiceMask
&& flowLabel == other.flowLabel
@@ -257,11 +256,11 @@ public final class QosBearerFilter implements Parcelable {
private QosBearerFilter(Parcel source) {
localAddresses = new ArrayList<>();
- source.readList(localAddresses, LinkAddress.class.getClassLoader(), android.net.LinkAddress.class);
+ source.readList(localAddresses, LinkAddress.class.getClassLoader());
remoteAddresses = new ArrayList<>();
- source.readList(remoteAddresses, LinkAddress.class.getClassLoader(), android.net.LinkAddress.class);
- localPort = source.readParcelable(PortRange.class.getClassLoader(), android.telephony.data.QosBearerFilter.PortRange.class);
- remotePort = source.readParcelable(PortRange.class.getClassLoader(), android.telephony.data.QosBearerFilter.PortRange.class);
+ source.readList(remoteAddresses, LinkAddress.class.getClassLoader());
+ localPort = source.readParcelable(PortRange.class.getClassLoader());
+ remotePort = source.readParcelable(PortRange.class.getClassLoader());
protocol = source.readInt();
typeOfServiceMask = source.readInt();
flowLabel = source.readLong();
diff --git a/telephony/java/android/telephony/data/QosBearerSession.java b/telephony/java/android/telephony/data/QosBearerSession.java
index dd080856d450..ffeb08a17584 100644
--- a/telephony/java/android/telephony/data/QosBearerSession.java
+++ b/telephony/java/android/telephony/data/QosBearerSession.java
@@ -46,9 +46,9 @@ public final class QosBearerSession implements Parcelable{
private QosBearerSession(Parcel source) {
qosBearerSessionId = source.readInt();
- qos = source.readParcelable(Qos.class.getClassLoader(), android.telephony.data.Qos.class);
+ qos = source.readParcelable(Qos.class.getClassLoader());
qosBearerFilterList = new ArrayList<>();
- source.readList(qosBearerFilterList, QosBearerFilter.class.getClassLoader(), android.telephony.data.QosBearerFilter.class);
+ source.readList(qosBearerFilterList, QosBearerFilter.class.getClassLoader());
}
public int getQosBearerSessionId() {
diff --git a/telephony/java/android/telephony/gba/GbaAuthRequest.java b/telephony/java/android/telephony/gba/GbaAuthRequest.java
index 2c6021a18ea2..5366e9af3147 100644
--- a/telephony/java/android/telephony/gba/GbaAuthRequest.java
+++ b/telephony/java/android/telephony/gba/GbaAuthRequest.java
@@ -120,7 +120,7 @@ public final class GbaAuthRequest implements Parcelable {
int token = in.readInt();
int subId = in.readInt();
int appType = in.readInt();
- Uri nafUrl = in.readParcelable(GbaAuthRequest.class.getClassLoader(), android.net.Uri.class);
+ Uri nafUrl = in.readParcelable(GbaAuthRequest.class.getClassLoader());
int len = in.readInt();
byte[] protocol = new byte[len];
in.readByteArray(protocol);
diff --git a/telephony/java/android/telephony/ims/DelegateRequest.java b/telephony/java/android/telephony/ims/DelegateRequest.java
index c5c92009ee32..c322d924182a 100644
--- a/telephony/java/android/telephony/ims/DelegateRequest.java
+++ b/telephony/java/android/telephony/ims/DelegateRequest.java
@@ -63,7 +63,7 @@ public final class DelegateRequest implements Parcelable {
*/
private DelegateRequest(Parcel in) {
mFeatureTags = new ArrayList<>();
- in.readList(mFeatureTags, null /*classLoader*/, java.lang.String.class);
+ in.readList(mFeatureTags, null /*classLoader*/);
}
@Override
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 7e2d80eb871c..8a665dc92421 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -843,7 +843,7 @@ public final class ImsCallProfile implements Parcelable {
mServiceType = in.readInt();
mCallType = in.readInt();
mCallExtras = in.readBundle();
- mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader(), android.telephony.ims.ImsStreamMediaProfile.class);
+ mMediaProfile = in.readParcelable(ImsStreamMediaProfile.class.getClassLoader());
mEmergencyServiceCategories = in.readInt();
mEmergencyUrns = in.createStringArrayList();
mEmergencyCallRouting = in.readInt();
@@ -851,7 +851,8 @@ public final class ImsCallProfile implements Parcelable {
mHasKnownUserIntentEmergency = in.readBoolean();
mRestrictCause = in.readInt();
mCallerNumberVerificationStatus = in.readInt();
- Object[] accepted = in.readArray(RtpHeaderExtensionType.class.getClassLoader());
+ Object[] accepted = in.readArray(RtpHeaderExtensionType.class.getClassLoader(),
+ RtpHeaderExtensionType.class);
mAcceptedRtpHeaderExtensionTypes = Arrays.stream(accepted)
.map(o -> (RtpHeaderExtensionType) o).collect(Collectors.toSet());
}
diff --git a/telephony/java/android/telephony/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java
index d4d8c44196d5..1fa5f52968e5 100644
--- a/telephony/java/android/telephony/ims/ImsConferenceState.java
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.java
@@ -133,7 +133,7 @@ public final class ImsConferenceState implements Parcelable {
for (int i = 0; i < size; ++i) {
String user = in.readString();
- Bundle state = in.readParcelable(null, android.os.Bundle.class);
+ Bundle state = in.readParcelable(null);
mParticipants.put(user, state);
}
}
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index d45110772ce4..c663e393fe06 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -141,8 +141,8 @@ public final class ImsExternalCallState implements Parcelable {
public ImsExternalCallState(Parcel in) {
mCallId = in.readInt();
ClassLoader classLoader = ImsExternalCallState.class.getClassLoader();
- mAddress = in.readParcelable(classLoader, android.net.Uri.class);
- mLocalAddress = in.readParcelable(classLoader, android.net.Uri.class);
+ mAddress = in.readParcelable(classLoader);
+ mLocalAddress = in.readParcelable(classLoader);
mIsPullable = (in.readInt() != 0);
mCallState = in.readInt();
mCallType = in.readInt();
diff --git a/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java
index b77d3063e2cc..ccb3231526dd 100644
--- a/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java
+++ b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java
@@ -153,7 +153,7 @@ public final class ImsRegistrationAttributes implements Parcelable {
mTransportType = source.readInt();
mImsAttributeFlags = source.readInt();
mFeatureTags = new ArrayList<>();
- source.readList(mFeatureTags, null /*classloader*/, java.lang.String.class);
+ source.readList(mFeatureTags, null /*classloader*/);
}
/**
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index 9f4b77e22dd7..868dea6a3121 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -365,8 +365,8 @@ public final class ImsSsData implements Parcelable {
serviceClass = in.readInt();
result = in.readInt();
mSsInfo = in.createIntArray();
- mCfInfo = in.readParcelableList(new ArrayList<>(), this.getClass().getClassLoader(), android.telephony.ims.ImsCallForwardInfo.class);
- mImsSsInfo = in.readParcelableList(new ArrayList<>(), this.getClass().getClassLoader(), android.telephony.ims.ImsSsInfo.class);
+ mCfInfo = in.readParcelableList(new ArrayList<>(), this.getClass().getClassLoader());
+ mImsSsInfo = in.readParcelableList(new ArrayList<>(), this.getClass().getClassLoader());
}
public static final @android.annotation.NonNull Creator<ImsSsData> CREATOR = new Creator<ImsSsData>() {
diff --git a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
index 6a6c3063483e..9c28c36521f5 100644
--- a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
+++ b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
@@ -439,13 +439,13 @@ public final class RcsContactPresenceTuple implements Parcelable {
}
private RcsContactPresenceTuple(Parcel in) {
- mContactUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
+ mContactUri = in.readParcelable(Uri.class.getClassLoader());
mTimestamp = convertStringFormatTimeToInstant(in.readString());
mStatus = in.readString();
mServiceId = in.readString();
mServiceVersion = in.readString();
mServiceDescription = in.readString();
- mServiceCapabilities = in.readParcelable(ServiceCapabilities.class.getClassLoader(), android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities.class);
+ mServiceCapabilities = in.readParcelable(ServiceCapabilities.class.getClassLoader());
}
@Override
diff --git a/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java
index ea022de3bc01..ee02564267c0 100644
--- a/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java
+++ b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java
@@ -37,7 +37,7 @@ public final class RcsContactTerminatedReason implements Parcelable {
}
private RcsContactTerminatedReason(Parcel in) {
- mContactUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
+ mContactUri = in.readParcelable(Uri.class.getClassLoader());
mReason = in.readString();
}
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index 0f1b3695270b..91121187a19a 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -244,14 +244,14 @@ public final class RcsContactUceCapability implements Parcelable {
}
private RcsContactUceCapability(Parcel in) {
- mContactUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
+ mContactUri = in.readParcelable(Uri.class.getClassLoader());
mCapabilityMechanism = in.readInt();
mSourceType = in.readInt();
mRequestResult = in.readInt();
List<String> featureTagList = new ArrayList<>();
in.readStringList(featureTagList);
mFeatureTags.addAll(featureTagList);
- in.readParcelableList(mPresenceTuples, RcsContactPresenceTuple.class.getClassLoader(), android.telephony.ims.RcsContactPresenceTuple.class);
+ in.readParcelableList(mPresenceTuples, RcsContactPresenceTuple.class.getClassLoader());
}
@Override
diff --git a/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java b/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java
index b9ffd247f658..af4e23476331 100644
--- a/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java
+++ b/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java
@@ -63,7 +63,7 @@ public final class RtpHeaderExtensionType implements Parcelable {
private RtpHeaderExtensionType(Parcel in) {
mLocalIdentifier = in.readInt();
- mUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
+ mUri = in.readParcelable(Uri.class.getClassLoader());
}
public static final @NonNull Creator<RtpHeaderExtensionType> CREATOR =
diff --git a/telephony/java/android/telephony/ims/SipDelegateConfiguration.java b/telephony/java/android/telephony/ims/SipDelegateConfiguration.java
index db0ae033713e..1bf5cad49c53 100644
--- a/telephony/java/android/telephony/ims/SipDelegateConfiguration.java
+++ b/telephony/java/android/telephony/ims/SipDelegateConfiguration.java
@@ -573,7 +573,7 @@ public final class SipDelegateConfiguration implements Parcelable {
mPrivateUserIdentifier = source.readString();
mHomeDomain = source.readString();
mImei = source.readString();
- mGruu = source.readParcelable(null, android.net.Uri.class);
+ mGruu = source.readParcelable(null);
mSipAuthHeader = source.readString();
mSipAuthNonce = source.readString();
mServiceRouteHeader = source.readString();
diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java
index 391372ac8ac1..acc62435e07c 100644
--- a/telephony/java/android/telephony/ims/SipMessage.java
+++ b/telephony/java/android/telephony/ims/SipMessage.java
@@ -57,7 +57,7 @@ public final class SipMessage implements Parcelable {
* @param startLine The start line of the message, containing either the request-line or
* status-line.
* @param headerSection A String containing the full unencoded SIP message header.
- * @param content UTF-8 encoded SIP message body.
+ * @param content SIP message body.
*/
public SipMessage(@NonNull String startLine, @NonNull String headerSection,
@NonNull byte[] content) {
@@ -105,7 +105,7 @@ public final class SipMessage implements Parcelable {
}
/**
- * @return only the UTF-8 encoded SIP message body.
+ * @return the SIP message body.
*/
public @NonNull byte[] getContent() {
return mContent;
diff --git a/telephony/java/android/telephony/mbms/DownloadRequest.java b/telephony/java/android/telephony/mbms/DownloadRequest.java
index 81d5be8562b6..eb59f87a6c02 100644
--- a/telephony/java/android/telephony/mbms/DownloadRequest.java
+++ b/telephony/java/android/telephony/mbms/DownloadRequest.java
@@ -242,8 +242,8 @@ public final class DownloadRequest implements Parcelable {
private DownloadRequest(Parcel in) {
fileServiceId = in.readString();
- sourceUri = in.readParcelable(getClass().getClassLoader(), android.net.Uri.class);
- destinationUri = in.readParcelable(getClass().getClassLoader(), android.net.Uri.class);
+ sourceUri = in.readParcelable(getClass().getClassLoader());
+ destinationUri = in.readParcelable(getClass().getClassLoader());
subscriptionId = in.readInt();
serializedResultIntentForApp = in.readString();
version = in.readInt();
diff --git a/telephony/java/android/telephony/mbms/FileInfo.java b/telephony/java/android/telephony/mbms/FileInfo.java
index ffd864ebda93..e52b2ce0c505 100644
--- a/telephony/java/android/telephony/mbms/FileInfo.java
+++ b/telephony/java/android/telephony/mbms/FileInfo.java
@@ -55,7 +55,7 @@ public final class FileInfo implements Parcelable {
}
private FileInfo(Parcel in) {
- uri = in.readParcelable(null, android.net.Uri.class);
+ uri = in.readParcelable(null);
mimeType = in.readString();
}
diff --git a/telephony/java/android/telephony/mbms/FileServiceInfo.java b/telephony/java/android/telephony/mbms/FileServiceInfo.java
index 0fc3be6de929..8777e7f59e3f 100644
--- a/telephony/java/android/telephony/mbms/FileServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/FileServiceInfo.java
@@ -58,7 +58,7 @@ public final class FileServiceInfo extends ServiceInfo implements Parcelable {
FileServiceInfo(Parcel in) {
super(in);
files = new ArrayList<FileInfo>();
- in.readList(files, FileInfo.class.getClassLoader(), android.telephony.mbms.FileInfo.class);
+ in.readList(files, FileInfo.class.getClassLoader());
}
@Override
diff --git a/telephony/java/android/telephony/mbms/ServiceInfo.java b/telephony/java/android/telephony/mbms/ServiceInfo.java
index 02424ff75c82..f78e7a6e54c4 100644
--- a/telephony/java/android/telephony/mbms/ServiceInfo.java
+++ b/telephony/java/android/telephony/mbms/ServiceInfo.java
@@ -80,7 +80,7 @@ public class ServiceInfo {
}
names = new HashMap(mapCount);
while (mapCount-- > 0) {
- Locale locale = (java.util.Locale) in.readSerializable(java.util.Locale.class.getClassLoader(), java.util.Locale.class);
+ Locale locale = (java.util.Locale) in.readSerializable();
String name = in.readString();
names.put(locale, name);
}
@@ -91,12 +91,12 @@ public class ServiceInfo {
}
locales = new ArrayList<Locale>(localesCount);
while (localesCount-- > 0) {
- Locale l = (java.util.Locale) in.readSerializable(java.util.Locale.class.getClassLoader(), java.util.Locale.class);
+ Locale l = (java.util.Locale) in.readSerializable();
locales.add(l);
}
serviceId = in.readString();
- sessionStartTime = (java.util.Date) in.readSerializable(java.util.Date.class.getClassLoader(), java.util.Date.class);
- sessionEndTime = (java.util.Date) in.readSerializable(java.util.Date.class.getClassLoader(), java.util.Date.class);
+ sessionStartTime = (java.util.Date) in.readSerializable();
+ sessionEndTime = (java.util.Date) in.readSerializable();
}
/** @hide */
diff --git a/telephony/java/android/telephony/mbms/UriPathPair.java b/telephony/java/android/telephony/mbms/UriPathPair.java
index 54d9d9e5284e..9258919919b7 100644
--- a/telephony/java/android/telephony/mbms/UriPathPair.java
+++ b/telephony/java/android/telephony/mbms/UriPathPair.java
@@ -48,8 +48,8 @@ public final class UriPathPair implements Parcelable {
/** @hide */
private UriPathPair(Parcel in) {
- mFilePathUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
- mContentUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
+ mFilePathUri = in.readParcelable(Uri.class.getClassLoader());
+ mContentUri = in.readParcelable(Uri.class.getClassLoader());
}
public static final @android.annotation.NonNull Creator<UriPathPair> CREATOR = new Creator<UriPathPair>() {
diff --git a/telephony/java/com/android/internal/telephony/NetworkScanResult.java b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
index 8b49f4b4593c..d07d77ca742a 100644
--- a/telephony/java/com/android/internal/telephony/NetworkScanResult.java
+++ b/telephony/java/com/android/internal/telephony/NetworkScanResult.java
@@ -83,7 +83,7 @@ public final class NetworkScanResult implements Parcelable {
scanStatus = in.readInt();
scanError = in.readInt();
List<CellInfo> ni = new ArrayList<>();
- in.readParcelableList(ni, Object.class.getClassLoader(), android.telephony.CellInfo.class);
+ in.readParcelableList(ni, Object.class.getClassLoader());
networkInfos = ni;
}
diff --git a/telephony/java/com/android/internal/telephony/OperatorInfo.java b/telephony/java/com/android/internal/telephony/OperatorInfo.java
index 1820a1dc4d6c..a6f0f667d0cd 100644
--- a/telephony/java/com/android/internal/telephony/OperatorInfo.java
+++ b/telephony/java/com/android/internal/telephony/OperatorInfo.java
@@ -189,7 +189,7 @@ public class OperatorInfo implements Parcelable {
in.readString(), /*operatorAlphaLong*/
in.readString(), /*operatorAlphaShort*/
in.readString(), /*operatorNumeric*/
- (State) in.readSerializable(com.android.internal.telephony.OperatorInfo.State.class.getClassLoader(), com.android.internal.telephony.OperatorInfo.State.class), /*state*/
+ (State) in.readSerializable(), /*state*/
in.readInt()); /*ran*/
return opInfo;
}
diff --git a/tests/AppLaunchWear/Android.bp b/tests/AppLaunchWear/Android.bp
deleted file mode 100644
index e2fc4735a7c2..000000000000
--- a/tests/AppLaunchWear/Android.bp
+++ /dev/null
@@ -1,22 +0,0 @@
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-android_test {
- name: "AppLaunchWear",
- // Only compile source java files in this apk.
- srcs: ["src/**/*.java"],
- platform_apis: true,
- certificate: "platform",
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
- static_libs: ["androidx.test.rules"],
- test_suites: ["device-tests"],
-}
diff --git a/tests/AppLaunchWear/AndroidManifest.xml b/tests/AppLaunchWear/AndroidManifest.xml
deleted file mode 100644
index 7dfd7bafbaaa..000000000000
--- a/tests/AppLaunchWear/AndroidManifest.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.tests.applaunch"
- android:sharedUserId="android.uid.system" >
-
- <uses-permission android:name="android.permission.REAL_GET_TASKS" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-
- <uses-sdk
- android:minSdkVersion="22"
- android:targetSdkVersion="24" />
-
- <instrumentation android:label="Measure app start up time"
- android:name="android.test.InstrumentationTestRunner"
- android:targetPackage="com.android.tests.applaunch" />
-
- <application android:label="App Launch Test">
- <uses-library android:name="android.test.runner" />
- </application>
-</manifest>
diff --git a/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java
deleted file mode 100644
index 97701c61011e..000000000000
--- a/tests/AppLaunchWear/src/com/android/tests/applaunch/AppLaunch.java
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.tests.applaunch;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.app.ActivityManager;
-import android.app.ActivityManager.ProcessErrorStateInfo;
-import android.app.IActivityManager;
-import android.app.UiAutomation;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.test.InstrumentationTestCase;
-import android.test.InstrumentationTestRunner;
-import android.util.Log;
-
-import androidx.test.rule.logging.AtraceLogger;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * This test is intended to measure the time it takes for the apps to start.
- * Names of the applications are passed in command line, and the
- * test starts each application, and reports the start up time in milliseconds.
- * The instrumentation expects the following key to be passed on the command line:
- * apps - A list of applications to start and their corresponding result keys
- * in the following format:
- * -e apps <app name>^<result key>|<app name>^<result key>
- */
-public class AppLaunch extends InstrumentationTestCase {
-
- private static final int JOIN_TIMEOUT = 10000;
- private static final String TAG = AppLaunch.class.getSimpleName();
-
- // optional parameter: comma separated list of required account types before proceeding
- // with the app launch
- private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
- private static final String KEY_APPS = "apps";
- private static final String KEY_TRIAL_LAUNCH = "trial_launch";
- private static final String KEY_LAUNCH_ITERATIONS = "launch_iterations";
- private static final String KEY_LAUNCH_ORDER = "launch_order";
- private static final String KEY_DROP_CACHE = "drop_cache";
- private static final String KEY_SIMPLEPERF_CMD = "simpleperf_cmd";
- private static final String KEY_SIMPLEPERF_APP = "simpleperf_app";
- private static final String KEY_TRACE_ITERATIONS = "trace_iterations";
- private static final String KEY_LAUNCH_DIRECTORY = "launch_directory";
- private static final String KEY_TRACE_DIRECTORY = "trace_directory";
- private static final String KEY_TRACE_CATEGORY = "trace_categories";
- private static final String KEY_TRACE_BUFFERSIZE = "trace_bufferSize";
- private static final String KEY_TRACE_DUMPINTERVAL = "tracedump_interval";
- private static final String KEY_COMPILER_FILTERS = "compiler_filters";
-
- private static final String SIMPLEPERF_APP_CMD =
- "simpleperf --log fatal stat --csv -e cpu-cycles,major-faults --app %s & %s";
- private static final String WEARABLE_ACTION_GOOGLE =
- "com.google.android.wearable.action.GOOGLE";
- private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 5000; // 5s to allow app to idle
- private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; // 750ms idle for non initial launches
- private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 5000; // 5s between launching apps
- private static final String LAUNCH_SUB_DIRECTORY = "launch_logs";
- private static final String LAUNCH_FILE = "applaunch.txt";
- private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
- private static final String DEFAULT_TRACE_CATEGORIES =
- "sched,freq,gfx,view,dalvik,webview,input,wm,disk,am,wm";
- private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
- private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
- private static final String TRIAL_LAUNCH = "TRIAL_LAUNCH";
- private static final String DELIMITER = ",";
- private static final String DROP_CACHE_SCRIPT = "/data/local/tmp/dropCache.sh";
- private static final String APP_LAUNCH_CMD = "am start -W -n";
- private static final String SUCCESS_MESSAGE = "Status: ok";
- private static final String WARNING_MESSAGE = "Warning: Activity not started";
- private static final String COMPILE_SUCCESS = "Success";
- private static final String THIS_TIME = "ThisTime:";
- private static final String LAUNCH_ITERATION = "LAUNCH_ITERATION - %d";
- private static final String TRACE_ITERATION = "TRACE_ITERATION-%d";
- private static final String LAUNCH_ITERATION_PREFIX = "LAUNCH_ITERATION";
- private static final String TRACE_ITERATION_PREFIX = "TRACE_ITERATION";
- private static final String LAUNCH_ORDER_CYCLIC = "cyclic";
- private static final String LAUNCH_ORDER_SEQUENTIAL = "sequential";
- private static final String COMPILE_CMD = "cmd package compile -f -m %s %s";
- private static final String SPEED_PROFILE_FILTER = "speed-profile";
- private static final String VERIFY_FILTER = "verify";
- private static final String LAUNCH_SCRIPT_NAME = "appLaunch";
- private static final String WEARABLE_HOME_PACKAGE = "com.google.android.wearable.app";
-
- private Map<String, Intent> mNameToIntent;
- private List<LaunchOrder> mLaunchOrderList = new ArrayList<LaunchOrder>();
- private Map<String, String> mNameToResultKey;
- private Map<String, Map<String, List<AppLaunchResult>>> mNameToLaunchTime;
- private IActivityManager mAm;
- private String mSimplePerfCmd = null;
- private String mLaunchOrder = null;
- private boolean mDropCache = false;
- private int mLaunchIterations = 10;
- private int mTraceLaunchCount = 0;
- private String mTraceDirectoryStr = null;
- private Bundle mResult = new Bundle();
- private Set<String> mRequiredAccounts;
- private boolean mTrialLaunch = false;
- private BufferedWriter mBufferedWriter = null;
- private boolean mSimplePerfAppOnly = false;
- private String[] mCompilerFilters = null;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0);
- }
-
- @Override
- protected void tearDown() throws Exception {
- getInstrumentation().getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE);
- super.tearDown();
- }
-
- private void addLaunchResult(LaunchOrder launch, AppLaunchResult result) {
- mNameToLaunchTime.get(launch.getApp()).get(launch.getCompilerFilter()).add(result);
- }
-
- private boolean hasFailureOnFirstLaunch(LaunchOrder launch) {
- List<AppLaunchResult> results =
- mNameToLaunchTime.get(launch.getApp()).get(launch.getCompilerFilter());
- return (results.size() > 0) && (results.get(0).mLaunchTime < 0);
- }
-
- public void testMeasureStartUpTime() throws RemoteException, NameNotFoundException,
- IOException, InterruptedException {
- InstrumentationTestRunner instrumentation =
- (InstrumentationTestRunner)getInstrumentation();
- Bundle args = instrumentation.getArguments();
- mAm = ActivityManager.getService();
- String launchDirectory = args.getString(KEY_LAUNCH_DIRECTORY);
-
- createMappings();
- parseArgs(args);
- checkAccountSignIn();
-
- // Root directory for applaunch file to log the app launch output
- // Will be useful in case of simpleperf command is used
- File launchRootDir = null;
- if (null != launchDirectory && !launchDirectory.isEmpty()) {
- launchRootDir = new File(launchDirectory);
- if (!launchRootDir.exists() && !launchRootDir.mkdirs()) {
- throw new IOException("Unable to create the destination directory");
- }
- }
-
- try {
- File launchSubDir = new File(launchRootDir, LAUNCH_SUB_DIRECTORY);
-
- if (!launchSubDir.exists() && !launchSubDir.mkdirs()) {
- throw new IOException("Unable to create the lauch file sub directory");
- }
- File file = new File(launchSubDir, LAUNCH_FILE);
- FileOutputStream outputStream = new FileOutputStream(file);
- mBufferedWriter = new BufferedWriter(new OutputStreamWriter(
- outputStream));
-
- // Root directory for trace file during the launches
- File rootTrace = null;
- File rootTraceSubDir = null;
- int traceBufferSize = 0;
- int traceDumpInterval = 0;
- Set<String> traceCategoriesSet = null;
- if (null != mTraceDirectoryStr && !mTraceDirectoryStr.isEmpty()) {
- rootTrace = new File(mTraceDirectoryStr);
- if (!rootTrace.exists() && !rootTrace.mkdirs()) {
- throw new IOException("Unable to create the trace directory");
- }
- rootTraceSubDir = new File(rootTrace, TRACE_SUB_DIRECTORY);
- if (!rootTraceSubDir.exists() && !rootTraceSubDir.mkdirs()) {
- throw new IOException("Unable to create the trace sub directory");
- }
- assertNotNull("Trace iteration parameter is mandatory",
- args.getString(KEY_TRACE_ITERATIONS));
- mTraceLaunchCount = Integer.parseInt(args.getString(KEY_TRACE_ITERATIONS));
- String traceCategoriesStr = args
- .getString(KEY_TRACE_CATEGORY, DEFAULT_TRACE_CATEGORIES);
- traceBufferSize = Integer.parseInt(args.getString(KEY_TRACE_BUFFERSIZE,
- DEFAULT_TRACE_BUFFER_SIZE));
- traceDumpInterval = Integer.parseInt(args.getString(KEY_TRACE_DUMPINTERVAL,
- DEFAULT_TRACE_DUMP_INTERVAL));
- traceCategoriesSet = new HashSet<String>();
- if (!traceCategoriesStr.isEmpty()) {
- String[] traceCategoriesSplit = traceCategoriesStr.split(DELIMITER);
- for (int i = 0; i < traceCategoriesSplit.length; i++) {
- traceCategoriesSet.add(traceCategoriesSplit[i]);
- }
- }
- }
-
- // Get the app launch order based on launch order, trial launch,
- // launch iterations and trace iterations
- setLaunchOrder();
-
- for (LaunchOrder launch : mLaunchOrderList) {
- if (mNameToIntent.get(launch.getApp()) == null) {
- continue;
- }
- dropCache();
- String appPkgName = mNameToIntent.get(launch.getApp())
- .getComponent().getPackageName();
- Log.v(TAG, String.format("\nApp name: %s", launch.getApp()));
- Log.v(TAG, String.format("Adding app package name: %s", appPkgName));
- // App launch times for trial launch will not be used for final
- // launch time calculations.
- if (launch.getLaunchReason().equals(TRIAL_LAUNCH)) {
- // In the "applaunch.txt" file, trail launches is referenced using
- // "TRIAL_LAUNCH"
- Log.v(TAG, "Trial Launch");
- if (SPEED_PROFILE_FILTER.equals(launch.getCompilerFilter())) {
- assertTrue(String.format("Not able to compile the app : %s", appPkgName),
- compileApp(VERIFY_FILTER, appPkgName));
- } else if (launch.getCompilerFilter() != null) {
- assertTrue(String.format("Not able to compile the app : %s", appPkgName),
- compileApp(launch.getCompilerFilter(), appPkgName));
- }
- // We only need to run a trial for the speed-profile filter, but we always
- // run one for "applaunch.txt" consistency.
- AppLaunchResult launchResult = null;
- if (appPkgName.contains(WEARABLE_HOME_PACKAGE)) {
- Log.v(TAG, "Home package detected. Not killing app");
- launchResult = startApp(launch.getApp(), false, launch.getLaunchReason());
- } else {
- Log.v(TAG, "Will kill app before launch");
- launchResult = startApp(launch.getApp(), true, launch.getLaunchReason());
- }
- if (launchResult.mLaunchTime < 0) {
- addLaunchResult(launch, new AppLaunchResult());
- // simply pass the app if launch isn't successful
- // error should have already been logged by startApp
- continue;
- }
- sleep(INITIAL_LAUNCH_IDLE_TIMEOUT);
- if (SPEED_PROFILE_FILTER.equals(launch.getCompilerFilter())) {
- // Send SIGUSR1 to force dumping a profile.
- String sendSignalCommand =
- String.format("killall -s SIGUSR1 %s", appPkgName);
- getInstrumentation().getUiAutomation().executeShellCommand(
- sendSignalCommand);
- assertTrue(String.format("Not able to compile the app : %s", appPkgName),
- compileApp(launch.getCompilerFilter(), appPkgName));
- }
- }
-
- // App launch times used for final calculation
- else if (launch.getLaunchReason().contains(LAUNCH_ITERATION_PREFIX)) {
- Log.v(TAG, "Launch iteration prefix.");
- AppLaunchResult launchResults = null;
- if (hasFailureOnFirstLaunch(launch)) {
- // skip if the app has failures while launched first
- continue;
- }
- // In the "applaunch.txt" file app launches are referenced using
- // "LAUNCH_ITERATION - ITERATION NUM"
- if (appPkgName.contains(WEARABLE_HOME_PACKAGE)) {
- Log.v(TAG, "Home package detected. Not killing app");
- launchResults = startApp(launch.getApp(), false, launch.getLaunchReason());
- } else {
- Log.v(TAG, "Will kill app before launch");
- launchResults = startApp(launch.getApp(), true, launch.getLaunchReason());
- }
- if (launchResults.mLaunchTime < 0) {
- addLaunchResult(launch, new AppLaunchResult());
- // if it fails once, skip the rest of the launches
- continue;
- } else {
- addLaunchResult(launch, launchResults);
- }
- sleep(POST_LAUNCH_IDLE_TIMEOUT);
- }
-
- // App launch times for trace launch will not be used for final
- // launch time calculations.
- else if (launch.getLaunchReason().contains(TRACE_ITERATION_PREFIX)) {
- Log.v(TAG, "Trace iteration prefix");
- AtraceLogger atraceLogger = AtraceLogger
- .getAtraceLoggerInstance(getInstrumentation());
- // Start the trace
- try {
- atraceLogger.atraceStart(traceCategoriesSet, traceBufferSize,
- traceDumpInterval, rootTraceSubDir,
- String.format("%s-%s", launch.getApp(), launch.getLaunchReason()));
- if (appPkgName.contains(WEARABLE_HOME_PACKAGE)) {
- Log.v(TAG, "Home package detected. Not killing app");
- startApp(launch.getApp(), false, launch.getLaunchReason());
- } else {
- Log.v(TAG, "Will kill app before launch");
- startApp(launch.getApp(), true, launch.getLaunchReason());
- }
- sleep(POST_LAUNCH_IDLE_TIMEOUT);
- } finally {
- // Stop the trace
- atraceLogger.atraceStop();
- }
- }
- closeApp(launch.getApp(), true);
- sleep(BETWEEN_LAUNCH_SLEEP_TIMEOUT);
- }
- } finally {
- if (null != mBufferedWriter) {
- mBufferedWriter.close();
- }
- }
-
- for (String app : mNameToResultKey.keySet()) {
- for (String compilerFilter : mCompilerFilters) {
- StringBuilder launchTimes = new StringBuilder();
- StringBuilder cpuCycles = new StringBuilder();
- StringBuilder majorFaults = new StringBuilder();
- for (AppLaunchResult result : mNameToLaunchTime.get(app).get(compilerFilter)) {
- launchTimes.append(result.mLaunchTime);
- launchTimes.append(",");
- if (mSimplePerfAppOnly) {
- cpuCycles.append(result.mCpuCycles);
- cpuCycles.append(",");
- majorFaults.append(result.mMajorFaults);
- majorFaults.append(",");
- }
- }
- String filterName = (compilerFilter == null) ? "" : ("-" + compilerFilter);
- mResult.putString(mNameToResultKey.get(app) + filterName, launchTimes.toString());
- if (mSimplePerfAppOnly) {
- mResult.putString(mNameToResultKey.get(app) + filterName + "-cpuCycles",
- cpuCycles.toString());
- mResult.putString(mNameToResultKey.get(app) + filterName + "-majorFaults",
- majorFaults.toString());
- }
- }
- }
- instrumentation.sendStatus(0, mResult);
- }
-
- /**
- * Compile the app package using compilerFilter and return true or false
- * based on status of the compilation command.
- */
- private boolean compileApp(String compilerFilter, String appPkgName) throws IOException {
- try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation().
- executeShellCommand(String.format(COMPILE_CMD, compilerFilter, appPkgName));
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
- new FileInputStream(result.getFileDescriptor())))) {
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- if (line.contains(COMPILE_SUCCESS)) {
- return true;
- }
- }
- return false;
- }
- }
-
- /**
- * If launch order is "cyclic" then apps will be launched one after the
- * other for each iteration count.
- * If launch order is "sequential" then each app will be launched for given number
- * iterations at once before launching the other apps.
- */
- private void setLaunchOrder() {
- if (LAUNCH_ORDER_CYCLIC.equalsIgnoreCase(mLaunchOrder)) {
- for (String compilerFilter : mCompilerFilters) {
- if (mTrialLaunch) {
- for (String app : mNameToResultKey.keySet()) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
- }
- }
- for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
- for (String app : mNameToResultKey.keySet()) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(LAUNCH_ITERATION, launchCount)));
- }
- }
- if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
- for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
- for (String app : mNameToResultKey.keySet()) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(TRACE_ITERATION, traceCount)));
- }
- }
- }
- }
- } else if (LAUNCH_ORDER_SEQUENTIAL.equalsIgnoreCase(mLaunchOrder)) {
- for (String compilerFilter : mCompilerFilters) {
- for (String app : mNameToResultKey.keySet()) {
- if (mTrialLaunch) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter, TRIAL_LAUNCH));
- }
- for (int launchCount = 0; launchCount < mLaunchIterations; launchCount++) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(LAUNCH_ITERATION, launchCount)));
- }
- if (mTraceDirectoryStr != null && !mTraceDirectoryStr.isEmpty()) {
- for (int traceCount = 0; traceCount < mTraceLaunchCount; traceCount++) {
- mLaunchOrderList.add(new LaunchOrder(app, compilerFilter,
- String.format(TRACE_ITERATION, traceCount)));
- }
- }
- }
- }
- } else {
- assertTrue("Launch order is not valid parameter", false);
- }
- }
-
- private void dropCache() {
- if (mDropCache) {
- assertNotNull("Issue in dropping the cache",
- getInstrumentation().getUiAutomation()
- .executeShellCommand(DROP_CACHE_SCRIPT));
- }
- }
-
- private void parseArgs(Bundle args) {
- mNameToResultKey = new LinkedHashMap<String, String>();
- mNameToLaunchTime = new HashMap<>();
- String launchIterations = args.getString(KEY_LAUNCH_ITERATIONS);
- if (launchIterations != null) {
- mLaunchIterations = Integer.parseInt(launchIterations);
- }
- String appList = args.getString(KEY_APPS);
- if (appList == null)
- return;
-
- String appNames[] = appList.split("\\|");
- for (String pair : appNames) {
- String[] parts = pair.split("\\^");
- if (parts.length != 2) {
- Log.e(TAG, "The apps key is incorrectly formatted");
- fail();
- }
-
- mNameToResultKey.put(parts[0], parts[1]);
- mNameToLaunchTime.put(parts[0], null);
- }
- String requiredAccounts = args.getString(KEY_REQUIRED_ACCOUNTS);
- if (requiredAccounts != null) {
- mRequiredAccounts = new HashSet<String>();
- for (String accountType : requiredAccounts.split(",")) {
- mRequiredAccounts.add(accountType);
- }
- }
-
- String compilerFilterList = args.getString(KEY_COMPILER_FILTERS);
- if (compilerFilterList != null) {
- // If a compiler filter is passed, we make a trial launch to force compilation
- // of the apps.
- mTrialLaunch = true;
- mCompilerFilters = compilerFilterList.split("\\|");
- } else {
- // Just pass a null compiler filter to use the current state of the app.
- mCompilerFilters = new String[1];
- }
-
- // Pre-populate the results map to avoid null checks.
- for (String app : mNameToLaunchTime.keySet()) {
- HashMap<String, List<AppLaunchResult>> map = new HashMap<>();
- mNameToLaunchTime.put(app, map);
- for (String compilerFilter : mCompilerFilters) {
- map.put(compilerFilter, new ArrayList<>());
- }
- }
-
- mTraceDirectoryStr = args.getString(KEY_TRACE_DIRECTORY);
- mDropCache = Boolean.parseBoolean(args.getString(KEY_DROP_CACHE));
- mSimplePerfCmd = args.getString(KEY_SIMPLEPERF_CMD);
- mLaunchOrder = args.getString(KEY_LAUNCH_ORDER, LAUNCH_ORDER_CYCLIC);
- mSimplePerfAppOnly = Boolean.parseBoolean(args.getString(KEY_SIMPLEPERF_APP));
- mTrialLaunch = mTrialLaunch || Boolean.parseBoolean(args.getString(KEY_TRIAL_LAUNCH));
-
- if (mSimplePerfCmd != null && mSimplePerfAppOnly) {
- Log.w(TAG, String.format("Passing both %s and %s is not supported, ignoring %s",
- KEY_SIMPLEPERF_CMD, KEY_SIMPLEPERF_APP));
- }
- }
-
- private boolean hasLeanback(Context context) {
- return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
- }
-
- private void createMappings() {
- mNameToIntent = new LinkedHashMap<String, Intent>();
-
- PackageManager pm = getInstrumentation().getContext()
- .getPackageManager();
- Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
- intentToResolve.addCategory(hasLeanback(getInstrumentation().getContext()) ?
- Intent.CATEGORY_LEANBACK_LAUNCHER :
- Intent.CATEGORY_LAUNCHER);
- List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
- resolveLoop(ris, intentToResolve, pm);
- // For Wear
- intentToResolve = new Intent(WEARABLE_ACTION_GOOGLE);
- ris = pm.queryIntentActivities(intentToResolve, 0);
- resolveLoop(ris, intentToResolve, pm);
- }
-
- private void resolveLoop(List<ResolveInfo> ris, Intent intentToResolve, PackageManager pm) {
- if (ris == null || ris.isEmpty()) {
- Log.i(TAG, "Could not find any apps");
- } else {
- for (ResolveInfo ri : ris) {
- Intent startIntent = new Intent(intentToResolve);
- startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- startIntent.setClassName(ri.activityInfo.packageName,
- ri.activityInfo.name);
- String appName = ri.loadLabel(pm).toString();
- if (appName != null) {
- // Support launching intent using package name or app name
- mNameToIntent.put(ri.activityInfo.packageName, startIntent);
- mNameToIntent.put(appName, startIntent);
- }
- }
- }
- }
-
- private AppLaunchResult startApp(String appName, boolean forceStopBeforeLaunch,
- String launchReason) throws NameNotFoundException, RemoteException {
- Log.i(TAG, "Starting " + appName);
-
- Intent startIntent = mNameToIntent.get(appName);
- if (startIntent == null) {
- Log.w(TAG, "App does not exist: " + appName);
- mResult.putString(mNameToResultKey.get(appName), "App does not exist");
- return new AppLaunchResult();
- }
- AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent, forceStopBeforeLaunch,
- launchReason);
- Thread t = new Thread(runnable);
- t.start();
- try {
- t.join(JOIN_TIMEOUT);
- } catch (InterruptedException e) {
- // ignore
- }
- return runnable.getResult();
- }
-
- private void checkAccountSignIn() {
- // ensure that the device has the required account types before starting test
- // e.g. device must have a valid Google account sign in to measure a meaningful launch time
- // for Gmail
- if (mRequiredAccounts == null || mRequiredAccounts.isEmpty()) {
- return;
- }
- final AccountManager am =
- (AccountManager) getInstrumentation().getTargetContext().getSystemService(
- Context.ACCOUNT_SERVICE);
- Account[] accounts = am.getAccounts();
- // use set here in case device has multiple accounts of the same type
- Set<String> foundAccounts = new HashSet<String>();
- for (Account account : accounts) {
- if (mRequiredAccounts.contains(account.type)) {
- foundAccounts.add(account.type);
- }
- }
- // check if account type matches, if not, fail test with message on what account types
- // are missing
- if (mRequiredAccounts.size() != foundAccounts.size()) {
- mRequiredAccounts.removeAll(foundAccounts);
- StringBuilder sb = new StringBuilder("Device missing these accounts:");
- for (String account : mRequiredAccounts) {
- sb.append(' ');
- sb.append(account);
- }
- fail(sb.toString());
- }
- }
-
- private void closeApp(String appName, boolean forceStopApp) {
- Intent homeIntent = new Intent(Intent.ACTION_MAIN);
- homeIntent.addCategory(Intent.CATEGORY_HOME);
- homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- getInstrumentation().getContext().startActivity(homeIntent);
- sleep(POST_LAUNCH_IDLE_TIMEOUT);
- if (forceStopApp) {
- Intent startIntent = mNameToIntent.get(appName);
- if (startIntent != null) {
- String packageName = startIntent.getComponent().getPackageName();
- try {
- mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
- } catch (RemoteException e) {
- Log.w(TAG, "Error closing app", e);
- }
- }
- }
- }
-
- private void sleep(int time) {
- try {
- Thread.sleep(time);
- } catch (InterruptedException e) {
- // ignore
- }
- }
-
- private void reportError(String appName, String processName) {
- ActivityManager am = (ActivityManager) getInstrumentation()
- .getContext().getSystemService(Context.ACTIVITY_SERVICE);
- List<ProcessErrorStateInfo> crashes = am.getProcessesInErrorState();
- if (crashes != null) {
- for (ProcessErrorStateInfo crash : crashes) {
- if (!crash.processName.equals(processName))
- continue;
-
- Log.w(TAG, appName + " crashed: " + crash.shortMsg);
- mResult.putString(mNameToResultKey.get(appName), crash.shortMsg);
- return;
- }
- }
-
- mResult.putString(mNameToResultKey.get(appName),
- "Crashed for unknown reason");
- Log.w(TAG, appName
- + " not found in process list, most likely it is crashed");
- }
-
- private class LaunchOrder {
- private String mApp;
- private String mCompilerFilter;
- private String mLaunchReason;
-
- LaunchOrder(String app, String compilerFilter, String launchReason){
- mApp = app;
- mCompilerFilter = compilerFilter;
- mLaunchReason = launchReason;
- }
-
- public String getApp() {
- return mApp;
- }
-
- public void setApp(String app) {
- mApp = app;
- }
-
- public String getCompilerFilter() {
- return mCompilerFilter;
- }
-
- public String getLaunchReason() {
- return mLaunchReason;
- }
-
- public void setLaunchReason(String launchReason) {
- mLaunchReason = launchReason;
- }
- }
-
- private class AppLaunchResult {
- long mLaunchTime;
- long mCpuCycles;
- long mMajorFaults;
-
- AppLaunchResult() {
- mLaunchTime = -1L;
- mCpuCycles = -1L;
- mMajorFaults = -1L;
- }
-
- AppLaunchResult(String launchTime, String cpuCycles, String majorFaults) {
- try {
- mLaunchTime = Long.parseLong(launchTime, 10);
- mCpuCycles = Long.parseLong(cpuCycles, 10);
- mMajorFaults = Long.parseLong(majorFaults, 10);
- } catch (NumberFormatException e) {
- Log.e(TAG, "Error parsing result", e);
- }
- }
- }
-
- private class AppLaunchRunnable implements Runnable {
- private Intent mLaunchIntent;
- private AppLaunchResult mLaunchResult;
- private boolean mForceStopBeforeLaunch;
- private String mLaunchReason;
-
- public AppLaunchRunnable(Intent intent, boolean forceStopBeforeLaunch,
- String launchReason) {
- mLaunchIntent = intent;
- mForceStopBeforeLaunch = forceStopBeforeLaunch;
- mLaunchReason = launchReason;
- mLaunchResult = new AppLaunchResult();
- }
-
- public AppLaunchResult getResult() {
- return mLaunchResult;
- }
-
- public void run() {
- File launchFile = null;
- try {
- String packageName = mLaunchIntent.getComponent().getPackageName();
- String componentName = mLaunchIntent.getComponent().flattenToShortString();
- if (mForceStopBeforeLaunch) {
- Log.v(TAG, "Stopping app before launch");
- mAm.forceStopPackage(packageName, UserHandle.USER_CURRENT);
- } else {
- Log.v(TAG, "Not killing app. Going to Home Screen.");
- ParcelFileDescriptor goHome = getInstrumentation().getUiAutomation()
- .executeShellCommand("input keyevent 3");
- }
- String launchCmd = String.format("%s %s", APP_LAUNCH_CMD, componentName);
- if (mSimplePerfAppOnly) {
- try {
- // executeShellCommand cannot handle shell specific actions, like '&'.
- // Therefore, we create a file containing the command and make that
- // the command to launch.
- launchFile = File.createTempFile(LAUNCH_SCRIPT_NAME, ".sh");
- launchFile.setExecutable(true);
- try (FileOutputStream stream = new FileOutputStream(launchFile);
- BufferedWriter writer =
- new BufferedWriter(new OutputStreamWriter(stream))) {
- String cmd = String.format(SIMPLEPERF_APP_CMD, packageName, launchCmd);
- writer.write(cmd);
- }
- launchCmd = launchFile.getAbsolutePath();
- } catch (IOException e) {
- Log.w(TAG, "Error writing the launch command", e);
- return;
- }
- } else if (null != mSimplePerfCmd) {
- launchCmd = String.format("%s %s", mSimplePerfCmd, launchCmd);
- }
- Log.v(TAG, "Final launch cmd:" + launchCmd);
- ParcelFileDescriptor parcelDesc = getInstrumentation().getUiAutomation()
- .executeShellCommand(launchCmd);
- mLaunchResult = parseLaunchTimeAndWrite(parcelDesc, String.format
- ("App Launch :%s %s", componentName, mLaunchReason));
- } catch (RemoteException e) {
- Log.w(TAG, "Error launching app", e);
- } finally {
- if (launchFile != null) {
- launchFile.delete();
- }
- }
- }
-
- /**
- * Method to parse the launch time info and write the result to file
- *
- * @param parcelDesc
- * @return
- */
- private AppLaunchResult parseLaunchTimeAndWrite(ParcelFileDescriptor parcelDesc,
- String headerInfo) {
- String launchTime = "-1";
- String cpuCycles = "-1";
- String majorFaults = "-1";
- boolean launchSuccess = false;
- try {
- InputStream inputStream = new FileInputStream(parcelDesc.getFileDescriptor());
- /* SAMPLE OUTPUT :
- Starting: Intent { cmp=com.google.android.calculator/com.android.calculator2.Calculator }
- Status: ok
- Activity: com.google.android.calculator/com.android.calculator2.Calculator
- ThisTime: 357
- TotalTime: 357
- WaitTime: 377
- Complete*/
- /* WHEN NOT KILLING HOME :
- Starting: Intent { cmp=com.google.android.wearable.app/
- com.google.android.clockwork.home.calendar.AgendaActivity }
- Warning: Activity not started, its current task has been brought to the front
- Status: ok
- Activity: com.google.android.wearable.app/
- com.google.android.clockwork.home.calendar.AgendaActivity
- ThisTime: 209
- TotalTime: 209
- WaitTime: 285
- Complete*/
- /* WITH SIMPLEPERF :
- Performance counter statistics,
- 6595722690,cpu-cycles,4.511040,GHz,(100%),
- 0,major-faults,0.000,/sec,(100%),
- Total test time,1.462129,seconds,*/
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
- inputStream));
- String line = null;
- int lineCount = 1;
- int addLineForWarning = 0;
- mBufferedWriter.newLine();
- mBufferedWriter.write(headerInfo);
- mBufferedWriter.newLine();
- while ((line = bufferedReader.readLine()) != null) {
- if (lineCount == 2 && line.contains(WARNING_MESSAGE)) {
- addLineForWarning = 1;
- }
- if (lineCount == (2 + addLineForWarning) && line.contains(SUCCESS_MESSAGE)) {
- launchSuccess = true;
- }
- // Parse TotalTime which is the launch time
- if (launchSuccess && lineCount == (5 + addLineForWarning)) {
- String launchSplit[] = line.split(":");
- launchTime = launchSplit[1].trim();
- }
-
- if (mSimplePerfAppOnly) {
- // Parse simpleperf output.
- if (lineCount == (9 + addLineForWarning)) {
- if (!line.contains("cpu-cycles")) {
- Log.e(TAG, "Error in simpleperf output");
- } else {
- cpuCycles = line.split(",")[0].trim();
- }
- } else if (lineCount == (10 + addLineForWarning)) {
- if (!line.contains("major-faults")) {
- Log.e(TAG, "Error in simpleperf output");
- } else {
- majorFaults = line.split(",")[0].trim();
- }
- }
- }
- mBufferedWriter.write(line);
- mBufferedWriter.newLine();
- lineCount++;
- }
- mBufferedWriter.flush();
- inputStream.close();
- } catch (IOException e) {
- Log.w(TAG, "Error writing the launch file", e);
- }
- return new AppLaunchResult(launchTime, cpuCycles, majorFaults);
- }
-
- }
-}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
index 46d3a3d669c0..65d168bd5238 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColorFiltersMutateActivity.java
@@ -84,7 +84,7 @@ public class ColorFiltersMutateActivity extends Activity {
mBlendPaint.setColorFilter(new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_OVER));
mRuntimeShader = new RuntimeShader(sSkSL, false);
- mRuntimeShader.setUniform("param1", mShaderParam1);
+ mRuntimeShader.setFloatUniform("param1", mShaderParam1);
mRuntimeShader.setInputShader("bitmapShader", new BitmapShader(mBitmap1,
Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP));
@@ -177,7 +177,7 @@ public class ColorFiltersMutateActivity extends Activity {
public void setShaderParam1(float value) {
mShaderParam1 = value;
- mRuntimeShader.setUniform("param1", mShaderParam1);
+ mRuntimeShader.setFloatUniform("param1", mShaderParam1);
invalidate();
}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
index 83e2de925ceb..73c4b8af99de 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/RippleActivity.java
@@ -110,7 +110,7 @@ public class RippleActivity extends Activity {
mPaint = CanvasProperty.createPaint(p);
mRuntimeShader = new RuntimeShader(sSkSL, false);
- mRuntimeShader.setUniform("in_maxRadius", MAX_RADIUS);
+ mRuntimeShader.setFloatUniform("in_maxRadius", MAX_RADIUS);
}
@Override
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java
index fcdee63a99a8..12e338c96aea 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchShaderActivity.java
@@ -357,18 +357,18 @@ public class StretchShaderActivity extends Activity {
float uScrollX = mScrollX;
float uScrollY = mScrollY;
- mRuntimeShader.setUniform("uMaxStretchIntensity", mMaxStretchIntensity);
- mRuntimeShader.setUniform("uStretchAffectedDist", mStretchAffectedDistance);
- mRuntimeShader.setUniform("uDistanceStretchedX", distanceStretchedX);
- mRuntimeShader.setUniform("uDistanceStretchedY", distanceStretchedY);
- mRuntimeShader.setUniform("uDistDiffX", diffX);
- mRuntimeShader.setUniform("uDistDiffY", diffY);
- mRuntimeShader.setUniform("uOverscrollX", normOverScrollDistX);
- mRuntimeShader.setUniform("uOverscrollY", normOverScrollDistY);
- mRuntimeShader.setUniform("uScrollX", uScrollX);
- mRuntimeShader.setUniform("uScrollY", uScrollY);
- mRuntimeShader.setUniform("viewportWidth", width);
- mRuntimeShader.setUniform("viewportHeight", height);
+ mRuntimeShader.setFloatUniform("uMaxStretchIntensity", mMaxStretchIntensity);
+ mRuntimeShader.setFloatUniform("uStretchAffectedDist", mStretchAffectedDistance);
+ mRuntimeShader.setFloatUniform("uDistanceStretchedX", distanceStretchedX);
+ mRuntimeShader.setFloatUniform("uDistanceStretchedY", distanceStretchedY);
+ mRuntimeShader.setFloatUniform("uDistDiffX", diffX);
+ mRuntimeShader.setFloatUniform("uDistDiffY", diffY);
+ mRuntimeShader.setFloatUniform("uOverscrollX", normOverScrollDistX);
+ mRuntimeShader.setFloatUniform("uOverscrollY", normOverScrollDistY);
+ mRuntimeShader.setFloatUniform("uScrollX", uScrollX);
+ mRuntimeShader.setFloatUniform("uScrollY", uScrollY);
+ mRuntimeShader.setFloatUniform("viewportWidth", width);
+ mRuntimeShader.setFloatUniform("viewportHeight", height);
mImageView.setRenderEffect(RenderEffect.createShaderEffect(mRuntimeShader));
diff --git a/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java
index d03aee282ee1..4a724b72f5f9 100644
--- a/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnCellUnderlyingNetworkTemplateTest.java
@@ -15,12 +15,13 @@
*/
package android.net.vcn;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_ANY;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
import org.junit.Test;
@@ -32,26 +33,26 @@ public class VcnCellUnderlyingNetworkTemplateTest {
private static final Set<Integer> ALLOWED_CARRIER_IDS = new HashSet<>();
// Package private for use in VcnGatewayConnectionConfigTest
- static VcnCellUnderlyingNetworkTemplate getTestNetworkPriority() {
+ static VcnCellUnderlyingNetworkTemplate getTestNetworkTemplate() {
return new VcnCellUnderlyingNetworkTemplate.Builder()
.setNetworkQuality(NETWORK_QUALITY_OK)
- .setAllowMetered(true /* allowMetered */)
- .setAllowedOperatorPlmnIds(ALLOWED_PLMN_IDS)
- .setAllowedSpecificCarrierIds(ALLOWED_CARRIER_IDS)
- .setAllowRoaming(true /* allowRoaming */)
- .setRequireOpportunistic(true /* requireOpportunistic */)
+ .setMetered(MATCH_FORBIDDEN)
+ .setOperatorPlmnIds(ALLOWED_PLMN_IDS)
+ .setSimSpecificCarrierIds(ALLOWED_CARRIER_IDS)
+ .setRoaming(MATCH_FORBIDDEN)
+ .setOpportunistic(MATCH_REQUIRED)
.build();
}
@Test
public void testBuilderAndGetters() {
- final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkPriority();
+ final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
assertEquals(NETWORK_QUALITY_OK, networkPriority.getNetworkQuality());
- assertTrue(networkPriority.allowMetered());
- assertEquals(ALLOWED_PLMN_IDS, networkPriority.getAllowedOperatorPlmnIds());
- assertEquals(ALLOWED_CARRIER_IDS, networkPriority.getAllowedSpecificCarrierIds());
- assertTrue(networkPriority.allowRoaming());
- assertTrue(networkPriority.requireOpportunistic());
+ assertEquals(MATCH_FORBIDDEN, networkPriority.getMetered());
+ assertEquals(ALLOWED_PLMN_IDS, networkPriority.getOperatorPlmnIds());
+ assertEquals(ALLOWED_CARRIER_IDS, networkPriority.getSimSpecificCarrierIds());
+ assertEquals(MATCH_FORBIDDEN, networkPriority.getRoaming());
+ assertEquals(MATCH_REQUIRED, networkPriority.getOpportunistic());
}
@Test
@@ -59,16 +60,16 @@ public class VcnCellUnderlyingNetworkTemplateTest {
final VcnCellUnderlyingNetworkTemplate networkPriority =
new VcnCellUnderlyingNetworkTemplate.Builder().build();
assertEquals(NETWORK_QUALITY_ANY, networkPriority.getNetworkQuality());
- assertFalse(networkPriority.allowMetered());
- assertEquals(new HashSet<String>(), networkPriority.getAllowedOperatorPlmnIds());
- assertEquals(new HashSet<Integer>(), networkPriority.getAllowedSpecificCarrierIds());
- assertFalse(networkPriority.allowRoaming());
- assertFalse(networkPriority.requireOpportunistic());
+ assertEquals(MATCH_ANY, networkPriority.getMetered());
+ assertEquals(new HashSet<String>(), networkPriority.getOperatorPlmnIds());
+ assertEquals(new HashSet<Integer>(), networkPriority.getSimSpecificCarrierIds());
+ assertEquals(MATCH_ANY, networkPriority.getRoaming());
+ assertEquals(MATCH_ANY, networkPriority.getOpportunistic());
}
@Test
public void testPersistableBundle() {
- final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkPriority();
+ final VcnCellUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
assertEquals(
networkPriority,
VcnUnderlyingNetworkTemplate.fromPersistableBundle(
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index 1f2905da08f4..2aef9ae7ca32 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -17,8 +17,8 @@
package android.net.vcn;
import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
-import static android.net.vcn.VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_PRIORITIES;
-import static android.net.vcn.VcnGatewayConnectionConfig.UNDERLYING_NETWORK_PRIORITIES_KEY;
+import static android.net.vcn.VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES;
+import static android.net.vcn.VcnGatewayConnectionConfig.UNDERLYING_NETWORK_TEMPLATES_KEY;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -40,8 +40,9 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
import java.util.Arrays;
-import java.util.LinkedHashSet;
+import java.util.List;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
@@ -54,17 +55,17 @@ public class VcnGatewayConnectionConfigTest {
};
public static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN};
- private static final LinkedHashSet<VcnUnderlyingNetworkTemplate> UNDERLYING_NETWORK_PRIORITIES =
- new LinkedHashSet();
+ private static final List<VcnUnderlyingNetworkTemplate> UNDERLYING_NETWORK_TEMPLATES =
+ new ArrayList();
static {
Arrays.sort(EXPOSED_CAPS);
Arrays.sort(UNDERLYING_CAPS);
- UNDERLYING_NETWORK_PRIORITIES.add(
- VcnCellUnderlyingNetworkTemplateTest.getTestNetworkPriority());
- UNDERLYING_NETWORK_PRIORITIES.add(
- VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkPriority());
+ UNDERLYING_NETWORK_TEMPLATES.add(
+ VcnCellUnderlyingNetworkTemplateTest.getTestNetworkTemplate());
+ UNDERLYING_NETWORK_TEMPLATES.add(
+ VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkTemplate());
}
public static final long[] RETRY_INTERVALS_MS =
@@ -95,7 +96,7 @@ public class VcnGatewayConnectionConfigTest {
// Public for use in VcnGatewayConnectionTest
public static VcnGatewayConnectionConfig buildTestConfig() {
final VcnGatewayConnectionConfig.Builder builder =
- newBuilder().setVcnUnderlyingNetworkPriorities(UNDERLYING_NETWORK_PRIORITIES);
+ newBuilder().setVcnUnderlyingNetworkPriorities(UNDERLYING_NETWORK_TEMPLATES);
return buildTestConfigWithExposedCaps(builder, EXPOSED_CAPS);
}
@@ -174,10 +175,10 @@ public class VcnGatewayConnectionConfigTest {
}
@Test
- public void testBuilderRequiresNonNullNetworkPriorities() {
+ public void testBuilderRequiresNonNullNetworkTemplates() {
try {
newBuilder().setVcnUnderlyingNetworkPriorities(null);
- fail("Expected exception due to invalid underlyingNetworkPriorities");
+ fail("Expected exception due to invalid underlyingNetworkTemplates");
} catch (NullPointerException e) {
}
}
@@ -219,7 +220,7 @@ public class VcnGatewayConnectionConfigTest {
Arrays.sort(exposedCaps);
assertArrayEquals(EXPOSED_CAPS, exposedCaps);
- assertEquals(UNDERLYING_NETWORK_PRIORITIES, config.getVcnUnderlyingNetworkPriorities());
+ assertEquals(UNDERLYING_NETWORK_TEMPLATES, config.getVcnUnderlyingNetworkPriorities());
assertEquals(TUNNEL_CONNECTION_PARAMS, config.getTunnelConnectionParams());
assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis());
@@ -234,13 +235,13 @@ public class VcnGatewayConnectionConfigTest {
}
@Test
- public void testParsePersistableBundleWithoutVcnUnderlyingNetworkPriorities() {
+ public void testParsePersistableBundleWithoutVcnUnderlyingNetworkTemplates() {
PersistableBundle configBundle = buildTestConfig().toPersistableBundle();
- configBundle.putPersistableBundle(UNDERLYING_NETWORK_PRIORITIES_KEY, null);
+ configBundle.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, null);
final VcnGatewayConnectionConfig config = new VcnGatewayConnectionConfig(configBundle);
assertEquals(
- DEFAULT_UNDERLYING_NETWORK_PRIORITIES, config.getVcnUnderlyingNetworkPriorities());
+ DEFAULT_UNDERLYING_NETWORK_TEMPLATES, config.getVcnUnderlyingNetworkPriorities());
}
private static IkeTunnelConnectionParams buildTunnelConnectionParams(String ikePsk) {
@@ -285,39 +286,36 @@ public class VcnGatewayConnectionConfigTest {
assertNotEquals(config, anotherConfig);
}
- private static VcnGatewayConnectionConfig buildTestConfigWithVcnUnderlyingNetworkPriorities(
- LinkedHashSet<VcnUnderlyingNetworkTemplate> networkPriorities) {
+ private static VcnGatewayConnectionConfig buildTestConfigWithVcnUnderlyingNetworkTemplates(
+ List<VcnUnderlyingNetworkTemplate> networkTemplates) {
return buildTestConfigWithExposedCaps(
new VcnGatewayConnectionConfig.Builder(
- "buildTestConfigWithVcnUnderlyingNetworkPriorities",
+ "buildTestConfigWithVcnUnderlyingNetworkTemplates",
TUNNEL_CONNECTION_PARAMS)
- .setVcnUnderlyingNetworkPriorities(networkPriorities),
+ .setVcnUnderlyingNetworkPriorities(networkTemplates),
EXPOSED_CAPS);
}
@Test
- public void testVcnUnderlyingNetworkPrioritiesEquality() throws Exception {
+ public void testVcnUnderlyingNetworkTemplatesEquality() throws Exception {
final VcnGatewayConnectionConfig config =
- buildTestConfigWithVcnUnderlyingNetworkPriorities(UNDERLYING_NETWORK_PRIORITIES);
+ buildTestConfigWithVcnUnderlyingNetworkTemplates(UNDERLYING_NETWORK_TEMPLATES);
- final LinkedHashSet<VcnUnderlyingNetworkTemplate> networkPrioritiesEqual =
- new LinkedHashSet();
- networkPrioritiesEqual.add(VcnCellUnderlyingNetworkTemplateTest.getTestNetworkPriority());
- networkPrioritiesEqual.add(VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkPriority());
+ final List<VcnUnderlyingNetworkTemplate> networkTemplatesEqual = new ArrayList();
+ networkTemplatesEqual.add(VcnCellUnderlyingNetworkTemplateTest.getTestNetworkTemplate());
+ networkTemplatesEqual.add(VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkTemplate());
final VcnGatewayConnectionConfig configEqual =
- buildTestConfigWithVcnUnderlyingNetworkPriorities(networkPrioritiesEqual);
+ buildTestConfigWithVcnUnderlyingNetworkTemplates(networkTemplatesEqual);
- final LinkedHashSet<VcnUnderlyingNetworkTemplate> networkPrioritiesNotEqual =
- new LinkedHashSet();
- networkPrioritiesNotEqual.add(
- VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkPriority());
+ final List<VcnUnderlyingNetworkTemplate> networkTemplatesNotEqual = new ArrayList();
+ networkTemplatesNotEqual.add(VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkTemplate());
final VcnGatewayConnectionConfig configNotEqual =
- buildTestConfigWithVcnUnderlyingNetworkPriorities(networkPrioritiesNotEqual);
+ buildTestConfigWithVcnUnderlyingNetworkTemplates(networkTemplatesNotEqual);
- assertEquals(UNDERLYING_NETWORK_PRIORITIES, networkPrioritiesEqual);
+ assertEquals(UNDERLYING_NETWORK_TEMPLATES, networkTemplatesEqual);
assertEquals(config, configEqual);
- assertNotEquals(UNDERLYING_NETWORK_PRIORITIES, networkPrioritiesNotEqual);
+ assertNotEquals(UNDERLYING_NETWORK_TEMPLATES, networkTemplatesNotEqual);
assertNotEquals(config, configNotEqual);
}
}
diff --git a/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java b/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java
index 652057fd48c7..cb5b47bbdc15 100644
--- a/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplateTest.java
@@ -15,36 +15,38 @@
*/
package android.net.vcn;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_ANY;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
+import java.util.Set;
+
public class VcnWifiUnderlyingNetworkTemplateTest {
private static final String SSID = "TestWifi";
private static final int INVALID_NETWORK_QUALITY = -1;
// Package private for use in VcnGatewayConnectionConfigTest
- static VcnWifiUnderlyingNetworkTemplate getTestNetworkPriority() {
+ static VcnWifiUnderlyingNetworkTemplate getTestNetworkTemplate() {
return new VcnWifiUnderlyingNetworkTemplate.Builder()
.setNetworkQuality(NETWORK_QUALITY_OK)
- .setAllowMetered(true /* allowMetered */)
- .setSsid(SSID)
+ .setMetered(MATCH_FORBIDDEN)
+ .setSsids(Set.of(SSID))
.build();
}
@Test
public void testBuilderAndGetters() {
- final VcnWifiUnderlyingNetworkTemplate networkPriority = getTestNetworkPriority();
+ final VcnWifiUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
assertEquals(NETWORK_QUALITY_OK, networkPriority.getNetworkQuality());
- assertTrue(networkPriority.allowMetered());
- assertEquals(SSID, networkPriority.getSsid());
+ assertEquals(MATCH_FORBIDDEN, networkPriority.getMetered());
+ assertEquals(Set.of(SSID), networkPriority.getSsids());
}
@Test
@@ -52,8 +54,8 @@ public class VcnWifiUnderlyingNetworkTemplateTest {
final VcnWifiUnderlyingNetworkTemplate networkPriority =
new VcnWifiUnderlyingNetworkTemplate.Builder().build();
assertEquals(NETWORK_QUALITY_ANY, networkPriority.getNetworkQuality());
- assertFalse(networkPriority.allowMetered());
- assertNull(SSID, networkPriority.getSsid());
+ assertEquals(MATCH_ANY, networkPriority.getMetered());
+ assertTrue(networkPriority.getSsids().isEmpty());
}
@Test
@@ -68,7 +70,7 @@ public class VcnWifiUnderlyingNetworkTemplateTest {
@Test
public void testPersistableBundle() {
- final VcnWifiUnderlyingNetworkTemplate networkPriority = getTestNetworkPriority();
+ final VcnWifiUnderlyingNetworkTemplate networkPriority = getTestNetworkTemplate();
assertEquals(
networkPriority,
VcnUnderlyingNetworkTemplate.fromPersistableBundle(
diff --git a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
index f23d5bf67ebf..4bb7de8c1fef 100644
--- a/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/NetworkPriorityClassifierTest.java
@@ -16,6 +16,8 @@
package com.android.server.vcn.routeselection;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.NETWORK_QUALITY_OK;
import static com.android.server.vcn.VcnTestUtils.setupSystemService;
@@ -145,7 +147,7 @@ public class NetworkPriorityClassifierTest {
final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
new VcnWifiUnderlyingNetworkTemplate.Builder()
.setNetworkQuality(NETWORK_QUALITY_OK)
- .setAllowMetered(false /* allowMetered */)
+ .setMetered(MATCH_FORBIDDEN)
.build();
assertFalse(
@@ -164,7 +166,6 @@ public class NetworkPriorityClassifierTest {
final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
new VcnWifiUnderlyingNetworkTemplate.Builder()
.setNetworkQuality(NETWORK_QUALITY_OK)
- .setAllowMetered(true /* allowMetered */)
.build();
final UnderlyingNetworkRecord selectedNetworkRecord =
isSelectedNetwork ? mWifiNetworkRecord : null;
@@ -214,8 +215,7 @@ public class NetworkPriorityClassifierTest {
final VcnWifiUnderlyingNetworkTemplate wifiNetworkPriority =
new VcnWifiUnderlyingNetworkTemplate.Builder()
.setNetworkQuality(NETWORK_QUALITY_OK)
- .setAllowMetered(true /* allowMetered */)
- .setSsid(nwPrioritySsid)
+ .setSsids(Set.of(nwPrioritySsid))
.build();
assertEquals(
@@ -238,10 +238,7 @@ public class NetworkPriorityClassifierTest {
}
private static VcnCellUnderlyingNetworkTemplate.Builder getCellNetworkPriorityBuilder() {
- return new VcnCellUnderlyingNetworkTemplate.Builder()
- .setNetworkQuality(NETWORK_QUALITY_OK)
- .setAllowMetered(true /* allowMetered */)
- .setAllowRoaming(true /* allowRoaming */);
+ return new VcnCellUnderlyingNetworkTemplate.Builder().setNetworkQuality(NETWORK_QUALITY_OK);
}
@Test
@@ -258,9 +255,7 @@ public class NetworkPriorityClassifierTest {
@Test
public void testMatchOpportunisticCell() {
final VcnCellUnderlyingNetworkTemplate opportunisticCellNetworkPriority =
- getCellNetworkPriorityBuilder()
- .setRequireOpportunistic(true /* requireOpportunistic */)
- .build();
+ getCellNetworkPriorityBuilder().setOpportunistic(MATCH_REQUIRED).build();
when(mSubscriptionSnapshot.isOpportunistic(SUB_ID)).thenReturn(true);
when(mSubscriptionSnapshot.getAllSubIdsInGroup(SUB_GROUP)).thenReturn(new ArraySet<>());
@@ -279,7 +274,7 @@ public class NetworkPriorityClassifierTest {
final String networkPriorityPlmnId = useMatchedPlmnId ? PLMN_ID : PLMN_ID_OTHER;
final VcnCellUnderlyingNetworkTemplate networkPriority =
getCellNetworkPriorityBuilder()
- .setAllowedOperatorPlmnIds(Set.of(networkPriorityPlmnId))
+ .setOperatorPlmnIds(Set.of(networkPriorityPlmnId))
.build();
assertEquals(
@@ -308,7 +303,7 @@ public class NetworkPriorityClassifierTest {
final int networkPriorityCarrierId = useMatchedCarrierId ? CARRIER_ID : CARRIER_ID_OTHER;
final VcnCellUnderlyingNetworkTemplate networkPriority =
getCellNetworkPriorityBuilder()
- .setAllowedSpecificCarrierIds(Set.of(networkPriorityCarrierId))
+ .setSimSpecificCarrierIds(Set.of(networkPriorityCarrierId))
.build();
assertEquals(
@@ -336,7 +331,7 @@ public class NetworkPriorityClassifierTest {
@Test
public void testMatchWifiFailWithoutNotRoamingBit() {
final VcnCellUnderlyingNetworkTemplate networkPriority =
- getCellNetworkPriorityBuilder().setAllowRoaming(false /* allowRoaming */).build();
+ getCellNetworkPriorityBuilder().setRoaming(MATCH_FORBIDDEN).build();
assertFalse(
checkMatchesCellPriorityRule(
@@ -353,7 +348,7 @@ public class NetworkPriorityClassifierTest {
calculatePriorityClass(
mVcnContext,
networkRecord,
- VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_PRIORITIES,
+ VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
SUB_GROUP,
mSubscriptionSnapshot,
null /* currentlySelected */,
diff --git a/tools/aapt2/cmd/Compile_test.cpp b/tools/aapt2/cmd/Compile_test.cpp
index 89757134f3a7..fbfbf68b30bb 100644
--- a/tools/aapt2/cmd/Compile_test.cpp
+++ b/tools/aapt2/cmd/Compile_test.cpp
@@ -19,12 +19,11 @@
#include "android-base/file.h"
#include "android-base/stringprintf.h"
#include "android-base/utf8.h"
-
+#include "format/proto/ProtoDeserialize.h"
#include "io/StringStream.h"
#include "io/ZipArchive.h"
#include "java/AnnotationProcessor.h"
#include "test/Test.h"
-#include "format/proto/ProtoDeserialize.h"
namespace aapt {
@@ -59,55 +58,56 @@ TEST_F(CompilerTest, MultiplePeriods) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
const std::string kResDir = BuildPath({android::base::Dirname(android::base::GetExecutablePath()),
"integration-tests", "CompileTest", "res"});
+ const std::string kOutDir = testing::TempDir();
// Resource files without periods in the file name should not throw errors
const std::string path0 = BuildPath({kResDir, "values", "values.xml"});
- const std::string path0_out = BuildPath({kResDir, "values_values.arsc.flat"});
+ const std::string path0_out = BuildPath({kOutDir, "values_values.arsc.flat"});
::android::base::utf8::unlink(path0_out.c_str());
- ASSERT_EQ(TestCompile(path0, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_EQ(TestCompile(path0, kOutDir, /** legacy */ false, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path0_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path0, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path0, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path0_out.c_str()), 0);
const std::string path1 = BuildPath({kResDir, "drawable", "image.png"});
- const std::string path1_out = BuildPath({kResDir, "drawable_image.png.flat"});
+ const std::string path1_out = BuildPath({kOutDir, "drawable_image.png.flat"});
::android::base::utf8::unlink(path1_out.c_str());
- ASSERT_EQ(TestCompile(path1, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_EQ(TestCompile(path1, kOutDir, /** legacy */ false, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path1_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path1, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path1, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path1_out.c_str()), 0);
const std::string path2 = BuildPath({kResDir, "drawable", "image.9.png"});
- const std::string path2_out = BuildPath({kResDir, "drawable_image.9.png.flat"});
+ const std::string path2_out = BuildPath({kOutDir, "drawable_image.9.png.flat"});
::android::base::utf8::unlink(path2_out.c_str());
- ASSERT_EQ(TestCompile(path2, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_EQ(TestCompile(path2, kOutDir, /** legacy */ false, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path2_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path2, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path2, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path2_out.c_str()), 0);
// Resource files with periods in the file name should fail on non-legacy compilations
const std::string path3 = BuildPath({kResDir, "values", "values.all.xml"});
- const std::string path3_out = BuildPath({kResDir, "values_values.all.arsc.flat"});
+ const std::string path3_out = BuildPath({kOutDir, "values_values.all.arsc.flat"});
::android::base::utf8::unlink(path3_out.c_str());
- ASSERT_NE(TestCompile(path3, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_NE(TestCompile(path3, kOutDir, /** legacy */ false, diag), 0);
ASSERT_NE(::android::base::utf8::unlink(path3_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path3, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path3, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path3_out.c_str()), 0);
const std::string path4 = BuildPath({kResDir, "drawable", "image.small.png"});
- const std::string path4_out = BuildPath({kResDir, "drawable_image.small.png.flat"});
+ const std::string path4_out = BuildPath({kOutDir, "drawable_image.small.png.flat"});
::android::base::utf8::unlink(path4_out.c_str());
- ASSERT_NE(TestCompile(path4, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_NE(TestCompile(path4, kOutDir, /** legacy */ false, diag), 0);
ASSERT_NE(::android::base::utf8::unlink(path4_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path4, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path4, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path4_out.c_str()), 0);
const std::string path5 = BuildPath({kResDir, "drawable", "image.small.9.png"});
- const std::string path5_out = BuildPath({kResDir, "drawable_image.small.9.png.flat"});
+ const std::string path5_out = BuildPath({kOutDir, "drawable_image.small.9.png.flat"});
::android::base::utf8::unlink(path5_out.c_str());
- ASSERT_NE(TestCompile(path5, kResDir, /** legacy */ false, diag), 0);
+ ASSERT_NE(TestCompile(path5, kOutDir, /** legacy */ false, diag), 0);
ASSERT_NE(::android::base::utf8::unlink(path5_out.c_str()), 0);
- ASSERT_EQ(TestCompile(path5, kResDir, /** legacy */ true, diag), 0);
+ ASSERT_EQ(TestCompile(path5, kOutDir, /** legacy */ true, diag), 0);
ASSERT_EQ(::android::base::utf8::unlink(path5_out.c_str()), 0);
}
@@ -116,9 +116,7 @@ TEST_F(CompilerTest, DirInput) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
const std::string kResDir = BuildPath({android::base::Dirname(android::base::GetExecutablePath()),
"integration-tests", "CompileTest", "DirInput", "res"});
- const std::string kOutputFlata =
- BuildPath({android::base::Dirname(android::base::GetExecutablePath()), "integration-tests",
- "CompileTest", "DirInput", "compiled.flata"});
+ const std::string kOutputFlata = BuildPath({testing::TempDir(), "compiled.flata"});
::android::base::utf8::unlink(kOutputFlata.c_str());
std::vector<android::StringPiece> args;
@@ -147,9 +145,7 @@ TEST_F(CompilerTest, ZipInput) {
const std::string kResZip =
BuildPath({android::base::Dirname(android::base::GetExecutablePath()), "integration-tests",
"CompileTest", "ZipInput", "res.zip"});
- const std::string kOutputFlata =
- BuildPath({android::base::Dirname(android::base::GetExecutablePath()), "integration-tests",
- "CompileTest", "ZipInput", "compiled.flata"});
+ const std::string kOutputFlata = BuildPath({testing::TempDir(), "compiled.flata"});
::android::base::utf8::unlink(kOutputFlata.c_str());
@@ -257,9 +253,9 @@ TEST_F(CompilerTest, DoNotTranslateTest) {
TEST_F(CompilerTest, RelativePathTest) {
StdErrDiagnostics diag;
- const std::string res_path = BuildPath(
- {android::base::Dirname(android::base::GetExecutablePath()),
- "integration-tests", "CompileTest", "res"});
+ const std::string res_path =
+ BuildPath({android::base::Dirname(android::base::GetExecutablePath()), "integration-tests",
+ "CompileTest", "res"});
const std::string path_values_colors = GetTestPath("values/colors.xml");
WriteFile(path_values_colors, "<resources>"
@@ -272,9 +268,8 @@ TEST_F(CompilerTest, RelativePathTest) {
"<TextBox android:id=\"@+id/text_one\" android:background=\"@color/color_one\"/>"
"</LinearLayout>");
- const std::string compiled_files_dir = BuildPath(
- {android::base::Dirname(android::base::GetExecutablePath()),
- "integration-tests", "CompileTest", "compiled"});
+ const std::string compiled_files_dir =
+ BuildPath({testing::TempDir(), "integration-tests", "CompileTest", "compiled"});
CHECK(file::mkdirs(compiled_files_dir.data()));
const std::string path_values_colors_out =
@@ -283,9 +278,8 @@ TEST_F(CompilerTest, RelativePathTest) {
BuildPath({compiled_files_dir, "layout_layout_one.flat"});
::android::base::utf8::unlink(path_values_colors_out.c_str());
::android::base::utf8::unlink(path_layout_layout_one_out.c_str());
- const std::string apk_path = BuildPath(
- {android::base::Dirname(android::base::GetExecutablePath()),
- "integration-tests", "CompileTest", "out.apk"});
+ const std::string apk_path =
+ BuildPath({testing::TempDir(), "integration-tests", "CompileTest", "out.apk"});
const std::string source_set_res = BuildPath({"main", "res"});
const std::string relative_path_values_colors =
diff --git a/tools/aapt2/test/Fixture.cpp b/tools/aapt2/test/Fixture.cpp
index e2f71dc45075..ddc1853ca13c 100644
--- a/tools/aapt2/test/Fixture.cpp
+++ b/tools/aapt2/test/Fixture.cpp
@@ -67,8 +67,7 @@ void ClearDirectory(const android::StringPiece& path) {
}
void TestDirectoryFixture::SetUp() {
- temp_dir_ = file::BuildPath({android::base::GetExecutableDirectory(),
- "_temp",
+ temp_dir_ = file::BuildPath({testing::TempDir(), "_temp",
testing::UnitTest::GetInstance()->current_test_case()->name(),
testing::UnitTest::GetInstance()->current_test_info()->name()});
ASSERT_TRUE(file::mkdirs(temp_dir_));
@@ -236,4 +235,4 @@ std::vector<std::string> LinkCommandBuilder::Build(const std::string& out_apk) {
return args_;
}
-} // namespace aapt \ No newline at end of file
+} // namespace aapt
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index fe2b0186c57f..3131f5687c6a 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -57,6 +57,7 @@ LANG_TO_SCRIPT = {
'sk': 'Latn',
'sl': 'Latn',
'sq': 'Latn',
+ 'sv': 'Latn',
'ta': 'Taml',
'te': 'Telu',
'tk': 'Latn',